use crate::{HighlightStyles, InlayId};use collections::{BTreeMap, BTreeSet};use gpui::HighlightStyle;use language::{Chunk, Edit, Point, TextSummary};use multi_buffer::{ Anchor, MultiBufferChunks, MultiBufferRow, MultiBufferRows, MultiBufferSnapshot, ToOffset,};use std::{ any::TypeId, cmp, iter::Peekable, ops::{Add, AddAssign, Range, Sub, SubAssign}, sync::Arc, vec,};use sum_tree::{Bias, Cursor, SumTree, TreeMap};use text::{Patch, Rope}; use super::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(crate) 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,} #[derive(Debug, Copy, Clone, Eq, PartialEq)]struct HighlightEndpoint { offset: InlayOffset, is_start: bool, tag: TypeId, style: HighlightStyle,} impl PartialOrd for HighlightEndpoint { fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { Some(self.cmp(other)) }} impl Ord for HighlightEndpoint { fn cmp(&self, other: &Self) -> cmp::Ordering { self.offset .cmp(&other.offset) .then_with(|| other.is_start.cmp(&self.is_start)) }} pub struct InlayChunks<'a> { transforms: Cursor<'a, Transform, (InlayOffset, usize)>, buffer_chunks: MultiBufferChunks<'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, highlight_endpoints: Peekable<vec::IntoIter<HighlightEndpoint>>, active_highlights: BTreeMap<TypeId, HighlightStyle>, 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; let mut highlight_endpoints = Vec::new(); if let Some(text_highlights) = self.highlights.text_highlights { if !text_highlights.is_empty() { self.snapshot.apply_text_highlights( &mut self.transforms, &new_range, text_highlights, &mut highlight_endpoints, ); self.transforms.seek(&new_range.start, Bias::Right, &()); highlight_endpoints.sort(); } } self.highlight_endpoints = highlight_endpoints.into_iter().peekable(); self.active_highlights.clear(); } 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 mut next_highlight_endpoint = InlayOffset(usize::MAX); while let Some(endpoint) = self.highlight_endpoints.peek().copied() { if endpoint.offset <= self.output_offset { if endpoint.is_start { self.active_highlights.insert(endpoint.tag, endpoint.style); } else { self.active_highlights.remove(&endpoint.tag); } self.highlight_endpoints.next(); } else { next_highlight_endpoint = endpoint.offset; break; } } 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) .min(next_highlight_endpoint.0 - self.output_offset.0), ); chunk.text = suffix; self.output_offset.0 += prefix.len(); let mut prefix = Chunk { text: prefix, ..chunk.clone() }; if !self.active_highlights.is_empty() { let mut highlight_style = HighlightStyle::default(); for active_highlight in self.active_highlights.values() { highlight_style.highlight(*active_highlight); } prefix.highlight_style = Some(highlight_style); } prefix } 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(); if !self.active_highlights.is_empty() { for active_highlight in self.active_highlights.values() { highlight_style .get_or_insert(Default::default()) .highlight(*active_highlight); } } 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()Lines 1–500 of 1939. Load more
use crate::{HighlightStyles, InlayId}; use collections::{BTreeMap, BTreeSet}; use gpui::HighlightStyle; use language::{Chunk, Edit, Point, TextSummary}; use multi_buffer::{ Anchor, MultiBufferChunks, MultiBufferRow, MultiBufferRows, MultiBufferSnapshot, ToOffset, }; use std::{ any::TypeId, cmp, iter::Peekable, ops::{Add, AddAssign, Range, Sub, SubAssign}, sync::Arc, vec, }; use sum_tree::{Bias, Cursor, SumTree, TreeMap}; use text::{Patch, Rope}; use super::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(crate) 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, } #[derive(Debug, Copy, Clone, Eq, PartialEq)] struct HighlightEndpoint { offset: InlayOffset, is_start: bool, tag: TypeId, style: HighlightStyle, } impl PartialOrd for HighlightEndpoint { fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { Some(self.cmp(other)) } } impl Ord for HighlightEndpoint { fn cmp(&self, other: &Self) -> cmp::Ordering { self.offset .cmp(&other.offset) .then_with(|| other.is_start.cmp(&self.is_start)) } } pub struct InlayChunks<'a> { transforms: Cursor<'a, Transform, (InlayOffset, usize)>, buffer_chunks: MultiBufferChunks<'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, highlight_endpoints: Peekable<vec::IntoIter<HighlightEndpoint>>, active_highlights: BTreeMap<TypeId, HighlightStyle>, 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; let mut highlight_endpoints = Vec::new(); if let Some(text_highlights) = self.highlights.text_highlights { if !text_highlights.is_empty() { self.snapshot.apply_text_highlights( &mut self.transforms, &new_range, text_highlights, &mut highlight_endpoints, ); self.transforms.seek(&new_range.start, Bias::Right, &()); highlight_endpoints.sort(); } } self.highlight_endpoints = highlight_endpoints.into_iter().peekable(); self.active_highlights.clear(); } 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 mut next_highlight_endpoint = InlayOffset(usize::MAX); while let Some(endpoint) = self.highlight_endpoints.peek().copied() { if endpoint.offset <= self.output_offset { if endpoint.is_start { self.active_highlights.insert(endpoint.tag, endpoint.style); } else { self.active_highlights.remove(&endpoint.tag); } self.highlight_endpoints.next(); } else { next_highlight_endpoint = endpoint.offset; break; } } 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) .min(next_highlight_endpoint.0 - self.output_offset.0), ); chunk.text = suffix; self.output_offset.0 += prefix.len(); let mut prefix = Chunk { text: prefix, ..chunk.clone() }; if !self.active_highlights.is_empty() { let mut highlight_style = HighlightStyle::default(); for active_highlight in self.active_highlights.values() { highlight_style.highlight(*active_highlight); } prefix.highlight_style = Some(highlight_style); } prefix } 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(); if !self.active_highlights.is_empty() { for active_highlight in self.active_highlights.values() { highlight_style .get_or_insert(Default::default()) .highlight(*active_highlight); } } 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()