use crate::{HighlightStyles, InlayId};use collections::BTreeSet;use language::{Chunk, Edit, Point, TextSummary};use multi_buffer::{Anchor, MultiBufferRow, MultiBufferRows, MultiBufferSnapshot, ToOffset};use std::{ cmp, ops::{Add, AddAssign, Range, Sub, SubAssign},};use sum_tree::{Bias, Cursor, SumTree};use text::{Patch, Rope}; use super::{custom_highlights::CustomHighlightsChunks, Highlights}; /// Decides where the [`Inlay`]s should be displayed.////// See the [`display_map` module documentation](crate::display_map) for more information.pub struct InlayMap { snapshot: InlaySnapshot, inlays: Vec<Inlay>,} #[derive(Clone)]pub struct InlaySnapshot { pub buffer: MultiBufferSnapshot, transforms: SumTree<Transform>, pub version: usize,} #[derive(Clone, Debug)]enum Transform { Isomorphic(TextSummary), Inlay(Inlay),} #[derive(Debug, Clone)]pub struct Inlay { pub(crate) id: InlayId, pub position: Anchor, pub text: text::Rope,} impl Inlay { pub fn hint(id: usize, position: Anchor, hint: &project::InlayHint) -> Self { let mut text = hint.text(); if hint.padding_right && !text.ends_with(' ') { text.push(' '); } if hint.padding_left && !text.starts_with(' ') { text.insert(0, ' '); } Self { id: InlayId::Hint(id), position, text: text.into(), } } pub fn inline_completion<T: Into<Rope>>(id: usize, position: Anchor, text: T) -> Self { Self { id: InlayId::InlineCompletion(id), position, text: text.into(), } }} impl sum_tree::Item for Transform { type Summary = TransformSummary; fn summary(&self, _cx: &()) -> Self::Summary { match self { Transform::Isomorphic(summary) => TransformSummary { input: summary.clone(), output: summary.clone(), }, Transform::Inlay(inlay) => TransformSummary { input: TextSummary::default(), output: inlay.text.summary(), }, } }} #[derive(Clone, Debug, Default)]struct TransformSummary { input: TextSummary, output: TextSummary,} impl sum_tree::Summary for TransformSummary { type Context = (); fn zero(_cx: &()) -> Self { Default::default() } fn add_summary(&mut self, other: &Self, _: &()) { self.input += &other.input; self.output += &other.output; }} pub type InlayEdit = Edit<InlayOffset>; #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]pub struct InlayOffset(pub usize); impl Add for InlayOffset { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Self(self.0 + rhs.0) }} impl Sub for InlayOffset { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Self(self.0 - rhs.0) }} impl AddAssign for InlayOffset { fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0; }} impl SubAssign for InlayOffset { fn sub_assign(&mut self, rhs: Self) { self.0 -= rhs.0; }} impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayOffset { fn zero(_cx: &()) -> Self { Default::default() } fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) { self.0 += &summary.output.len; }} #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]pub struct InlayPoint(pub Point); impl Add for InlayPoint { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Self(self.0 + rhs.0) }} impl Sub for InlayPoint { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Self(self.0 - rhs.0) }} impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayPoint { fn zero(_cx: &()) -> Self { Default::default() } fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) { self.0 += &summary.output.lines; }} impl<'a> sum_tree::Dimension<'a, TransformSummary> for usize { fn zero(_cx: &()) -> Self { Default::default() } fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) { *self += &summary.input.len; }} impl<'a> sum_tree::Dimension<'a, TransformSummary> for Point { fn zero(_cx: &()) -> Self { Default::default() } fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) { *self += &summary.input.lines; }} #[derive(Clone)]pub struct InlayBufferRows<'a> { transforms: Cursor<'a, Transform, (InlayPoint, Point)>, buffer_rows: MultiBufferRows<'a>, inlay_row: u32, max_buffer_row: MultiBufferRow,} pub struct InlayChunks<'a> { transforms: Cursor<'a, Transform, (InlayOffset, usize)>, buffer_chunks: CustomHighlightsChunks<'a>, buffer_chunk: Option<Chunk<'a>>, inlay_chunks: Option<text::Chunks<'a>>, inlay_chunk: Option<&'a str>, output_offset: InlayOffset, max_output_offset: InlayOffset, highlight_styles: HighlightStyles, highlights: Highlights<'a>, snapshot: &'a InlaySnapshot,} impl<'a> InlayChunks<'a> { pub fn seek(&mut self, new_range: Range<InlayOffset>) { self.transforms.seek(&new_range.start, Bias::Right, &()); let buffer_range = self.snapshot.to_buffer_offset(new_range.start) ..self.snapshot.to_buffer_offset(new_range.end); self.buffer_chunks.seek(buffer_range); self.inlay_chunks = None; self.buffer_chunk = None; self.output_offset = new_range.start; self.max_output_offset = new_range.end; } pub fn offset(&self) -> InlayOffset { self.output_offset }} impl<'a> Iterator for InlayChunks<'a> { type Item = Chunk<'a>; fn next(&mut self) -> Option<Self::Item> { if self.output_offset == self.max_output_offset { return None; } let chunk = match self.transforms.item()? { Transform::Isomorphic(_) => { let chunk = self .buffer_chunk .get_or_insert_with(|| self.buffer_chunks.next().unwrap()); if chunk.text.is_empty() { *chunk = self.buffer_chunks.next().unwrap(); } let (prefix, suffix) = chunk.text.split_at( chunk .text .len() .min(self.transforms.end(&()).0 .0 - self.output_offset.0), ); chunk.text = suffix; self.output_offset.0 += prefix.len(); Chunk { text: prefix, ..chunk.clone() } } Transform::Inlay(inlay) => { let mut inlay_style_and_highlight = None; if let Some(inlay_highlights) = self.highlights.inlay_highlights { for (_, inlay_id_to_data) in inlay_highlights.iter() { let style_and_highlight = inlay_id_to_data.get(&inlay.id); if style_and_highlight.is_some() { inlay_style_and_highlight = style_and_highlight; break; } } } let mut highlight_style = match inlay.id { InlayId::InlineCompletion(_) => { self.highlight_styles.inline_completion.map(|s| { if inlay.text.chars().all(|c| c.is_whitespace()) { s.whitespace } else { s.insertion } }) } InlayId::Hint(_) => self.highlight_styles.inlay_hint, }; let next_inlay_highlight_endpoint; let offset_in_inlay = self.output_offset - self.transforms.start().0; if let Some((style, highlight)) = inlay_style_and_highlight { let range = &highlight.range; if offset_in_inlay.0 < range.start { next_inlay_highlight_endpoint = range.start - offset_in_inlay.0; } else if offset_in_inlay.0 >= range.end { next_inlay_highlight_endpoint = usize::MAX; } else { next_inlay_highlight_endpoint = range.end - offset_in_inlay.0; highlight_style .get_or_insert_with(Default::default) .highlight(*style); } } else { next_inlay_highlight_endpoint = usize::MAX; } let inlay_chunks = self.inlay_chunks.get_or_insert_with(|| { let start = offset_in_inlay; let end = cmp::min(self.max_output_offset, self.transforms.end(&()).0) - self.transforms.start().0; inlay.text.chunks_in_range(start.0..end.0) }); let inlay_chunk = self .inlay_chunk .get_or_insert_with(|| inlay_chunks.next().unwrap()); let (chunk, remainder) = inlay_chunk.split_at(inlay_chunk.len().min(next_inlay_highlight_endpoint)); *inlay_chunk = remainder; if inlay_chunk.is_empty() { self.inlay_chunk = None; } self.output_offset.0 += chunk.len(); Chunk { text: chunk, highlight_style, ..Default::default() } } }; if self.output_offset == self.transforms.end(&()).0 { self.inlay_chunks = None; self.transforms.next(&()); } Some(chunk) }} impl<'a> InlayBufferRows<'a> { pub fn seek(&mut self, row: u32) { let inlay_point = InlayPoint::new(row, 0); self.transforms.seek(&inlay_point, Bias::Left, &()); let mut buffer_point = self.transforms.start().1; let buffer_row = MultiBufferRow(if row == 0 { 0 } else { match self.transforms.item() { Some(Transform::Isomorphic(_)) => { buffer_point += inlay_point.0 - self.transforms.start().0 .0; buffer_point.row } _ => cmp::min(buffer_point.row + 1, self.max_buffer_row.0), } }); self.inlay_row = inlay_point.row(); self.buffer_rows.seek(buffer_row); }} impl<'a> Iterator for InlayBufferRows<'a> { type Item = Option<u32>; fn next(&mut self) -> Option<Self::Item> { let buffer_row = if self.inlay_row == 0 { self.buffer_rows.next().unwrap() } else { match self.transforms.item()? { Transform::Inlay(_) => None, Transform::Isomorphic(_) => self.buffer_rows.next().unwrap(), } }; self.inlay_row += 1; self.transforms .seek_forward(&InlayPoint::new(self.inlay_row, 0), Bias::Left, &()); Some(buffer_row) }} impl InlayPoint { pub fn new(row: u32, column: u32) -> Self { Self(Point::new(row, column)) } pub fn row(self) -> u32 { self.0.row }} impl InlayMap { pub fn new(buffer: MultiBufferSnapshot) -> (Self, InlaySnapshot) { let version = 0; let snapshot = InlaySnapshot { buffer: buffer.clone(), transforms: SumTree::from_iter(Some(Transform::Isomorphic(buffer.text_summary())), &()), version, }; ( Self { snapshot: snapshot.clone(), inlays: Vec::new(), }, snapshot, ) } pub fn sync( &mut self, buffer_snapshot: MultiBufferSnapshot, mut buffer_edits: Vec<text::Edit<usize>>, ) -> (InlaySnapshot, Vec<InlayEdit>) { let snapshot = &mut self.snapshot; if buffer_edits.is_empty() && snapshot.buffer.trailing_excerpt_update_count() != buffer_snapshot.trailing_excerpt_update_count() { buffer_edits.push(Edit { old: snapshot.buffer.len()..snapshot.buffer.len(), new: buffer_snapshot.len()..buffer_snapshot.len(), }); } if buffer_edits.is_empty() { if snapshot.buffer.edit_count() != buffer_snapshot.edit_count() || snapshot.buffer.non_text_state_update_count() != buffer_snapshot.non_text_state_update_count() || snapshot.buffer.trailing_excerpt_update_count() != buffer_snapshot.trailing_excerpt_update_count() { snapshot.version += 1; } snapshot.buffer = buffer_snapshot; (snapshot.clone(), Vec::new()) } else { let mut inlay_edits = Patch::default(); let mut new_transforms = SumTree::default(); let mut cursor = snapshot.transforms.cursor::<(usize, InlayOffset)>(&()); let mut buffer_edits_iter = buffer_edits.iter().peekable(); while let Some(buffer_edit) = buffer_edits_iter.next() { new_transforms.append(cursor.slice(&buffer_edit.old.start, Bias::Left, &()), &()); if let Some(Transform::Isomorphic(transform)) = cursor.item() { if cursor.end(&()).0 == buffer_edit.old.start { push_isomorphic(&mut new_transforms, transform.clone()); cursor.next(&()); } } // Remove all the inlays and transforms contained by the edit. let old_start = cursor.start().1 + InlayOffset(buffer_edit.old.start - cursor.start().0); cursor.seek(&buffer_edit.old.end, Bias::Right, &()); let old_end = cursor.start().1 + InlayOffset(buffer_edit.old.end - cursor.start().0); // Push the unchanged prefix. let prefix_start = new_transforms.summary().input.len; let prefix_end = buffer_edit.new.start; push_isomorphic( &mut new_transforms, buffer_snapshot.text_summary_for_range(prefix_start..prefix_end), ); let new_start = InlayOffset(new_transforms.summary().output.len); let start_ix = match self.inlays.binary_search_by(|probe| { probe .position .to_offset(&buffer_snapshot) .cmp(&buffer_edit.new.start) .then(std::cmp::Ordering::Greater) }) { Ok(ix) | Err(ix) => ix, }; for inlay in &self.inlays[start_ix..] { let buffer_offset = inlay.position.to_offset(&buffer_snapshot); if buffer_offset > buffer_edit.new.end { break; } let prefix_start = new_transforms.summary().input.len; let prefix_end = buffer_offset; push_isomorphic( &mut new_transforms, buffer_snapshot.text_summary_for_range(prefix_start..prefix_end), ); if inlay.position.is_valid(&buffer_snapshot) { new_transforms.push(Transform::Inlay(inlay.clone()), &()); } } // Apply the rest of the edit.Lines 1–500 of 1795. Load more
use crate::{HighlightStyles, InlayId}; use collections::BTreeSet; use language::{Chunk, Edit, Point, TextSummary}; use multi_buffer::{Anchor, MultiBufferRow, MultiBufferRows, MultiBufferSnapshot, ToOffset}; use std::{ cmp, ops::{Add, AddAssign, Range, Sub, SubAssign}, }; use sum_tree::{Bias, Cursor, SumTree}; use text::{Patch, Rope}; use super::{custom_highlights::CustomHighlightsChunks, Highlights}; /// Decides where the [`Inlay`]s should be displayed. /// /// See the [`display_map` module documentation](crate::display_map) for more information. pub struct InlayMap { snapshot: InlaySnapshot, inlays: Vec<Inlay>, } #[derive(Clone)] pub struct InlaySnapshot { pub buffer: MultiBufferSnapshot, transforms: SumTree<Transform>, pub version: usize, } #[derive(Clone, Debug)] enum Transform { Isomorphic(TextSummary), Inlay(Inlay), } #[derive(Debug, Clone)] pub struct Inlay { pub(crate) id: InlayId, pub position: Anchor, pub text: text::Rope, } impl Inlay { pub fn hint(id: usize, position: Anchor, hint: &project::InlayHint) -> Self { let mut text = hint.text(); if hint.padding_right && !text.ends_with(' ') { text.push(' '); } if hint.padding_left && !text.starts_with(' ') { text.insert(0, ' '); } Self { id: InlayId::Hint(id), position, text: text.into(), } } pub fn inline_completion<T: Into<Rope>>(id: usize, position: Anchor, text: T) -> Self { Self { id: InlayId::InlineCompletion(id), position, text: text.into(), } } } impl sum_tree::Item for Transform { type Summary = TransformSummary; fn summary(&self, _cx: &()) -> Self::Summary { match self { Transform::Isomorphic(summary) => TransformSummary { input: summary.clone(), output: summary.clone(), }, Transform::Inlay(inlay) => TransformSummary { input: TextSummary::default(), output: inlay.text.summary(), }, } } } #[derive(Clone, Debug, Default)] struct TransformSummary { input: TextSummary, output: TextSummary, } impl sum_tree::Summary for TransformSummary { type Context = (); fn zero(_cx: &()) -> Self { Default::default() } fn add_summary(&mut self, other: &Self, _: &()) { self.input += &other.input; self.output += &other.output; } } pub type InlayEdit = Edit<InlayOffset>; #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] pub struct InlayOffset(pub usize); impl Add for InlayOffset { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Self(self.0 + rhs.0) } } impl Sub for InlayOffset { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Self(self.0 - rhs.0) } } impl AddAssign for InlayOffset { fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0; } } impl SubAssign for InlayOffset { fn sub_assign(&mut self, rhs: Self) { self.0 -= rhs.0; } } impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayOffset { fn zero(_cx: &()) -> Self { Default::default() } fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) { self.0 += &summary.output.len; } } #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] pub struct InlayPoint(pub Point); impl Add for InlayPoint { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Self(self.0 + rhs.0) } } impl Sub for InlayPoint { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Self(self.0 - rhs.0) } } impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayPoint { fn zero(_cx: &()) -> Self { Default::default() } fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) { self.0 += &summary.output.lines; } } impl<'a> sum_tree::Dimension<'a, TransformSummary> for usize { fn zero(_cx: &()) -> Self { Default::default() } fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) { *self += &summary.input.len; } } impl<'a> sum_tree::Dimension<'a, TransformSummary> for Point { fn zero(_cx: &()) -> Self { Default::default() } fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) { *self += &summary.input.lines; } } #[derive(Clone)] pub struct InlayBufferRows<'a> { transforms: Cursor<'a, Transform, (InlayPoint, Point)>, buffer_rows: MultiBufferRows<'a>, inlay_row: u32, max_buffer_row: MultiBufferRow, } pub struct InlayChunks<'a> { transforms: Cursor<'a, Transform, (InlayOffset, usize)>, buffer_chunks: CustomHighlightsChunks<'a>, buffer_chunk: Option<Chunk<'a>>, inlay_chunks: Option<text::Chunks<'a>>, inlay_chunk: Option<&'a str>, output_offset: InlayOffset, max_output_offset: InlayOffset, highlight_styles: HighlightStyles, highlights: Highlights<'a>, snapshot: &'a InlaySnapshot, } impl<'a> InlayChunks<'a> { pub fn seek(&mut self, new_range: Range<InlayOffset>) { self.transforms.seek(&new_range.start, Bias::Right, &()); let buffer_range = self.snapshot.to_buffer_offset(new_range.start) ..self.snapshot.to_buffer_offset(new_range.end); self.buffer_chunks.seek(buffer_range); self.inlay_chunks = None; self.buffer_chunk = None; self.output_offset = new_range.start; self.max_output_offset = new_range.end; } pub fn offset(&self) -> InlayOffset { self.output_offset } } impl<'a> Iterator for InlayChunks<'a> { type Item = Chunk<'a>; fn next(&mut self) -> Option<Self::Item> { if self.output_offset == self.max_output_offset { return None; } let chunk = match self.transforms.item()? { Transform::Isomorphic(_) => { let chunk = self .buffer_chunk .get_or_insert_with(|| self.buffer_chunks.next().unwrap()); if chunk.text.is_empty() { *chunk = self.buffer_chunks.next().unwrap(); } let (prefix, suffix) = chunk.text.split_at( chunk .text .len() .min(self.transforms.end(&()).0 .0 - self.output_offset.0), ); chunk.text = suffix; self.output_offset.0 += prefix.len(); Chunk { text: prefix, ..chunk.clone() } } Transform::Inlay(inlay) => { let mut inlay_style_and_highlight = None; if let Some(inlay_highlights) = self.highlights.inlay_highlights { for (_, inlay_id_to_data) in inlay_highlights.iter() { let style_and_highlight = inlay_id_to_data.get(&inlay.id); if style_and_highlight.is_some() { inlay_style_and_highlight = style_and_highlight; break; } } } let mut highlight_style = match inlay.id { InlayId::InlineCompletion(_) => { self.highlight_styles.inline_completion.map(|s| { if inlay.text.chars().all(|c| c.is_whitespace()) { s.whitespace } else { s.insertion } }) } InlayId::Hint(_) => self.highlight_styles.inlay_hint, }; let next_inlay_highlight_endpoint; let offset_in_inlay = self.output_offset - self.transforms.start().0; if let Some((style, highlight)) = inlay_style_and_highlight { let range = &highlight.range; if offset_in_inlay.0 < range.start { next_inlay_highlight_endpoint = range.start - offset_in_inlay.0; } else if offset_in_inlay.0 >= range.end { next_inlay_highlight_endpoint = usize::MAX; } else { next_inlay_highlight_endpoint = range.end - offset_in_inlay.0; highlight_style .get_or_insert_with(Default::default) .highlight(*style); } } else { next_inlay_highlight_endpoint = usize::MAX; } let inlay_chunks = self.inlay_chunks.get_or_insert_with(|| { let start = offset_in_inlay; let end = cmp::min(self.max_output_offset, self.transforms.end(&()).0) - self.transforms.start().0; inlay.text.chunks_in_range(start.0..end.0) }); let inlay_chunk = self .inlay_chunk .get_or_insert_with(|| inlay_chunks.next().unwrap()); let (chunk, remainder) = inlay_chunk.split_at(inlay_chunk.len().min(next_inlay_highlight_endpoint)); *inlay_chunk = remainder; if inlay_chunk.is_empty() { self.inlay_chunk = None; } self.output_offset.0 += chunk.len(); Chunk { text: chunk, highlight_style, ..Default::default() } } }; if self.output_offset == self.transforms.end(&()).0 { self.inlay_chunks = None; self.transforms.next(&()); } Some(chunk) } } impl<'a> InlayBufferRows<'a> { pub fn seek(&mut self, row: u32) { let inlay_point = InlayPoint::new(row, 0); self.transforms.seek(&inlay_point, Bias::Left, &()); let mut buffer_point = self.transforms.start().1; let buffer_row = MultiBufferRow(if row == 0 { 0 } else { match self.transforms.item() { Some(Transform::Isomorphic(_)) => { buffer_point += inlay_point.0 - self.transforms.start().0 .0; buffer_point.row } _ => cmp::min(buffer_point.row + 1, self.max_buffer_row.0), } }); self.inlay_row = inlay_point.row(); self.buffer_rows.seek(buffer_row); } } impl<'a> Iterator for InlayBufferRows<'a> { type Item = Option<u32>; fn next(&mut self) -> Option<Self::Item> { let buffer_row = if self.inlay_row == 0 { self.buffer_rows.next().unwrap() } else { match self.transforms.item()? { Transform::Inlay(_) => None, Transform::Isomorphic(_) => self.buffer_rows.next().unwrap(), } }; self.inlay_row += 1; self.transforms .seek_forward(&InlayPoint::new(self.inlay_row, 0), Bias::Left, &()); Some(buffer_row) } } impl InlayPoint { pub fn new(row: u32, column: u32) -> Self { Self(Point::new(row, column)) } pub fn row(self) -> u32 { self.0.row } } impl InlayMap { pub fn new(buffer: MultiBufferSnapshot) -> (Self, InlaySnapshot) { let version = 0; let snapshot = InlaySnapshot { buffer: buffer.clone(), transforms: SumTree::from_iter(Some(Transform::Isomorphic(buffer.text_summary())), &()), version, }; ( Self { snapshot: snapshot.clone(), inlays: Vec::new(), }, snapshot, ) } pub fn sync( &mut self, buffer_snapshot: MultiBufferSnapshot, mut buffer_edits: Vec<text::Edit<usize>>, ) -> (InlaySnapshot, Vec<InlayEdit>) { let snapshot = &mut self.snapshot; if buffer_edits.is_empty() && snapshot.buffer.trailing_excerpt_update_count() != buffer_snapshot.trailing_excerpt_update_count() { buffer_edits.push(Edit { old: snapshot.buffer.len()..snapshot.buffer.len(), new: buffer_snapshot.len()..buffer_snapshot.len(), }); } if buffer_edits.is_empty() { if snapshot.buffer.edit_count() != buffer_snapshot.edit_count() || snapshot.buffer.non_text_state_update_count() != buffer_snapshot.non_text_state_update_count() || snapshot.buffer.trailing_excerpt_update_count() != buffer_snapshot.trailing_excerpt_update_count() { snapshot.version += 1; } snapshot.buffer = buffer_snapshot; (snapshot.clone(), Vec::new()) } else { let mut inlay_edits = Patch::default(); let mut new_transforms = SumTree::default(); let mut cursor = snapshot.transforms.cursor::<(usize, InlayOffset)>(&()); let mut buffer_edits_iter = buffer_edits.iter().peekable(); while let Some(buffer_edit) = buffer_edits_iter.next() { new_transforms.append(cursor.slice(&buffer_edit.old.start, Bias::Left, &()), &()); if let Some(Transform::Isomorphic(transform)) = cursor.item() { if cursor.end(&()).0 == buffer_edit.old.start { push_isomorphic(&mut new_transforms, transform.clone()); cursor.next(&()); } } // Remove all the inlays and transforms contained by the edit. let old_start = cursor.start().1 + InlayOffset(buffer_edit.old.start - cursor.start().0); cursor.seek(&buffer_edit.old.end, Bias::Right, &()); let old_end = cursor.start().1 + InlayOffset(buffer_edit.old.end - cursor.start().0); // Push the unchanged prefix. let prefix_start = new_transforms.summary().input.len; let prefix_end = buffer_edit.new.start; push_isomorphic( &mut new_transforms, buffer_snapshot.text_summary_for_range(prefix_start..prefix_end), ); let new_start = InlayOffset(new_transforms.summary().output.len); let start_ix = match self.inlays.binary_search_by(|probe| { probe .position .to_offset(&buffer_snapshot) .cmp(&buffer_edit.new.start) .then(std::cmp::Ordering::Greater) }) { Ok(ix) | Err(ix) => ix, }; for inlay in &self.inlays[start_ix..] { let buffer_offset = inlay.position.to_offset(&buffer_snapshot); if buffer_offset > buffer_edit.new.end { break; } let prefix_start = new_transforms.summary().input.len; let prefix_end = buffer_offset; push_isomorphic( &mut new_transforms, buffer_snapshot.text_summary_for_range(prefix_start..prefix_end), ); if inlay.position.is_valid(&buffer_snapshot) { new_transforms.push(Transform::Inlay(inlay.clone()), &()); } } // Apply the rest of the edit.