multi_buffer: Typed MultiBufferOffset (#42707)
This PR introduces a new `MultiBufferOffset` new type wrapping size. The goal of this is to make it clear at the type level when we are interacting with offsets of a multi buffer versus offsets of a language / text buffer. This improves readability of things quite a bit by making it clear what kind of offsets one is working with while also reducing accidental bugs by using the wrong kin of offset for the wrong API. This PR also uncovered two minor bugs due to that. Does not yet introduce the MultiBufferPoint equivalent, that is for a follow up PR. Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
@@ -44,12 +44,10 @@ pub use invisibles::{is_invisible, replacement};
|
||||
|
||||
use collections::{HashMap, HashSet};
|
||||
use gpui::{App, Context, Entity, Font, HighlightStyle, LineLayout, Pixels, UnderlineStyle};
|
||||
use language::{
|
||||
OffsetUtf16, Point, Subscription as BufferSubscription, language_settings::language_settings,
|
||||
};
|
||||
use language::{Point, Subscription as BufferSubscription, language_settings::language_settings};
|
||||
use multi_buffer::{
|
||||
Anchor, AnchorRangeExt, MultiBuffer, MultiBufferPoint, MultiBufferRow, MultiBufferSnapshot,
|
||||
RowInfo, ToOffset, ToPoint,
|
||||
Anchor, AnchorRangeExt, MultiBuffer, MultiBufferOffset, MultiBufferOffsetUtf16,
|
||||
MultiBufferPoint, MultiBufferRow, MultiBufferSnapshot, RowInfo, ToOffset, ToPoint,
|
||||
};
|
||||
use project::InlayId;
|
||||
use project::project_settings::DiagnosticSeverity;
|
||||
@@ -104,7 +102,7 @@ type InlayHighlights = TreeMap<TypeId, TreeMap<InlayId, (HighlightStyle, InlayHi
|
||||
pub struct DisplayMap {
|
||||
/// The buffer that we are displaying.
|
||||
buffer: Entity<MultiBuffer>,
|
||||
buffer_subscription: BufferSubscription,
|
||||
buffer_subscription: BufferSubscription<MultiBufferOffset>,
|
||||
/// Decides where the [`Inlay`]s should be displayed.
|
||||
inlay_map: InlayMap,
|
||||
/// Decides where the fold indicators should be and tracks parts of a source file that are currently folded.
|
||||
@@ -198,7 +196,7 @@ impl DisplayMap {
|
||||
pub fn set_state(&mut self, other: &DisplaySnapshot, cx: &mut Context<Self>) {
|
||||
self.fold(
|
||||
other
|
||||
.folds_in_range(0..other.buffer_snapshot().len())
|
||||
.folds_in_range(MultiBufferOffset(0)..other.buffer_snapshot().len())
|
||||
.map(|fold| {
|
||||
Crease::simple(
|
||||
fold.range.to_offset(other.buffer_snapshot()),
|
||||
@@ -794,7 +792,7 @@ impl DisplaySnapshot {
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.buffer_snapshot().len() == 0
|
||||
self.buffer_snapshot().len() == MultiBufferOffset(0)
|
||||
}
|
||||
|
||||
pub fn row_infos(&self, start_row: DisplayRow) -> impl Iterator<Item = RowInfo> + '_ {
|
||||
@@ -1133,7 +1131,10 @@ impl DisplaySnapshot {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn buffer_chars_at(&self, mut offset: usize) -> impl Iterator<Item = (char, usize)> + '_ {
|
||||
pub fn buffer_chars_at(
|
||||
&self,
|
||||
mut offset: MultiBufferOffset,
|
||||
) -> impl Iterator<Item = (char, MultiBufferOffset)> + '_ {
|
||||
self.buffer_snapshot().chars_at(offset).map(move |ch| {
|
||||
let ret = (ch, offset);
|
||||
offset += ch.len_utf8();
|
||||
@@ -1143,8 +1144,8 @@ impl DisplaySnapshot {
|
||||
|
||||
pub fn reverse_buffer_chars_at(
|
||||
&self,
|
||||
mut offset: usize,
|
||||
) -> impl Iterator<Item = (char, usize)> + '_ {
|
||||
mut offset: MultiBufferOffset,
|
||||
) -> impl Iterator<Item = (char, MultiBufferOffset)> + '_ {
|
||||
self.buffer_snapshot()
|
||||
.reversed_chars_at(offset)
|
||||
.map(move |ch| {
|
||||
@@ -1526,7 +1527,7 @@ impl DisplayPoint {
|
||||
map.display_point_to_point(self, Bias::Left)
|
||||
}
|
||||
|
||||
pub fn to_offset(self, map: &DisplaySnapshot, bias: Bias) -> usize {
|
||||
pub fn to_offset(self, map: &DisplaySnapshot, bias: Bias) -> MultiBufferOffset {
|
||||
let wrap_point = map.block_snapshot.to_wrap_point(self.0, bias);
|
||||
let tab_point = map.wrap_snapshot().to_tab_point(wrap_point);
|
||||
let fold_point = map.tab_snapshot().to_fold_point(tab_point, bias).0;
|
||||
@@ -1536,13 +1537,13 @@ impl DisplayPoint {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToDisplayPoint for usize {
|
||||
impl ToDisplayPoint for MultiBufferOffset {
|
||||
fn to_display_point(&self, map: &DisplaySnapshot) -> DisplayPoint {
|
||||
map.point_to_display_point(self.to_point(map.buffer_snapshot()), Bias::Left)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToDisplayPoint for OffsetUtf16 {
|
||||
impl ToDisplayPoint for MultiBufferOffsetUtf16 {
|
||||
fn to_display_point(&self, map: &DisplaySnapshot) -> DisplayPoint {
|
||||
self.to_offset(map.buffer_snapshot()).to_display_point(map)
|
||||
}
|
||||
@@ -1685,7 +1686,7 @@ pub mod tests {
|
||||
let block_properties = (0..rng.random_range(1..=1))
|
||||
.map(|_| {
|
||||
let position = buffer.anchor_after(buffer.clip_offset(
|
||||
rng.random_range(0..=buffer.len()),
|
||||
rng.random_range(MultiBufferOffset(0)..=buffer.len()),
|
||||
Bias::Left,
|
||||
));
|
||||
|
||||
@@ -1727,8 +1728,12 @@ pub mod tests {
|
||||
for _ in 0..rng.random_range(1..=3) {
|
||||
buffer.read_with(cx, |buffer, cx| {
|
||||
let buffer = buffer.read(cx);
|
||||
let end = buffer.clip_offset(rng.random_range(0..=buffer.len()), Right);
|
||||
let start = buffer.clip_offset(rng.random_range(0..=end), Left);
|
||||
let end = buffer.clip_offset(
|
||||
rng.random_range(MultiBufferOffset(0)..=buffer.len()),
|
||||
Right,
|
||||
);
|
||||
let start = buffer
|
||||
.clip_offset(rng.random_range(MultiBufferOffset(0)..=end), Left);
|
||||
ranges.push(start..end);
|
||||
});
|
||||
}
|
||||
@@ -1954,7 +1959,7 @@ pub mod tests {
|
||||
)
|
||||
);
|
||||
|
||||
let ix = snapshot.buffer_snapshot().text().find("seven").unwrap();
|
||||
let ix = MultiBufferOffset(snapshot.buffer_snapshot().text().find("seven").unwrap());
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit([(ix..ix, "and ")], None, cx);
|
||||
});
|
||||
@@ -2083,7 +2088,7 @@ pub mod tests {
|
||||
&[],
|
||||
vec![Inlay::edit_prediction(
|
||||
0,
|
||||
buffer_snapshot.anchor_after(0),
|
||||
buffer_snapshot.anchor_after(MultiBufferOffset(0)),
|
||||
"\n",
|
||||
)],
|
||||
cx,
|
||||
@@ -2094,7 +2099,11 @@ pub mod tests {
|
||||
// Regression test: updating the display map does not crash when a
|
||||
// block is immediately followed by a multi-line inlay.
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit([(1..1, "b")], None, cx);
|
||||
buffer.edit(
|
||||
[(MultiBufferOffset(1)..MultiBufferOffset(1), "b")],
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
map.update(cx, |m, cx| assert_eq!(m.snapshot(cx).text(), "\n\n\nab"));
|
||||
}
|
||||
@@ -2694,6 +2703,7 @@ pub mod tests {
|
||||
HighlightKey::Type(TypeId::of::<MyType>()),
|
||||
highlighted_ranges
|
||||
.into_iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end))
|
||||
.map(|range| {
|
||||
buffer_snapshot.anchor_before(range.start)
|
||||
..buffer_snapshot.anchor_before(range.end)
|
||||
|
||||
@@ -11,8 +11,8 @@ use collections::{Bound, HashMap, HashSet};
|
||||
use gpui::{AnyElement, App, EntityId, Pixels, Window};
|
||||
use language::{Patch, Point};
|
||||
use multi_buffer::{
|
||||
Anchor, ExcerptId, ExcerptInfo, MultiBuffer, MultiBufferRow, MultiBufferSnapshot, RowInfo,
|
||||
ToOffset, ToPoint as _,
|
||||
Anchor, ExcerptId, ExcerptInfo, MultiBuffer, MultiBufferOffset, MultiBufferRow,
|
||||
MultiBufferSnapshot, RowInfo, ToOffset, ToPoint as _,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use std::{
|
||||
@@ -1208,7 +1208,7 @@ impl BlockMapWriter<'_> {
|
||||
|
||||
pub fn remove_intersecting_replace_blocks(
|
||||
&mut self,
|
||||
ranges: impl IntoIterator<Item = Range<usize>>,
|
||||
ranges: impl IntoIterator<Item = Range<MultiBufferOffset>>,
|
||||
inclusive: bool,
|
||||
) {
|
||||
let wrap_snapshot = self.0.wrap_snapshot.borrow();
|
||||
@@ -1283,7 +1283,7 @@ impl BlockMapWriter<'_> {
|
||||
|
||||
fn blocks_intersecting_buffer_range(
|
||||
&self,
|
||||
range: Range<usize>,
|
||||
range: Range<MultiBufferOffset>,
|
||||
inclusive: bool,
|
||||
) -> &[Arc<CustomBlock>] {
|
||||
if range.is_empty() && !inclusive {
|
||||
@@ -3043,8 +3043,10 @@ mod tests {
|
||||
let block_properties = (0..block_count)
|
||||
.map(|_| {
|
||||
let buffer = cx.update(|cx| buffer.read(cx).read(cx).clone());
|
||||
let offset =
|
||||
buffer.clip_offset(rng.random_range(0..=buffer.len()), Bias::Left);
|
||||
let offset = buffer.clip_offset(
|
||||
rng.random_range(MultiBufferOffset(0)..=buffer.len()),
|
||||
Bias::Left,
|
||||
);
|
||||
let mut min_height = 0;
|
||||
let placement = match rng.random_range(0..3) {
|
||||
0 => {
|
||||
@@ -3244,7 +3246,7 @@ mod tests {
|
||||
// Note that this needs to be synced with the related section in BlockMap::sync
|
||||
expected_blocks.extend(block_map.header_and_footer_blocks(
|
||||
&buffer_snapshot,
|
||||
0..,
|
||||
MultiBufferOffset(0)..,
|
||||
&wraps_snapshot,
|
||||
));
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use collections::BTreeMap;
|
||||
use gpui::HighlightStyle;
|
||||
use language::Chunk;
|
||||
use multi_buffer::{MultiBufferChunks, MultiBufferSnapshot, ToOffset as _};
|
||||
use multi_buffer::{MultiBufferChunks, MultiBufferOffset, MultiBufferSnapshot, ToOffset as _};
|
||||
use std::{
|
||||
cmp,
|
||||
iter::{self, Peekable},
|
||||
@@ -14,7 +14,7 @@ use crate::display_map::{HighlightKey, TextHighlights};
|
||||
pub struct CustomHighlightsChunks<'a> {
|
||||
buffer_chunks: MultiBufferChunks<'a>,
|
||||
buffer_chunk: Option<Chunk<'a>>,
|
||||
offset: usize,
|
||||
offset: MultiBufferOffset,
|
||||
multibuffer_snapshot: &'a MultiBufferSnapshot,
|
||||
|
||||
highlight_endpoints: Peekable<vec::IntoIter<HighlightEndpoint>>,
|
||||
@@ -24,14 +24,14 @@ pub struct CustomHighlightsChunks<'a> {
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
struct HighlightEndpoint {
|
||||
offset: usize,
|
||||
offset: MultiBufferOffset,
|
||||
tag: HighlightKey,
|
||||
style: Option<HighlightStyle>,
|
||||
}
|
||||
|
||||
impl<'a> CustomHighlightsChunks<'a> {
|
||||
pub fn new(
|
||||
range: Range<usize>,
|
||||
range: Range<MultiBufferOffset>,
|
||||
language_aware: bool,
|
||||
text_highlights: Option<&'a TextHighlights>,
|
||||
multibuffer_snapshot: &'a MultiBufferSnapshot,
|
||||
@@ -52,7 +52,7 @@ impl<'a> CustomHighlightsChunks<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn seek(&mut self, new_range: Range<usize>) {
|
||||
pub fn seek(&mut self, new_range: Range<MultiBufferOffset>) {
|
||||
self.highlight_endpoints =
|
||||
create_highlight_endpoints(&new_range, self.text_highlights, self.multibuffer_snapshot);
|
||||
self.offset = new_range.start;
|
||||
@@ -63,7 +63,7 @@ impl<'a> CustomHighlightsChunks<'a> {
|
||||
}
|
||||
|
||||
fn create_highlight_endpoints(
|
||||
range: &Range<usize>,
|
||||
range: &Range<MultiBufferOffset>,
|
||||
text_highlights: Option<&TextHighlights>,
|
||||
buffer: &MultiBufferSnapshot,
|
||||
) -> iter::Peekable<vec::IntoIter<HighlightEndpoint>> {
|
||||
@@ -117,7 +117,7 @@ impl<'a> Iterator for CustomHighlightsChunks<'a> {
|
||||
type Item = Chunk<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let mut next_highlight_endpoint = usize::MAX;
|
||||
let mut next_highlight_endpoint = MultiBufferOffset(usize::MAX);
|
||||
while let Some(endpoint) = self.highlight_endpoints.peek().copied() {
|
||||
if endpoint.offset <= self.offset {
|
||||
if let Some(style) = endpoint.style {
|
||||
@@ -224,20 +224,22 @@ mod tests {
|
||||
let range_count = rng.random_range(1..10);
|
||||
let text = buffer_snapshot.text();
|
||||
for _ in 0..range_count {
|
||||
if buffer_snapshot.len() == 0 {
|
||||
if buffer_snapshot.len() == MultiBufferOffset(0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut start = rng.random_range(0..=buffer_snapshot.len().saturating_sub(10));
|
||||
let mut start = rng.random_range(
|
||||
MultiBufferOffset(0)..=buffer_snapshot.len().saturating_sub_usize(10),
|
||||
);
|
||||
|
||||
while !text.is_char_boundary(start) {
|
||||
start = start.saturating_sub(1);
|
||||
while !text.is_char_boundary(start.0) {
|
||||
start = start.saturating_sub_usize(1);
|
||||
}
|
||||
|
||||
let end_end = buffer_snapshot.len().min(start + 100);
|
||||
let end_end = buffer_snapshot.len().min(start + 100usize);
|
||||
let mut end = rng.random_range(start..=end_end);
|
||||
while !text.is_char_boundary(end) {
|
||||
end = end.saturating_sub(1);
|
||||
while !text.is_char_boundary(end.0) {
|
||||
end = end.saturating_sub_usize(1);
|
||||
}
|
||||
|
||||
if start < end {
|
||||
@@ -253,8 +255,12 @@ mod tests {
|
||||
}
|
||||
|
||||
// Get all chunks and verify their bitmaps
|
||||
let chunks =
|
||||
CustomHighlightsChunks::new(0..buffer_snapshot.len(), false, None, &buffer_snapshot);
|
||||
let chunks = CustomHighlightsChunks::new(
|
||||
MultiBufferOffset(0)..buffer_snapshot.len(),
|
||||
false,
|
||||
None,
|
||||
&buffer_snapshot,
|
||||
);
|
||||
|
||||
for chunk in chunks {
|
||||
let chunk_text = chunk.text;
|
||||
|
||||
@@ -5,16 +5,17 @@ use super::{
|
||||
inlay_map::{InlayBufferRows, InlayChunks, InlayEdit, InlayOffset, InlayPoint, InlaySnapshot},
|
||||
};
|
||||
use gpui::{AnyElement, App, ElementId, HighlightStyle, Pixels, Window};
|
||||
use language::{Edit, HighlightId, Point, TextSummary};
|
||||
use language::{Edit, HighlightId, Point};
|
||||
use multi_buffer::{
|
||||
Anchor, AnchorRangeExt, MultiBufferRow, MultiBufferSnapshot, RowInfo, ToOffset,
|
||||
Anchor, AnchorRangeExt, MBTextSummary, MultiBufferOffset, MultiBufferRow, MultiBufferSnapshot,
|
||||
RowInfo, ToOffset,
|
||||
};
|
||||
use project::InlayId;
|
||||
use std::{
|
||||
any::TypeId,
|
||||
cmp::{self, Ordering},
|
||||
fmt, iter,
|
||||
ops::{Add, AddAssign, Deref, DerefMut, Range, Sub},
|
||||
ops::{Add, AddAssign, Deref, DerefMut, Range, Sub, SubAssign},
|
||||
sync::Arc,
|
||||
usize,
|
||||
};
|
||||
@@ -261,7 +262,7 @@ impl FoldMapWriter<'_> {
|
||||
fold_ixs_to_delete.dedup();
|
||||
|
||||
self.0.snapshot.folds = {
|
||||
let mut cursor = self.0.snapshot.folds.cursor::<usize>(buffer);
|
||||
let mut cursor = self.0.snapshot.folds.cursor::<MultiBufferOffset>(buffer);
|
||||
let mut folds = SumTree::new(buffer);
|
||||
for fold_ix in fold_ixs_to_delete {
|
||||
folds.append(cursor.slice(&fold_ix, Bias::Right), buffer);
|
||||
@@ -413,7 +414,7 @@ impl FoldMap {
|
||||
|
||||
let mut new_transforms = SumTree::<Transform>::default();
|
||||
let mut cursor = self.snapshot.transforms.cursor::<InlayOffset>(());
|
||||
cursor.seek(&InlayOffset(0), Bias::Right);
|
||||
cursor.seek(&InlayOffset(MultiBufferOffset(0)), Bias::Right);
|
||||
|
||||
while let Some(mut edit) = inlay_edits_iter.next() {
|
||||
if let Some(item) = cursor.item()
|
||||
@@ -436,7 +437,7 @@ impl FoldMap {
|
||||
cursor.seek(&edit.old.end, Bias::Right);
|
||||
cursor.next();
|
||||
|
||||
let mut delta = edit.new_len().0 as isize - edit.old_len().0 as isize;
|
||||
let mut delta = edit.new_len() as isize - edit.old_len() as isize;
|
||||
loop {
|
||||
edit.old.end = *cursor.start();
|
||||
|
||||
@@ -446,7 +447,7 @@ impl FoldMap {
|
||||
}
|
||||
|
||||
let next_edit = inlay_edits_iter.next().unwrap();
|
||||
delta += next_edit.new_len().0 as isize - next_edit.old_len().0 as isize;
|
||||
delta += next_edit.new_len() as isize - next_edit.old_len() as isize;
|
||||
|
||||
if next_edit.old.end >= edit.old.end {
|
||||
edit.old.end = next_edit.old.end;
|
||||
@@ -458,8 +459,9 @@ impl FoldMap {
|
||||
}
|
||||
}
|
||||
|
||||
edit.new.end =
|
||||
InlayOffset(((edit.new.start + edit.old_len()).0 as isize + delta) as usize);
|
||||
edit.new.end = InlayOffset(MultiBufferOffset(
|
||||
((edit.new.start + edit.old_len()).0.0 as isize + delta) as usize,
|
||||
));
|
||||
|
||||
let anchor = inlay_snapshot
|
||||
.buffer
|
||||
@@ -522,7 +524,7 @@ impl FoldMap {
|
||||
new_transforms.push(
|
||||
Transform {
|
||||
summary: TransformSummary {
|
||||
output: TextSummary::from(ELLIPSIS),
|
||||
output: MBTextSummary::from(ELLIPSIS),
|
||||
input: inlay_snapshot
|
||||
.text_summary_for_range(fold_range.start..fold_range.end),
|
||||
},
|
||||
@@ -579,7 +581,7 @@ impl FoldMap {
|
||||
edit.old.start = old_transforms.start().0;
|
||||
}
|
||||
let old_start =
|
||||
old_transforms.start().1.0 + (edit.old.start - old_transforms.start().0).0;
|
||||
old_transforms.start().1.0 + (edit.old.start - old_transforms.start().0);
|
||||
|
||||
old_transforms.seek_forward(&edit.old.end, Bias::Right);
|
||||
if old_transforms.item().is_some_and(|t| t.is_fold()) {
|
||||
@@ -587,14 +589,14 @@ impl FoldMap {
|
||||
edit.old.end = old_transforms.start().0;
|
||||
}
|
||||
let old_end =
|
||||
old_transforms.start().1.0 + (edit.old.end - old_transforms.start().0).0;
|
||||
old_transforms.start().1.0 + (edit.old.end - old_transforms.start().0);
|
||||
|
||||
new_transforms.seek(&edit.new.start, Bias::Left);
|
||||
if new_transforms.item().is_some_and(|t| t.is_fold()) {
|
||||
edit.new.start = new_transforms.start().0;
|
||||
}
|
||||
let new_start =
|
||||
new_transforms.start().1.0 + (edit.new.start - new_transforms.start().0).0;
|
||||
new_transforms.start().1.0 + (edit.new.start - new_transforms.start().0);
|
||||
|
||||
new_transforms.seek_forward(&edit.new.end, Bias::Right);
|
||||
if new_transforms.item().is_some_and(|t| t.is_fold()) {
|
||||
@@ -602,7 +604,7 @@ impl FoldMap {
|
||||
edit.new.end = new_transforms.start().0;
|
||||
}
|
||||
let new_end =
|
||||
new_transforms.start().1.0 + (edit.new.end - new_transforms.start().0).0;
|
||||
new_transforms.start().1.0 + (edit.new.end - new_transforms.start().0);
|
||||
|
||||
fold_edits.push(FoldEdit {
|
||||
old: FoldOffset(old_start)..FoldOffset(old_end),
|
||||
@@ -649,9 +651,13 @@ impl FoldSnapshot {
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn text(&self) -> String {
|
||||
self.chunks(FoldOffset(0)..self.len(), false, Highlights::default())
|
||||
.map(|c| c.text)
|
||||
.collect()
|
||||
self.chunks(
|
||||
FoldOffset(MultiBufferOffset(0))..self.len(),
|
||||
false,
|
||||
Highlights::default(),
|
||||
)
|
||||
.map(|c| c.text)
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -659,8 +665,8 @@ impl FoldSnapshot {
|
||||
self.folds.items(&self.inlay_snapshot.buffer).len()
|
||||
}
|
||||
|
||||
pub fn text_summary_for_range(&self, range: Range<FoldPoint>) -> TextSummary {
|
||||
let mut summary = TextSummary::default();
|
||||
pub fn text_summary_for_range(&self, range: Range<FoldPoint>) -> MBTextSummary {
|
||||
let mut summary = MBTextSummary::default();
|
||||
|
||||
let mut cursor = self
|
||||
.transforms
|
||||
@@ -670,7 +676,7 @@ impl FoldSnapshot {
|
||||
let start_in_transform = range.start.0 - cursor.start().0.0;
|
||||
let end_in_transform = cmp::min(range.end, cursor.end().0).0 - cursor.start().0.0;
|
||||
if let Some(placeholder) = transform.placeholder.as_ref() {
|
||||
summary = TextSummary::from(
|
||||
summary = MBTextSummary::from(
|
||||
&placeholder.text
|
||||
[start_in_transform.column as usize..end_in_transform.column as usize],
|
||||
);
|
||||
@@ -689,14 +695,14 @@ impl FoldSnapshot {
|
||||
|
||||
if range.end > cursor.end().0 {
|
||||
cursor.next();
|
||||
summary += &cursor
|
||||
summary += cursor
|
||||
.summary::<_, TransformSummary>(&range.end, Bias::Right)
|
||||
.output;
|
||||
if let Some(transform) = cursor.item() {
|
||||
let end_in_transform = range.end.0 - cursor.start().0.0;
|
||||
if let Some(placeholder) = transform.placeholder.as_ref() {
|
||||
summary +=
|
||||
TextSummary::from(&placeholder.text[..end_in_transform.column as usize]);
|
||||
MBTextSummary::from(&placeholder.text[..end_in_transform.column as usize]);
|
||||
} else {
|
||||
let inlay_start = self.inlay_snapshot.to_offset(cursor.start().1);
|
||||
let inlay_end = self
|
||||
@@ -839,8 +845,8 @@ impl FoldSnapshot {
|
||||
transform_cursor.seek(&range.start, Bias::Right);
|
||||
|
||||
let inlay_start = {
|
||||
let overshoot = range.start.0 - transform_cursor.start().0.0;
|
||||
transform_cursor.start().1 + InlayOffset(overshoot)
|
||||
let overshoot = range.start - transform_cursor.start().0;
|
||||
transform_cursor.start().1 + overshoot
|
||||
};
|
||||
|
||||
let transform_end = transform_cursor.end();
|
||||
@@ -851,8 +857,8 @@ impl FoldSnapshot {
|
||||
{
|
||||
inlay_start
|
||||
} else if range.end < transform_end.0 {
|
||||
let overshoot = range.end.0 - transform_cursor.start().0.0;
|
||||
transform_cursor.start().1 + InlayOffset(overshoot)
|
||||
let overshoot = range.end - transform_cursor.start().0;
|
||||
transform_cursor.start().1 + overshoot
|
||||
} else {
|
||||
transform_end.1
|
||||
};
|
||||
@@ -921,7 +927,7 @@ impl FoldSnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
fn push_isomorphic(transforms: &mut SumTree<Transform>, summary: TextSummary) {
|
||||
fn push_isomorphic(transforms: &mut SumTree<Transform>, summary: MBTextSummary) {
|
||||
let mut did_merge = false;
|
||||
transforms.update_last(
|
||||
|last| {
|
||||
@@ -950,13 +956,13 @@ fn push_isomorphic(transforms: &mut SumTree<Transform>, summary: TextSummary) {
|
||||
fn intersecting_folds<'a>(
|
||||
inlay_snapshot: &'a InlaySnapshot,
|
||||
folds: &'a SumTree<Fold>,
|
||||
range: Range<usize>,
|
||||
range: Range<MultiBufferOffset>,
|
||||
inclusive: bool,
|
||||
) -> FilterCursor<'a, 'a, impl 'a + FnMut(&FoldSummary) -> bool, Fold, usize> {
|
||||
) -> FilterCursor<'a, 'a, impl 'a + FnMut(&FoldSummary) -> bool, Fold, MultiBufferOffset> {
|
||||
let buffer = &inlay_snapshot.buffer;
|
||||
let start = buffer.anchor_before(range.start.to_offset(buffer));
|
||||
let end = buffer.anchor_after(range.end.to_offset(buffer));
|
||||
let mut cursor = folds.filter::<_, usize>(buffer, move |summary| {
|
||||
let mut cursor = folds.filter::<_, MultiBufferOffset>(buffer, move |summary| {
|
||||
let start_cmp = start.cmp(&summary.max_end, buffer);
|
||||
let end_cmp = end.cmp(&summary.min_start, buffer);
|
||||
|
||||
@@ -1061,8 +1067,8 @@ impl Transform {
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
struct TransformSummary {
|
||||
output: TextSummary,
|
||||
input: TextSummary,
|
||||
output: MBTextSummary,
|
||||
input: MBTextSummary,
|
||||
}
|
||||
|
||||
impl sum_tree::Item for Transform {
|
||||
@@ -1079,8 +1085,8 @@ impl sum_tree::ContextLessSummary for TransformSummary {
|
||||
}
|
||||
|
||||
fn add_summary(&mut self, other: &Self) {
|
||||
self.input += &other.input;
|
||||
self.output += &other.output;
|
||||
self.input += other.input;
|
||||
self.output += other.output;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1211,7 +1217,7 @@ impl sum_tree::SeekTarget<'_, FoldSummary, FoldRange> for FoldRange {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::Dimension<'a, FoldSummary> for usize {
|
||||
impl<'a> sum_tree::Dimension<'a, FoldSummary> for MultiBufferOffset {
|
||||
fn zero(_cx: &MultiBufferSnapshot) -> Self {
|
||||
Default::default()
|
||||
}
|
||||
@@ -1357,8 +1363,8 @@ impl FoldChunks<'_> {
|
||||
self.transform_cursor.seek(&range.start, Bias::Right);
|
||||
|
||||
let inlay_start = {
|
||||
let overshoot = range.start.0 - self.transform_cursor.start().0.0;
|
||||
self.transform_cursor.start().1 + InlayOffset(overshoot)
|
||||
let overshoot = range.start - self.transform_cursor.start().0;
|
||||
self.transform_cursor.start().1 + overshoot
|
||||
};
|
||||
|
||||
let transform_end = self.transform_cursor.end();
|
||||
@@ -1370,8 +1376,8 @@ impl FoldChunks<'_> {
|
||||
{
|
||||
inlay_start
|
||||
} else if range.end < transform_end.0 {
|
||||
let overshoot = range.end.0 - self.transform_cursor.start().0.0;
|
||||
self.transform_cursor.start().1 + InlayOffset(overshoot)
|
||||
let overshoot = range.end - self.transform_cursor.start().0;
|
||||
self.transform_cursor.start().1 + overshoot
|
||||
} else {
|
||||
transform_end.1
|
||||
};
|
||||
@@ -1423,8 +1429,8 @@ impl<'a> Iterator for FoldChunks<'a> {
|
||||
let transform_start = self.transform_cursor.start();
|
||||
let transform_end = self.transform_cursor.end();
|
||||
let inlay_end = if self.max_output_offset < transform_end.0 {
|
||||
let overshoot = self.max_output_offset.0 - transform_start.0.0;
|
||||
transform_start.1 + InlayOffset(overshoot)
|
||||
let overshoot = self.max_output_offset - transform_start.0;
|
||||
transform_start.1 + overshoot
|
||||
} else {
|
||||
transform_end.1
|
||||
};
|
||||
@@ -1441,15 +1447,15 @@ impl<'a> Iterator for FoldChunks<'a> {
|
||||
// Otherwise, take a chunk from the buffer's text.
|
||||
if let Some((buffer_chunk_start, mut inlay_chunk)) = self.inlay_chunk.clone() {
|
||||
let chunk = &mut inlay_chunk.chunk;
|
||||
let buffer_chunk_end = buffer_chunk_start + InlayOffset(chunk.text.len());
|
||||
let buffer_chunk_end = buffer_chunk_start + chunk.text.len();
|
||||
let transform_end = self.transform_cursor.end().1;
|
||||
let chunk_end = buffer_chunk_end.min(transform_end);
|
||||
|
||||
let bit_start = (self.inlay_offset - buffer_chunk_start).0;
|
||||
let bit_end = (chunk_end - buffer_chunk_start).0;
|
||||
let bit_start = self.inlay_offset - buffer_chunk_start;
|
||||
let bit_end = chunk_end - buffer_chunk_start;
|
||||
chunk.text = &chunk.text[bit_start..bit_end];
|
||||
|
||||
let bit_end = (chunk_end - buffer_chunk_start).0;
|
||||
let bit_end = chunk_end - buffer_chunk_start;
|
||||
let mask = 1u128.unbounded_shl(bit_end as u32).wrapping_sub(1);
|
||||
|
||||
chunk.tabs = (chunk.tabs >> bit_start) & mask;
|
||||
@@ -1483,7 +1489,7 @@ impl<'a> Iterator for FoldChunks<'a> {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
|
||||
pub struct FoldOffset(pub usize);
|
||||
pub struct FoldOffset(pub MultiBufferOffset);
|
||||
|
||||
impl FoldOffset {
|
||||
pub fn to_point(self, snapshot: &FoldSnapshot) -> FoldPoint {
|
||||
@@ -1493,7 +1499,7 @@ impl FoldOffset {
|
||||
let overshoot = if item.is_none_or(|t| t.is_fold()) {
|
||||
Point::new(0, (self.0 - start.0.0) as u32)
|
||||
} else {
|
||||
let inlay_offset = start.1.input.len + self.0 - start.0.0;
|
||||
let inlay_offset = start.1.input.len + (self - start.0);
|
||||
let inlay_point = snapshot.inlay_snapshot.to_point(InlayOffset(inlay_offset));
|
||||
inlay_point.0 - start.1.input.lines
|
||||
};
|
||||
@@ -1505,7 +1511,7 @@ impl FoldOffset {
|
||||
let (start, _, _) = snapshot
|
||||
.transforms
|
||||
.find::<Dimensions<FoldOffset, InlayOffset>, _>((), &self, Bias::Right);
|
||||
let overshoot = self.0 - start.0.0;
|
||||
let overshoot = self - start.0;
|
||||
InlayOffset(start.1.0 + overshoot)
|
||||
}
|
||||
}
|
||||
@@ -1518,17 +1524,46 @@ impl Add for FoldOffset {
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for FoldOffset {
|
||||
type Output = <MultiBufferOffset as Sub>::Output;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
self.0 - rhs.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SubAssign<T> for FoldOffset
|
||||
where
|
||||
MultiBufferOffset: SubAssign<T>,
|
||||
{
|
||||
fn sub_assign(&mut self, rhs: T) {
|
||||
self.0 -= rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Add<T> for FoldOffset
|
||||
where
|
||||
MultiBufferOffset: Add<T, Output = MultiBufferOffset>,
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: T) -> Self::Output {
|
||||
Self(self.0 + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for FoldOffset {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.0 += rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for FoldOffset {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 - rhs.0)
|
||||
impl<T> AddAssign<T> for FoldOffset
|
||||
where
|
||||
MultiBufferOffset: AddAssign<T>,
|
||||
{
|
||||
fn add_assign(&mut self, rhs: T) {
|
||||
self.0 += rhs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1538,7 +1573,7 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for FoldOffset {
|
||||
}
|
||||
|
||||
fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
|
||||
self.0 += &summary.output.len;
|
||||
self.0 += summary.output.len;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1558,7 +1593,7 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayOffset {
|
||||
}
|
||||
|
||||
fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
|
||||
self.0 += &summary.input.len;
|
||||
self.0 += summary.input.len;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1596,12 +1631,12 @@ mod tests {
|
||||
edits,
|
||||
&[
|
||||
FoldEdit {
|
||||
old: FoldOffset(2)..FoldOffset(16),
|
||||
new: FoldOffset(2)..FoldOffset(5),
|
||||
old: FoldOffset(MultiBufferOffset(2))..FoldOffset(MultiBufferOffset(16)),
|
||||
new: FoldOffset(MultiBufferOffset(2))..FoldOffset(MultiBufferOffset(5)),
|
||||
},
|
||||
FoldEdit {
|
||||
old: FoldOffset(18)..FoldOffset(29),
|
||||
new: FoldOffset(7)..FoldOffset(10)
|
||||
old: FoldOffset(MultiBufferOffset(18))..FoldOffset(MultiBufferOffset(29)),
|
||||
new: FoldOffset(MultiBufferOffset(7))..FoldOffset(MultiBufferOffset(10)),
|
||||
},
|
||||
]
|
||||
);
|
||||
@@ -1626,12 +1661,12 @@ mod tests {
|
||||
edits,
|
||||
&[
|
||||
FoldEdit {
|
||||
old: FoldOffset(0)..FoldOffset(1),
|
||||
new: FoldOffset(0)..FoldOffset(3),
|
||||
old: FoldOffset(MultiBufferOffset(0))..FoldOffset(MultiBufferOffset(1)),
|
||||
new: FoldOffset(MultiBufferOffset(0))..FoldOffset(MultiBufferOffset(3)),
|
||||
},
|
||||
FoldEdit {
|
||||
old: FoldOffset(6)..FoldOffset(6),
|
||||
new: FoldOffset(8)..FoldOffset(11),
|
||||
old: FoldOffset(MultiBufferOffset(6))..FoldOffset(MultiBufferOffset(6)),
|
||||
new: FoldOffset(MultiBufferOffset(8))..FoldOffset(MultiBufferOffset(11)),
|
||||
},
|
||||
]
|
||||
);
|
||||
@@ -1668,15 +1703,24 @@ mod tests {
|
||||
let mut map = FoldMap::new(inlay_snapshot.clone()).0;
|
||||
|
||||
let (mut writer, _, _) = map.write(inlay_snapshot.clone(), vec![]);
|
||||
writer.fold(vec![(5..8, FoldPlaceholder::test())]);
|
||||
writer.fold(vec![(
|
||||
MultiBufferOffset(5)..MultiBufferOffset(8),
|
||||
FoldPlaceholder::test(),
|
||||
)]);
|
||||
let (snapshot, _) = map.read(inlay_snapshot.clone(), vec![]);
|
||||
assert_eq!(snapshot.text(), "abcde⋯ijkl");
|
||||
|
||||
// Create an fold adjacent to the start of the first fold.
|
||||
let (mut writer, _, _) = map.write(inlay_snapshot.clone(), vec![]);
|
||||
writer.fold(vec![
|
||||
(0..1, FoldPlaceholder::test()),
|
||||
(2..5, FoldPlaceholder::test()),
|
||||
(
|
||||
MultiBufferOffset(0)..MultiBufferOffset(1),
|
||||
FoldPlaceholder::test(),
|
||||
),
|
||||
(
|
||||
MultiBufferOffset(2)..MultiBufferOffset(5),
|
||||
FoldPlaceholder::test(),
|
||||
),
|
||||
]);
|
||||
let (snapshot, _) = map.read(inlay_snapshot.clone(), vec![]);
|
||||
assert_eq!(snapshot.text(), "⋯b⋯ijkl");
|
||||
@@ -1684,8 +1728,14 @@ mod tests {
|
||||
// Create an fold adjacent to the end of the first fold.
|
||||
let (mut writer, _, _) = map.write(inlay_snapshot.clone(), vec![]);
|
||||
writer.fold(vec![
|
||||
(11..11, FoldPlaceholder::test()),
|
||||
(8..10, FoldPlaceholder::test()),
|
||||
(
|
||||
MultiBufferOffset(11)..MultiBufferOffset(11),
|
||||
FoldPlaceholder::test(),
|
||||
),
|
||||
(
|
||||
MultiBufferOffset(8)..MultiBufferOffset(10),
|
||||
FoldPlaceholder::test(),
|
||||
),
|
||||
]);
|
||||
let (snapshot, _) = map.read(inlay_snapshot.clone(), vec![]);
|
||||
assert_eq!(snapshot.text(), "⋯b⋯kl");
|
||||
@@ -1697,15 +1747,25 @@ mod tests {
|
||||
// Create two adjacent folds.
|
||||
let (mut writer, _, _) = map.write(inlay_snapshot.clone(), vec![]);
|
||||
writer.fold(vec![
|
||||
(0..2, FoldPlaceholder::test()),
|
||||
(2..5, FoldPlaceholder::test()),
|
||||
(
|
||||
MultiBufferOffset(0)..MultiBufferOffset(2),
|
||||
FoldPlaceholder::test(),
|
||||
),
|
||||
(
|
||||
MultiBufferOffset(2)..MultiBufferOffset(5),
|
||||
FoldPlaceholder::test(),
|
||||
),
|
||||
]);
|
||||
let (snapshot, _) = map.read(inlay_snapshot, vec![]);
|
||||
assert_eq!(snapshot.text(), "⋯fghijkl");
|
||||
|
||||
// Edit within one of the folds.
|
||||
let buffer_snapshot = buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit([(0..1, "12345")], None, cx);
|
||||
buffer.edit(
|
||||
[(MultiBufferOffset(0)..MultiBufferOffset(1), "12345")],
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
buffer.snapshot(cx)
|
||||
});
|
||||
let (inlay_snapshot, inlay_edits) =
|
||||
@@ -1849,7 +1909,7 @@ mod tests {
|
||||
for fold_range in map.merged_folds().into_iter().rev() {
|
||||
let fold_inlay_start = inlay_snapshot.to_inlay_offset(fold_range.start);
|
||||
let fold_inlay_end = inlay_snapshot.to_inlay_offset(fold_range.end);
|
||||
expected_text.replace_range(fold_inlay_start.0..fold_inlay_end.0, "⋯");
|
||||
expected_text.replace_range(fold_inlay_start.0.0..fold_inlay_end.0.0, "⋯");
|
||||
}
|
||||
|
||||
assert_eq!(snapshot.text(), expected_text);
|
||||
@@ -1898,7 +1958,7 @@ mod tests {
|
||||
.chars()
|
||||
.count();
|
||||
let mut fold_point = FoldPoint::new(0, 0);
|
||||
let mut fold_offset = FoldOffset(0);
|
||||
let mut fold_offset = FoldOffset(MultiBufferOffset(0));
|
||||
let mut char_column = 0;
|
||||
for c in expected_text.chars() {
|
||||
let inlay_point = fold_point.to_inlay_point(&snapshot);
|
||||
@@ -1944,18 +2004,18 @@ mod tests {
|
||||
|
||||
for _ in 0..5 {
|
||||
let mut start = snapshot.clip_offset(
|
||||
FoldOffset(rng.random_range(0..=snapshot.len().0)),
|
||||
FoldOffset(rng.random_range(MultiBufferOffset(0)..=snapshot.len().0)),
|
||||
Bias::Left,
|
||||
);
|
||||
let mut end = snapshot.clip_offset(
|
||||
FoldOffset(rng.random_range(0..=snapshot.len().0)),
|
||||
FoldOffset(rng.random_range(MultiBufferOffset(0)..=snapshot.len().0)),
|
||||
Bias::Right,
|
||||
);
|
||||
if start > end {
|
||||
mem::swap(&mut start, &mut end);
|
||||
}
|
||||
|
||||
let text = &expected_text[start.0..end.0];
|
||||
let text = &expected_text[start.0.0..end.0.0];
|
||||
assert_eq!(
|
||||
snapshot
|
||||
.chunks(start..end, false, Highlights::default())
|
||||
@@ -2004,9 +2064,12 @@ mod tests {
|
||||
}
|
||||
|
||||
for _ in 0..5 {
|
||||
let end =
|
||||
buffer_snapshot.clip_offset(rng.random_range(0..=buffer_snapshot.len()), Right);
|
||||
let start = buffer_snapshot.clip_offset(rng.random_range(0..=end), Left);
|
||||
let end = buffer_snapshot.clip_offset(
|
||||
rng.random_range(MultiBufferOffset(0)..=buffer_snapshot.len()),
|
||||
Right,
|
||||
);
|
||||
let start =
|
||||
buffer_snapshot.clip_offset(rng.random_range(MultiBufferOffset(0)..=end), Left);
|
||||
let expected_folds = map
|
||||
.snapshot
|
||||
.folds
|
||||
@@ -2046,7 +2109,7 @@ mod tests {
|
||||
let bytes = start.to_offset(&snapshot)..end.to_offset(&snapshot);
|
||||
assert_eq!(
|
||||
snapshot.text_summary_for_range(lines),
|
||||
TextSummary::from(&text[bytes.start.0..bytes.end.0])
|
||||
MBTextSummary::from(&text[bytes.start.0.0..bytes.end.0.0])
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2054,8 +2117,8 @@ mod tests {
|
||||
for (snapshot, edits) in snapshot_edits.drain(..) {
|
||||
let new_text = snapshot.text();
|
||||
for edit in edits {
|
||||
let old_bytes = edit.new.start.0..edit.new.start.0 + edit.old_len().0;
|
||||
let new_bytes = edit.new.start.0..edit.new.end.0;
|
||||
let old_bytes = edit.new.start.0.0..edit.new.start.0.0 + edit.old_len();
|
||||
let new_bytes = edit.new.start.0.0..edit.new.end.0.0;
|
||||
text.replace_range(old_bytes, &new_text[new_bytes]);
|
||||
}
|
||||
|
||||
@@ -2126,7 +2189,7 @@ mod tests {
|
||||
|
||||
// Get all chunks and verify their bitmaps
|
||||
let chunks = snapshot.chunks(
|
||||
FoldOffset(0)..FoldOffset(snapshot.len().0),
|
||||
FoldOffset(MultiBufferOffset(0))..FoldOffset(snapshot.len().0),
|
||||
false,
|
||||
Highlights::default(),
|
||||
);
|
||||
@@ -2195,7 +2258,7 @@ mod tests {
|
||||
}
|
||||
|
||||
impl FoldMap {
|
||||
fn merged_folds(&self) -> Vec<Range<usize>> {
|
||||
fn merged_folds(&self) -> Vec<Range<MultiBufferOffset>> {
|
||||
let inlay_snapshot = self.snapshot.inlay_snapshot.clone();
|
||||
let buffer = &inlay_snapshot.buffer;
|
||||
let mut folds = self.snapshot.folds.items(buffer);
|
||||
@@ -2236,8 +2299,12 @@ mod tests {
|
||||
let buffer = &inlay_snapshot.buffer;
|
||||
let mut to_unfold = Vec::new();
|
||||
for _ in 0..rng.random_range(1..=3) {
|
||||
let end = buffer.clip_offset(rng.random_range(0..=buffer.len()), Right);
|
||||
let start = buffer.clip_offset(rng.random_range(0..=end), Left);
|
||||
let end = buffer.clip_offset(
|
||||
rng.random_range(MultiBufferOffset(0)..=buffer.len()),
|
||||
Right,
|
||||
);
|
||||
let start =
|
||||
buffer.clip_offset(rng.random_range(MultiBufferOffset(0)..=end), Left);
|
||||
to_unfold.push(start..end);
|
||||
}
|
||||
let inclusive = rng.random();
|
||||
@@ -2252,8 +2319,12 @@ mod tests {
|
||||
let buffer = &inlay_snapshot.buffer;
|
||||
let mut to_fold = Vec::new();
|
||||
for _ in 0..rng.random_range(1..=2) {
|
||||
let end = buffer.clip_offset(rng.random_range(0..=buffer.len()), Right);
|
||||
let start = buffer.clip_offset(rng.random_range(0..=end), Left);
|
||||
let end = buffer.clip_offset(
|
||||
rng.random_range(MultiBufferOffset(0)..=buffer.len()),
|
||||
Right,
|
||||
);
|
||||
let start =
|
||||
buffer.clip_offset(rng.random_range(MultiBufferOffset(0)..=end), Left);
|
||||
to_fold.push((start..end, FoldPlaceholder::test()));
|
||||
}
|
||||
log::info!("folding {:?}", to_fold);
|
||||
|
||||
@@ -4,7 +4,10 @@ use crate::{
|
||||
};
|
||||
use collections::BTreeSet;
|
||||
use language::{Chunk, Edit, Point, TextSummary};
|
||||
use multi_buffer::{MultiBufferRow, MultiBufferRows, MultiBufferSnapshot, RowInfo, ToOffset};
|
||||
use multi_buffer::{
|
||||
MBTextSummary, MultiBufferOffset, MultiBufferRow, MultiBufferRows, MultiBufferSnapshot,
|
||||
RowInfo, ToOffset,
|
||||
};
|
||||
use project::InlayId;
|
||||
use std::{
|
||||
cmp,
|
||||
@@ -42,7 +45,7 @@ impl std::ops::Deref for InlaySnapshot {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum Transform {
|
||||
Isomorphic(TextSummary),
|
||||
Isomorphic(MBTextSummary),
|
||||
Inlay(Inlay),
|
||||
}
|
||||
|
||||
@@ -56,8 +59,8 @@ impl sum_tree::Item for Transform {
|
||||
output: *summary,
|
||||
},
|
||||
Transform::Inlay(inlay) => TransformSummary {
|
||||
input: TextSummary::default(),
|
||||
output: inlay.text().summary(),
|
||||
input: MBTextSummary::default(),
|
||||
output: MBTextSummary::from(inlay.text().summary()),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -65,8 +68,8 @@ impl sum_tree::Item for Transform {
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct TransformSummary {
|
||||
input: TextSummary,
|
||||
output: TextSummary,
|
||||
input: MBTextSummary,
|
||||
output: MBTextSummary,
|
||||
}
|
||||
|
||||
impl sum_tree::ContextLessSummary for TransformSummary {
|
||||
@@ -75,15 +78,15 @@ impl sum_tree::ContextLessSummary for TransformSummary {
|
||||
}
|
||||
|
||||
fn add_summary(&mut self, other: &Self) {
|
||||
self.input += &other.input;
|
||||
self.output += &other.output;
|
||||
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);
|
||||
pub struct InlayOffset(pub MultiBufferOffset);
|
||||
|
||||
impl Add for InlayOffset {
|
||||
type Output = Self;
|
||||
@@ -94,10 +97,30 @@ impl Add for InlayOffset {
|
||||
}
|
||||
|
||||
impl Sub for InlayOffset {
|
||||
type Output = Self;
|
||||
type Output = <MultiBufferOffset as Sub>::Output;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 - rhs.0)
|
||||
self.0 - rhs.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SubAssign<T> for InlayOffset
|
||||
where
|
||||
MultiBufferOffset: SubAssign<T>,
|
||||
{
|
||||
fn sub_assign(&mut self, rhs: T) {
|
||||
self.0 -= rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Add<T> for InlayOffset
|
||||
where
|
||||
MultiBufferOffset: Add<T, Output = MultiBufferOffset>,
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: T) -> Self::Output {
|
||||
Self(self.0 + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,9 +130,12 @@ impl AddAssign for InlayOffset {
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for InlayOffset {
|
||||
fn sub_assign(&mut self, rhs: Self) {
|
||||
self.0 -= rhs.0;
|
||||
impl<T> AddAssign<T> for InlayOffset
|
||||
where
|
||||
MultiBufferOffset: AddAssign<T>,
|
||||
{
|
||||
fn add_assign(&mut self, rhs: T) {
|
||||
self.0 += rhs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +145,7 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayOffset {
|
||||
}
|
||||
|
||||
fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
|
||||
self.0 += &summary.output.len;
|
||||
self.0 += summary.output.len;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,13 +178,13 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for InlayPoint {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::Dimension<'a, TransformSummary> for usize {
|
||||
impl<'a> sum_tree::Dimension<'a, TransformSummary> for MultiBufferOffset {
|
||||
fn zero(_cx: ()) -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn add_summary(&mut self, summary: &'a TransformSummary, _: ()) {
|
||||
*self += &summary.input.len;
|
||||
*self += summary.input.len;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +207,7 @@ pub struct InlayBufferRows<'a> {
|
||||
}
|
||||
|
||||
pub struct InlayChunks<'a> {
|
||||
transforms: Cursor<'a, 'static, Transform, Dimensions<InlayOffset, usize>>,
|
||||
transforms: Cursor<'a, 'static, Transform, Dimensions<InlayOffset, MultiBufferOffset>>,
|
||||
buffer_chunks: CustomHighlightsChunks<'a>,
|
||||
buffer_chunk: Option<Chunk<'a>>,
|
||||
inlay_chunks: Option<text::ChunkWithBitmaps<'a>>,
|
||||
@@ -332,12 +358,12 @@ impl<'a> Iterator for InlayChunks<'a> {
|
||||
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 {
|
||||
if offset_in_inlay < range.start {
|
||||
next_inlay_highlight_endpoint = range.start - offset_in_inlay;
|
||||
} else if offset_in_inlay >= range.end {
|
||||
next_inlay_highlight_endpoint = usize::MAX;
|
||||
} else {
|
||||
next_inlay_highlight_endpoint = range.end - offset_in_inlay.0;
|
||||
next_inlay_highlight_endpoint = range.end - offset_in_inlay;
|
||||
highlight_style = highlight_style
|
||||
.map(|highlight| highlight.highlight(*style))
|
||||
.or_else(|| Some(*style));
|
||||
@@ -350,7 +376,7 @@ impl<'a> Iterator for InlayChunks<'a> {
|
||||
let start = offset_in_inlay;
|
||||
let end = cmp::min(self.max_output_offset, self.transforms.end().0)
|
||||
- self.transforms.start().0;
|
||||
let chunks = inlay.text().chunks_in_range(start.0..end.0);
|
||||
let chunks = inlay.text().chunks_in_range(start..end);
|
||||
text::ChunkWithBitmaps(chunks)
|
||||
});
|
||||
let ChunkBitmaps {
|
||||
@@ -488,7 +514,7 @@ impl InlayMap {
|
||||
pub fn sync(
|
||||
&mut self,
|
||||
buffer_snapshot: MultiBufferSnapshot,
|
||||
mut buffer_edits: Vec<text::Edit<usize>>,
|
||||
mut buffer_edits: Vec<text::Edit<MultiBufferOffset>>,
|
||||
) -> (InlaySnapshot, Vec<InlayEdit>) {
|
||||
let snapshot = &mut self.snapshot;
|
||||
|
||||
@@ -519,7 +545,7 @@ impl InlayMap {
|
||||
let mut new_transforms = SumTree::default();
|
||||
let mut cursor = snapshot
|
||||
.transforms
|
||||
.cursor::<Dimensions<usize, InlayOffset>>(());
|
||||
.cursor::<Dimensions<MultiBufferOffset, 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), ());
|
||||
@@ -531,11 +557,9 @@ impl InlayMap {
|
||||
}
|
||||
|
||||
// Remove all the inlays and transforms contained by the edit.
|
||||
let old_start =
|
||||
cursor.start().1 + InlayOffset(buffer_edit.old.start - cursor.start().0);
|
||||
let old_start = cursor.start().1 + (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);
|
||||
let old_end = cursor.start().1 + (buffer_edit.old.end - cursor.start().0);
|
||||
|
||||
// Push the unchanged prefix.
|
||||
let prefix_start = new_transforms.summary().input.len;
|
||||
@@ -687,7 +711,10 @@ impl InlayMap {
|
||||
let snapshot = &mut self.snapshot;
|
||||
for i in 0..rng.random_range(1..=5) {
|
||||
if self.inlays.is_empty() || rng.random() {
|
||||
let position = snapshot.buffer.random_byte_range(0, rng).start;
|
||||
let position = snapshot
|
||||
.buffer
|
||||
.random_byte_range(MultiBufferOffset(0), rng)
|
||||
.start;
|
||||
let bias = if rng.random() {
|
||||
Bias::Left
|
||||
} else {
|
||||
@@ -740,9 +767,11 @@ impl InlayMap {
|
||||
|
||||
impl InlaySnapshot {
|
||||
pub fn to_point(&self, offset: InlayOffset) -> InlayPoint {
|
||||
let (start, _, item) = self
|
||||
.transforms
|
||||
.find::<Dimensions<InlayOffset, InlayPoint, usize>, _>((), &offset, Bias::Right);
|
||||
let (start, _, item) = self.transforms.find::<Dimensions<
|
||||
InlayOffset,
|
||||
InlayPoint,
|
||||
MultiBufferOffset,
|
||||
>, _>((), &offset, Bias::Right);
|
||||
let overshoot = offset.0 - start.0.0;
|
||||
match item {
|
||||
Some(Transform::Isomorphic(_)) => {
|
||||
@@ -801,22 +830,24 @@ impl InlaySnapshot {
|
||||
None => self.buffer.max_point(),
|
||||
}
|
||||
}
|
||||
pub fn to_buffer_offset(&self, offset: InlayOffset) -> usize {
|
||||
let (start, _, item) =
|
||||
self.transforms
|
||||
.find::<Dimensions<InlayOffset, usize>, _>((), &offset, Bias::Right);
|
||||
pub fn to_buffer_offset(&self, offset: InlayOffset) -> MultiBufferOffset {
|
||||
let (start, _, item) = self
|
||||
.transforms
|
||||
.find::<Dimensions<InlayOffset, MultiBufferOffset>, _>((), &offset, Bias::Right);
|
||||
match item {
|
||||
Some(Transform::Isomorphic(_)) => {
|
||||
let overshoot = offset - start.0;
|
||||
start.1 + overshoot.0
|
||||
start.1 + overshoot
|
||||
}
|
||||
Some(Transform::Inlay(_)) => start.1,
|
||||
None => self.buffer.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_inlay_offset(&self, offset: usize) -> InlayOffset {
|
||||
let mut cursor = self.transforms.cursor::<Dimensions<usize, InlayOffset>>(());
|
||||
pub fn to_inlay_offset(&self, offset: MultiBufferOffset) -> InlayOffset {
|
||||
let mut cursor = self
|
||||
.transforms
|
||||
.cursor::<Dimensions<MultiBufferOffset, InlayOffset>>(());
|
||||
cursor.seek(&offset, Bias::Left);
|
||||
loop {
|
||||
match cursor.item() {
|
||||
@@ -973,14 +1004,16 @@ impl InlaySnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn text_summary(&self) -> TextSummary {
|
||||
pub fn text_summary(&self) -> MBTextSummary {
|
||||
self.transforms.summary().output
|
||||
}
|
||||
|
||||
pub fn text_summary_for_range(&self, range: Range<InlayOffset>) -> TextSummary {
|
||||
let mut summary = TextSummary::default();
|
||||
pub fn text_summary_for_range(&self, range: Range<InlayOffset>) -> MBTextSummary {
|
||||
let mut summary = MBTextSummary::default();
|
||||
|
||||
let mut cursor = self.transforms.cursor::<Dimensions<InlayOffset, usize>>(());
|
||||
let mut cursor = self
|
||||
.transforms
|
||||
.cursor::<Dimensions<InlayOffset, MultiBufferOffset>>(());
|
||||
cursor.seek(&range.start, Bias::Right);
|
||||
|
||||
let overshoot = range.start.0 - cursor.start().0.0;
|
||||
@@ -996,7 +1029,12 @@ impl InlaySnapshot {
|
||||
Some(Transform::Inlay(inlay)) => {
|
||||
let suffix_start = overshoot;
|
||||
let suffix_end = cmp::min(cursor.end().0, range.end).0 - cursor.start().0.0;
|
||||
summary = inlay.text().cursor(suffix_start).summary(suffix_end);
|
||||
summary = MBTextSummary::from(
|
||||
inlay
|
||||
.text()
|
||||
.cursor(suffix_start)
|
||||
.summary::<TextSummary>(suffix_end),
|
||||
);
|
||||
cursor.next();
|
||||
}
|
||||
None => {}
|
||||
@@ -1014,7 +1052,7 @@ impl InlaySnapshot {
|
||||
let prefix_end = prefix_start + overshoot;
|
||||
summary += self
|
||||
.buffer
|
||||
.text_summary_for_range::<TextSummary, _>(prefix_start..prefix_end);
|
||||
.text_summary_for_range::<MBTextSummary, _>(prefix_start..prefix_end);
|
||||
}
|
||||
Some(Transform::Inlay(inlay)) => {
|
||||
let prefix_end = overshoot;
|
||||
@@ -1070,7 +1108,9 @@ impl InlaySnapshot {
|
||||
language_aware: bool,
|
||||
highlights: Highlights<'a>,
|
||||
) -> InlayChunks<'a> {
|
||||
let mut cursor = self.transforms.cursor::<Dimensions<InlayOffset, usize>>(());
|
||||
let mut cursor = self
|
||||
.transforms
|
||||
.cursor::<Dimensions<InlayOffset, MultiBufferOffset>>(());
|
||||
cursor.seek(&range.start, Bias::Right);
|
||||
|
||||
let buffer_range = self.to_buffer_offset(range.start)..self.to_buffer_offset(range.end);
|
||||
@@ -1122,8 +1162,8 @@ impl InlaySnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
fn push_isomorphic(sum_tree: &mut SumTree<Transform>, summary: TextSummary) {
|
||||
if summary.len == 0 {
|
||||
fn push_isomorphic(sum_tree: &mut SumTree<Transform>, summary: MBTextSummary) {
|
||||
if summary.len == MultiBufferOffset(0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1279,7 +1319,10 @@ mod tests {
|
||||
&[],
|
||||
vec![Inlay::mock_hint(
|
||||
post_inc(&mut next_inlay_id),
|
||||
buffer.read(cx).snapshot(cx).anchor_after(3),
|
||||
buffer
|
||||
.read(cx)
|
||||
.snapshot(cx)
|
||||
.anchor_after(MultiBufferOffset(3)),
|
||||
"|123|",
|
||||
)],
|
||||
);
|
||||
@@ -1335,7 +1378,15 @@ mod tests {
|
||||
|
||||
// Edits before or after the inlay should not affect it.
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit([(2..3, "x"), (3..3, "y"), (4..4, "z")], None, cx)
|
||||
buffer.edit(
|
||||
[
|
||||
(MultiBufferOffset(2)..MultiBufferOffset(3), "x"),
|
||||
(MultiBufferOffset(3)..MultiBufferOffset(3), "y"),
|
||||
(MultiBufferOffset(4)..MultiBufferOffset(4), "z"),
|
||||
],
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let (inlay_snapshot, _) = inlay_map.sync(
|
||||
buffer.read(cx).snapshot(cx),
|
||||
@@ -1344,7 +1395,13 @@ mod tests {
|
||||
assert_eq!(inlay_snapshot.text(), "abxy|123|dzefghi");
|
||||
|
||||
// An edit surrounding the inlay should invalidate it.
|
||||
buffer.update(cx, |buffer, cx| buffer.edit([(4..5, "D")], None, cx));
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit(
|
||||
[(MultiBufferOffset(4)..MultiBufferOffset(5), "D")],
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let (inlay_snapshot, _) = inlay_map.sync(
|
||||
buffer.read(cx).snapshot(cx),
|
||||
buffer_edits.consume().into_inner(),
|
||||
@@ -1356,12 +1413,18 @@ mod tests {
|
||||
vec![
|
||||
Inlay::mock_hint(
|
||||
post_inc(&mut next_inlay_id),
|
||||
buffer.read(cx).snapshot(cx).anchor_before(3),
|
||||
buffer
|
||||
.read(cx)
|
||||
.snapshot(cx)
|
||||
.anchor_before(MultiBufferOffset(3)),
|
||||
"|123|",
|
||||
),
|
||||
Inlay::edit_prediction(
|
||||
post_inc(&mut next_inlay_id),
|
||||
buffer.read(cx).snapshot(cx).anchor_after(3),
|
||||
buffer
|
||||
.read(cx)
|
||||
.snapshot(cx)
|
||||
.anchor_after(MultiBufferOffset(3)),
|
||||
"|456|",
|
||||
),
|
||||
],
|
||||
@@ -1369,7 +1432,13 @@ mod tests {
|
||||
assert_eq!(inlay_snapshot.text(), "abx|123||456|yDzefghi");
|
||||
|
||||
// Edits ending where the inlay starts should not move it if it has a left bias.
|
||||
buffer.update(cx, |buffer, cx| buffer.edit([(3..3, "JKL")], None, cx));
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit(
|
||||
[(MultiBufferOffset(3)..MultiBufferOffset(3), "JKL")],
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let (inlay_snapshot, _) = inlay_map.sync(
|
||||
buffer.read(cx).snapshot(cx),
|
||||
buffer_edits.consume().into_inner(),
|
||||
@@ -1571,17 +1640,26 @@ mod tests {
|
||||
vec![
|
||||
Inlay::mock_hint(
|
||||
post_inc(&mut next_inlay_id),
|
||||
buffer.read(cx).snapshot(cx).anchor_before(0),
|
||||
buffer
|
||||
.read(cx)
|
||||
.snapshot(cx)
|
||||
.anchor_before(MultiBufferOffset(0)),
|
||||
"|123|\n",
|
||||
),
|
||||
Inlay::mock_hint(
|
||||
post_inc(&mut next_inlay_id),
|
||||
buffer.read(cx).snapshot(cx).anchor_before(4),
|
||||
buffer
|
||||
.read(cx)
|
||||
.snapshot(cx)
|
||||
.anchor_before(MultiBufferOffset(4)),
|
||||
"|456|",
|
||||
),
|
||||
Inlay::edit_prediction(
|
||||
post_inc(&mut next_inlay_id),
|
||||
buffer.read(cx).snapshot(cx).anchor_before(7),
|
||||
buffer
|
||||
.read(cx)
|
||||
.snapshot(cx)
|
||||
.anchor_before(MultiBufferOffset(7)),
|
||||
"\n|567|\n",
|
||||
),
|
||||
],
|
||||
@@ -1658,7 +1736,7 @@ mod tests {
|
||||
.collect::<Vec<_>>();
|
||||
let mut expected_text = Rope::from(&buffer_snapshot.text());
|
||||
for (offset, inlay) in inlays.iter().rev() {
|
||||
expected_text.replace(*offset..*offset, &inlay.text().to_string());
|
||||
expected_text.replace(offset.0..offset.0, &inlay.text().to_string());
|
||||
}
|
||||
assert_eq!(inlay_snapshot.text(), expected_text.to_string());
|
||||
|
||||
@@ -1681,7 +1759,7 @@ mod tests {
|
||||
let mut text_highlights = TextHighlights::default();
|
||||
let text_highlight_count = rng.random_range(0_usize..10);
|
||||
let mut text_highlight_ranges = (0..text_highlight_count)
|
||||
.map(|_| buffer_snapshot.random_byte_range(0, &mut rng))
|
||||
.map(|_| buffer_snapshot.random_byte_range(MultiBufferOffset(0), &mut rng))
|
||||
.collect::<Vec<_>>();
|
||||
text_highlight_ranges.sort_by_key(|range| (range.start, Reverse(range.end)));
|
||||
log::info!("highlighting text ranges {text_highlight_ranges:?}");
|
||||
@@ -1744,12 +1822,13 @@ mod tests {
|
||||
}
|
||||
|
||||
for _ in 0..5 {
|
||||
let mut end = rng.random_range(0..=inlay_snapshot.len().0);
|
||||
let mut end = rng.random_range(0..=inlay_snapshot.len().0.0);
|
||||
end = expected_text.clip_offset(end, Bias::Right);
|
||||
let mut start = rng.random_range(0..=end);
|
||||
start = expected_text.clip_offset(start, Bias::Right);
|
||||
|
||||
let range = InlayOffset(start)..InlayOffset(end);
|
||||
let range =
|
||||
InlayOffset(MultiBufferOffset(start))..InlayOffset(MultiBufferOffset(end));
|
||||
log::info!("calling inlay_snapshot.chunks({range:?})");
|
||||
let actual_text = inlay_snapshot
|
||||
.chunks(
|
||||
@@ -1771,25 +1850,27 @@ mod tests {
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
inlay_snapshot.text_summary_for_range(InlayOffset(start)..InlayOffset(end)),
|
||||
expected_text.slice(start..end).summary()
|
||||
inlay_snapshot.text_summary_for_range(
|
||||
InlayOffset(MultiBufferOffset(start))..InlayOffset(MultiBufferOffset(end))
|
||||
),
|
||||
MBTextSummary::from(expected_text.slice(start..end).summary())
|
||||
);
|
||||
}
|
||||
|
||||
for edit in inlay_edits {
|
||||
prev_inlay_text.replace_range(
|
||||
edit.new.start.0..edit.new.start.0 + edit.old_len().0,
|
||||
&inlay_snapshot.text()[edit.new.start.0..edit.new.end.0],
|
||||
edit.new.start.0.0..edit.new.start.0.0 + edit.old_len(),
|
||||
&inlay_snapshot.text()[edit.new.start.0.0..edit.new.end.0.0],
|
||||
);
|
||||
}
|
||||
assert_eq!(prev_inlay_text, inlay_snapshot.text());
|
||||
|
||||
assert_eq!(expected_text.max_point(), inlay_snapshot.max_point().0);
|
||||
assert_eq!(expected_text.len(), inlay_snapshot.len().0);
|
||||
assert_eq!(expected_text.len(), inlay_snapshot.len().0.0);
|
||||
|
||||
let mut buffer_point = Point::default();
|
||||
let mut inlay_point = inlay_snapshot.to_inlay_point(buffer_point);
|
||||
let mut buffer_chars = buffer_snapshot.chars_at(0);
|
||||
let mut buffer_chars = buffer_snapshot.chars_at(MultiBufferOffset(0));
|
||||
loop {
|
||||
// Ensure conversion from buffer coordinates to inlay coordinates
|
||||
// is consistent.
|
||||
@@ -1930,7 +2011,7 @@ mod tests {
|
||||
|
||||
// Get all chunks and verify their bitmaps
|
||||
let chunks = snapshot.chunks(
|
||||
InlayOffset(0)..InlayOffset(snapshot.len().0),
|
||||
InlayOffset(MultiBufferOffset(0))..snapshot.len(),
|
||||
false,
|
||||
Highlights::default(),
|
||||
);
|
||||
@@ -2064,7 +2145,7 @@ mod tests {
|
||||
// Collect chunks - this previously would panic
|
||||
let chunks: Vec<_> = inlay_snapshot
|
||||
.chunks(
|
||||
InlayOffset(0)..InlayOffset(inlay_snapshot.len().0),
|
||||
InlayOffset(MultiBufferOffset(0))..inlay_snapshot.len(),
|
||||
false,
|
||||
highlights,
|
||||
)
|
||||
@@ -2178,7 +2259,7 @@ mod tests {
|
||||
|
||||
let chunks: Vec<_> = inlay_snapshot
|
||||
.chunks(
|
||||
InlayOffset(0)..InlayOffset(inlay_snapshot.len().0),
|
||||
InlayOffset(MultiBufferOffset(0))..inlay_snapshot.len(),
|
||||
false,
|
||||
highlights,
|
||||
)
|
||||
|
||||
@@ -648,6 +648,7 @@ mod tests {
|
||||
inlay_map::InlayMap,
|
||||
},
|
||||
};
|
||||
use multi_buffer::MultiBufferOffset;
|
||||
use rand::{Rng, prelude::StdRng};
|
||||
use util;
|
||||
|
||||
@@ -1156,7 +1157,7 @@ mod tests {
|
||||
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot);
|
||||
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot);
|
||||
let chunks = fold_snapshot.chunks(
|
||||
FoldOffset(0)..fold_snapshot.len(),
|
||||
FoldOffset(MultiBufferOffset(0))..fold_snapshot.len(),
|
||||
false,
|
||||
Default::default(),
|
||||
);
|
||||
@@ -1318,7 +1319,7 @@ mod tests {
|
||||
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot);
|
||||
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot);
|
||||
let chunks = fold_snapshot.chunks(
|
||||
FoldOffset(0)..fold_snapshot.len(),
|
||||
FoldOffset(MultiBufferOffset(0))..fold_snapshot.len(),
|
||||
false,
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
+317
-202
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,7 @@ use language_settings::Formatter;
|
||||
use languages::markdown_lang;
|
||||
use languages::rust_lang;
|
||||
use lsp::CompletionParams;
|
||||
use multi_buffer::{IndentGuide, PathKey};
|
||||
use multi_buffer::{IndentGuide, MultiBufferOffset, MultiBufferOffsetUtf16, PathKey};
|
||||
use parking_lot::Mutex;
|
||||
use pretty_assertions::{assert_eq, assert_ne};
|
||||
use project::{
|
||||
@@ -197,7 +197,7 @@ fn test_edit_events(cx: &mut TestAppContext) {
|
||||
// No event is emitted when the mutation is a no-op.
|
||||
_ = editor2.update(cx, |editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([0..0])
|
||||
s.select_ranges([MultiBufferOffset(0)..MultiBufferOffset(0)])
|
||||
});
|
||||
|
||||
editor.backspace(&Backspace, window, cx);
|
||||
@@ -222,7 +222,7 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
|
||||
_ = editor.update(cx, |editor, window, cx| {
|
||||
editor.start_transaction_at(now, window, cx);
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([2..4])
|
||||
s.select_ranges([MultiBufferOffset(2)..MultiBufferOffset(4)])
|
||||
});
|
||||
|
||||
editor.insert("cd", window, cx);
|
||||
@@ -230,38 +230,46 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
|
||||
assert_eq!(editor.text(cx), "12cd56");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
vec![4..4]
|
||||
vec![MultiBufferOffset(4)..MultiBufferOffset(4)]
|
||||
);
|
||||
|
||||
editor.start_transaction_at(now, window, cx);
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([4..5])
|
||||
s.select_ranges([MultiBufferOffset(4)..MultiBufferOffset(5)])
|
||||
});
|
||||
editor.insert("e", window, cx);
|
||||
editor.end_transaction_at(now, cx);
|
||||
assert_eq!(editor.text(cx), "12cde6");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
vec![5..5]
|
||||
vec![MultiBufferOffset(5)..MultiBufferOffset(5)]
|
||||
);
|
||||
|
||||
now += group_interval + Duration::from_millis(1);
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([2..2])
|
||||
s.select_ranges([MultiBufferOffset(2)..MultiBufferOffset(2)])
|
||||
});
|
||||
|
||||
// Simulate an edit in another editor
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.start_transaction_at(now, cx);
|
||||
buffer.edit([(0..1, "a")], None, cx);
|
||||
buffer.edit([(1..1, "b")], None, cx);
|
||||
buffer.edit(
|
||||
[(MultiBufferOffset(0)..MultiBufferOffset(1), "a")],
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
buffer.edit(
|
||||
[(MultiBufferOffset(1)..MultiBufferOffset(1), "b")],
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
buffer.end_transaction_at(now, cx);
|
||||
});
|
||||
|
||||
assert_eq!(editor.text(cx), "ab2cde6");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
vec![3..3]
|
||||
vec![MultiBufferOffset(3)..MultiBufferOffset(3)]
|
||||
);
|
||||
|
||||
// Last transaction happened past the group interval in a different editor.
|
||||
@@ -270,7 +278,7 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
|
||||
assert_eq!(editor.text(cx), "12cde6");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
vec![2..2]
|
||||
vec![MultiBufferOffset(2)..MultiBufferOffset(2)]
|
||||
);
|
||||
|
||||
// First two transactions happened within the group interval in this editor.
|
||||
@@ -280,7 +288,7 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
|
||||
assert_eq!(editor.text(cx), "123456");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
vec![0..0]
|
||||
vec![MultiBufferOffset(0)..MultiBufferOffset(0)]
|
||||
);
|
||||
|
||||
// Redo the first two transactions together.
|
||||
@@ -288,7 +296,7 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
|
||||
assert_eq!(editor.text(cx), "12cde6");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
vec![5..5]
|
||||
vec![MultiBufferOffset(5)..MultiBufferOffset(5)]
|
||||
);
|
||||
|
||||
// Redo the last transaction on its own.
|
||||
@@ -296,7 +304,7 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
|
||||
assert_eq!(editor.text(cx), "ab2cde6");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
vec![6..6]
|
||||
vec![MultiBufferOffset(6)..MultiBufferOffset(6)]
|
||||
);
|
||||
|
||||
// Test empty transactions.
|
||||
@@ -329,7 +337,9 @@ fn test_ime_composition(cx: &mut TestAppContext) {
|
||||
assert_eq!(editor.text(cx), "äbcde");
|
||||
assert_eq!(
|
||||
editor.marked_text_ranges(cx),
|
||||
Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
|
||||
Some(vec![
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(0))..MultiBufferOffsetUtf16(OffsetUtf16(1))
|
||||
])
|
||||
);
|
||||
|
||||
// Finalize IME composition.
|
||||
@@ -349,7 +359,9 @@ fn test_ime_composition(cx: &mut TestAppContext) {
|
||||
editor.replace_and_mark_text_in_range(Some(0..1), "à", None, window, cx);
|
||||
assert_eq!(
|
||||
editor.marked_text_ranges(cx),
|
||||
Some(vec![OffsetUtf16(0)..OffsetUtf16(1)])
|
||||
Some(vec![
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(0))..MultiBufferOffsetUtf16(OffsetUtf16(1))
|
||||
])
|
||||
);
|
||||
|
||||
// Undoing during an IME composition cancels it.
|
||||
@@ -362,7 +374,9 @@ fn test_ime_composition(cx: &mut TestAppContext) {
|
||||
assert_eq!(editor.text(cx), "ābcdè");
|
||||
assert_eq!(
|
||||
editor.marked_text_ranges(cx),
|
||||
Some(vec![OffsetUtf16(4)..OffsetUtf16(5)])
|
||||
Some(vec![
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(4))..MultiBufferOffsetUtf16(OffsetUtf16(5))
|
||||
])
|
||||
);
|
||||
|
||||
// Finalize IME composition with an invalid replacement range, ensuring it gets clipped.
|
||||
@@ -373,9 +387,9 @@ fn test_ime_composition(cx: &mut TestAppContext) {
|
||||
// Start a new IME composition with multiple cursors.
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([
|
||||
OffsetUtf16(1)..OffsetUtf16(1),
|
||||
OffsetUtf16(3)..OffsetUtf16(3),
|
||||
OffsetUtf16(5)..OffsetUtf16(5),
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(1))..MultiBufferOffsetUtf16(OffsetUtf16(1)),
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(3))..MultiBufferOffsetUtf16(OffsetUtf16(3)),
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(5))..MultiBufferOffsetUtf16(OffsetUtf16(5)),
|
||||
])
|
||||
});
|
||||
editor.replace_and_mark_text_in_range(Some(4..5), "XYZ", None, window, cx);
|
||||
@@ -383,9 +397,9 @@ fn test_ime_composition(cx: &mut TestAppContext) {
|
||||
assert_eq!(
|
||||
editor.marked_text_ranges(cx),
|
||||
Some(vec![
|
||||
OffsetUtf16(0)..OffsetUtf16(3),
|
||||
OffsetUtf16(4)..OffsetUtf16(7),
|
||||
OffsetUtf16(8)..OffsetUtf16(11)
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(0))..MultiBufferOffsetUtf16(OffsetUtf16(3)),
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(4))..MultiBufferOffsetUtf16(OffsetUtf16(7)),
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(8))..MultiBufferOffsetUtf16(OffsetUtf16(11))
|
||||
])
|
||||
);
|
||||
|
||||
@@ -395,9 +409,9 @@ fn test_ime_composition(cx: &mut TestAppContext) {
|
||||
assert_eq!(
|
||||
editor.marked_text_ranges(cx),
|
||||
Some(vec![
|
||||
OffsetUtf16(1)..OffsetUtf16(2),
|
||||
OffsetUtf16(5)..OffsetUtf16(6),
|
||||
OffsetUtf16(9)..OffsetUtf16(10)
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(1))..MultiBufferOffsetUtf16(OffsetUtf16(2)),
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(5))..MultiBufferOffsetUtf16(OffsetUtf16(6)),
|
||||
MultiBufferOffsetUtf16(OffsetUtf16(9))..MultiBufferOffsetUtf16(OffsetUtf16(10))
|
||||
])
|
||||
);
|
||||
|
||||
@@ -757,7 +771,11 @@ fn test_clone(cx: &mut TestAppContext) {
|
||||
|
||||
_ = editor.update(cx, |editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges(selection_ranges.clone())
|
||||
s.select_ranges(
|
||||
selection_ranges
|
||||
.iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end)),
|
||||
)
|
||||
});
|
||||
editor.fold_creases(
|
||||
vec![
|
||||
@@ -794,9 +812,11 @@ fn test_clone(cx: &mut TestAppContext) {
|
||||
);
|
||||
assert_eq!(
|
||||
cloned_snapshot
|
||||
.folds_in_range(0..text.len())
|
||||
.folds_in_range(MultiBufferOffset(0)..MultiBufferOffset(text.len()))
|
||||
.collect::<Vec<_>>(),
|
||||
snapshot
|
||||
.folds_in_range(MultiBufferOffset(0)..MultiBufferOffset(text.len()))
|
||||
.collect::<Vec<_>>(),
|
||||
snapshot.folds_in_range(0..text.len()).collect::<Vec<_>>(),
|
||||
);
|
||||
assert_set_eq!(
|
||||
cloned_editor
|
||||
@@ -1418,7 +1438,11 @@ fn test_fold_at_level(cx: &mut TestAppContext) {
|
||||
);
|
||||
|
||||
editor.change_selections(SelectionEffects::default(), window, cx, |s| {
|
||||
s.select_ranges(positions)
|
||||
s.select_ranges(
|
||||
positions
|
||||
.iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end)),
|
||||
)
|
||||
});
|
||||
|
||||
editor.fold_at_level(&FoldAtLevel(2), window, cx);
|
||||
@@ -3700,7 +3724,11 @@ fn test_insert_with_old_selections(cx: &mut TestAppContext) {
|
||||
let buffer = MultiBuffer::build_simple("a( X ), b( Y ), c( Z )", cx);
|
||||
let mut editor = build_editor(buffer, window, cx);
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([3..4, 11..12, 19..20])
|
||||
s.select_ranges([
|
||||
MultiBufferOffset(3)..MultiBufferOffset(4),
|
||||
MultiBufferOffset(11)..MultiBufferOffset(12),
|
||||
MultiBufferOffset(19)..MultiBufferOffset(20),
|
||||
])
|
||||
});
|
||||
editor
|
||||
});
|
||||
@@ -3708,12 +3736,24 @@ fn test_insert_with_old_selections(cx: &mut TestAppContext) {
|
||||
_ = editor.update(cx, |editor, window, cx| {
|
||||
// Edit the buffer directly, deleting ranges surrounding the editor's selections
|
||||
editor.buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], None, cx);
|
||||
buffer.edit(
|
||||
[
|
||||
(MultiBufferOffset(2)..MultiBufferOffset(5), ""),
|
||||
(MultiBufferOffset(10)..MultiBufferOffset(13), ""),
|
||||
(MultiBufferOffset(18)..MultiBufferOffset(21), ""),
|
||||
],
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
assert_eq!(buffer.read(cx).text(), "a(), b(), c()".unindent());
|
||||
});
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
&[2..2, 7..7, 12..12],
|
||||
&[
|
||||
MultiBufferOffset(2)..MultiBufferOffset(2),
|
||||
MultiBufferOffset(7)..MultiBufferOffset(7),
|
||||
MultiBufferOffset(12)..MultiBufferOffset(12)
|
||||
],
|
||||
);
|
||||
|
||||
editor.insert("Z", window, cx);
|
||||
@@ -3722,7 +3762,11 @@ fn test_insert_with_old_selections(cx: &mut TestAppContext) {
|
||||
// The selections are moved after the inserted characters
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
&[3..3, 9..9, 15..15],
|
||||
&[
|
||||
MultiBufferOffset(3)..MultiBufferOffset(3),
|
||||
MultiBufferOffset(9)..MultiBufferOffset(9),
|
||||
MultiBufferOffset(15)..MultiBufferOffset(15)
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -4692,7 +4736,7 @@ async fn test_custom_newlines_cause_no_false_positive_diffs(
|
||||
assert_eq!(
|
||||
snapshot
|
||||
.buffer_snapshot()
|
||||
.diff_hunks_in_range(0..snapshot.buffer_snapshot().len())
|
||||
.diff_hunks_in_range(MultiBufferOffset(0)..snapshot.buffer_snapshot().len())
|
||||
.collect::<Vec<_>>(),
|
||||
Vec::new(),
|
||||
"Should not have any diffs for files with custom newlines"
|
||||
@@ -5964,27 +6008,27 @@ fn test_transpose(cx: &mut TestAppContext) {
|
||||
let mut editor = build_editor(MultiBuffer::build_simple("abc", cx), window, cx);
|
||||
editor.set_style(EditorStyle::default(), window, cx);
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([1..1])
|
||||
s.select_ranges([MultiBufferOffset(1)..MultiBufferOffset(1)])
|
||||
});
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "bac");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[2..2]
|
||||
[MultiBufferOffset(2)..MultiBufferOffset(2)]
|
||||
);
|
||||
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "bca");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[3..3]
|
||||
[MultiBufferOffset(3)..MultiBufferOffset(3)]
|
||||
);
|
||||
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "bac");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[3..3]
|
||||
[MultiBufferOffset(3)..MultiBufferOffset(3)]
|
||||
);
|
||||
|
||||
editor
|
||||
@@ -5994,37 +6038,37 @@ fn test_transpose(cx: &mut TestAppContext) {
|
||||
let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), window, cx);
|
||||
editor.set_style(EditorStyle::default(), window, cx);
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([3..3])
|
||||
s.select_ranges([MultiBufferOffset(3)..MultiBufferOffset(3)])
|
||||
});
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "acb\nde");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[3..3]
|
||||
[MultiBufferOffset(3)..MultiBufferOffset(3)]
|
||||
);
|
||||
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([4..4])
|
||||
s.select_ranges([MultiBufferOffset(4)..MultiBufferOffset(4)])
|
||||
});
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "acbd\ne");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[5..5]
|
||||
[MultiBufferOffset(5)..MultiBufferOffset(5)]
|
||||
);
|
||||
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "acbde\n");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[6..6]
|
||||
[MultiBufferOffset(6)..MultiBufferOffset(6)]
|
||||
);
|
||||
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "acbd\ne");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[6..6]
|
||||
[MultiBufferOffset(6)..MultiBufferOffset(6)]
|
||||
);
|
||||
|
||||
editor
|
||||
@@ -6034,41 +6078,62 @@ fn test_transpose(cx: &mut TestAppContext) {
|
||||
let mut editor = build_editor(MultiBuffer::build_simple("abc\nde", cx), window, cx);
|
||||
editor.set_style(EditorStyle::default(), window, cx);
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([1..1, 2..2, 4..4])
|
||||
s.select_ranges([
|
||||
MultiBufferOffset(1)..MultiBufferOffset(1),
|
||||
MultiBufferOffset(2)..MultiBufferOffset(2),
|
||||
MultiBufferOffset(4)..MultiBufferOffset(4),
|
||||
])
|
||||
});
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "bacd\ne");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[2..2, 3..3, 5..5]
|
||||
[
|
||||
MultiBufferOffset(2)..MultiBufferOffset(2),
|
||||
MultiBufferOffset(3)..MultiBufferOffset(3),
|
||||
MultiBufferOffset(5)..MultiBufferOffset(5)
|
||||
]
|
||||
);
|
||||
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "bcade\n");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[3..3, 4..4, 6..6]
|
||||
[
|
||||
MultiBufferOffset(3)..MultiBufferOffset(3),
|
||||
MultiBufferOffset(4)..MultiBufferOffset(4),
|
||||
MultiBufferOffset(6)..MultiBufferOffset(6)
|
||||
]
|
||||
);
|
||||
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "bcda\ne");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[4..4, 6..6]
|
||||
[
|
||||
MultiBufferOffset(4)..MultiBufferOffset(4),
|
||||
MultiBufferOffset(6)..MultiBufferOffset(6)
|
||||
]
|
||||
);
|
||||
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "bcade\n");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[4..4, 6..6]
|
||||
[
|
||||
MultiBufferOffset(4)..MultiBufferOffset(4),
|
||||
MultiBufferOffset(6)..MultiBufferOffset(6)
|
||||
]
|
||||
);
|
||||
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "bcaed\n");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[5..5, 6..6]
|
||||
[
|
||||
MultiBufferOffset(5)..MultiBufferOffset(5),
|
||||
MultiBufferOffset(6)..MultiBufferOffset(6)
|
||||
]
|
||||
);
|
||||
|
||||
editor
|
||||
@@ -6078,27 +6143,27 @@ fn test_transpose(cx: &mut TestAppContext) {
|
||||
let mut editor = build_editor(MultiBuffer::build_simple("🍐🏀✋", cx), window, cx);
|
||||
editor.set_style(EditorStyle::default(), window, cx);
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([4..4])
|
||||
s.select_ranges([MultiBufferOffset(4)..MultiBufferOffset(4)])
|
||||
});
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "🏀🍐✋");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[8..8]
|
||||
[MultiBufferOffset(8)..MultiBufferOffset(8)]
|
||||
);
|
||||
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "🏀✋🍐");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[11..11]
|
||||
[MultiBufferOffset(11)..MultiBufferOffset(11)]
|
||||
);
|
||||
|
||||
editor.transpose(&Default::default(), window, cx);
|
||||
assert_eq!(editor.text(cx), "🏀🍐✋");
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
[11..11]
|
||||
[MultiBufferOffset(11)..MultiBufferOffset(11)]
|
||||
);
|
||||
|
||||
editor
|
||||
@@ -9731,7 +9796,11 @@ async fn test_autoindent(cx: &mut TestAppContext) {
|
||||
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([5..5, 8..8, 9..9])
|
||||
s.select_ranges([
|
||||
MultiBufferOffset(5)..MultiBufferOffset(5),
|
||||
MultiBufferOffset(8)..MultiBufferOffset(8),
|
||||
MultiBufferOffset(9)..MultiBufferOffset(9),
|
||||
])
|
||||
});
|
||||
editor.newline(&Newline, window, cx);
|
||||
assert_eq!(editor.text(cx), "fn a(\n \n) {\n \n}\n");
|
||||
@@ -9796,7 +9865,11 @@ async fn test_autoindent_disabled(cx: &mut TestAppContext) {
|
||||
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([5..5, 8..8, 9..9])
|
||||
s.select_ranges([
|
||||
MultiBufferOffset(5)..MultiBufferOffset(5),
|
||||
MultiBufferOffset(8)..MultiBufferOffset(8),
|
||||
MultiBufferOffset(9)..MultiBufferOffset(9),
|
||||
])
|
||||
});
|
||||
editor.newline(&Newline, window, cx);
|
||||
assert_eq!(
|
||||
@@ -10453,7 +10526,7 @@ async fn test_autoclose_with_embedded_language(cx: &mut TestAppContext) {
|
||||
let snapshot = editor.snapshot(window, cx);
|
||||
let cursors = editor
|
||||
.selections
|
||||
.ranges::<usize>(&editor.display_snapshot(cx));
|
||||
.ranges::<MultiBufferOffset>(&editor.display_snapshot(cx));
|
||||
let languages = cursors
|
||||
.iter()
|
||||
.map(|c| snapshot.language_at(c.start).unwrap().name())
|
||||
@@ -11143,17 +11216,26 @@ async fn test_snippet_placeholder_choices(cx: &mut TestAppContext) {
|
||||
let snippet = Snippet::parse("type ${1|,i32,u32|} = $2").unwrap();
|
||||
|
||||
editor
|
||||
.insert_snippet(&insertion_ranges, snippet, window, cx)
|
||||
.insert_snippet(
|
||||
&insertion_ranges
|
||||
.iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end))
|
||||
.collect::<Vec<_>>(),
|
||||
snippet,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
fn assert(editor: &mut Editor, cx: &mut Context<Editor>, marked_text: &str) {
|
||||
let (expected_text, selection_ranges) = marked_text_ranges(marked_text, false);
|
||||
assert_eq!(editor.text(cx), expected_text);
|
||||
assert_eq!(
|
||||
editor
|
||||
.selections
|
||||
.ranges::<usize>(&editor.display_snapshot(cx)),
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
selection_ranges
|
||||
.iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end))
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11177,10 +11259,11 @@ async fn test_snippet_tabstop_navigation_with_placeholders(cx: &mut TestAppConte
|
||||
let (expected_text, selection_ranges) = marked_text_ranges(marked_text, false);
|
||||
assert_eq!(editor.text(cx), expected_text);
|
||||
assert_eq!(
|
||||
editor
|
||||
.selections
|
||||
.ranges::<usize>(&editor.display_snapshot(cx)),
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
selection_ranges
|
||||
.iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end))
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11198,7 +11281,15 @@ async fn test_snippet_tabstop_navigation_with_placeholders(cx: &mut TestAppConte
|
||||
let snippet = Snippet::parse("type ${1|,i32,u32|} = $2; $3").unwrap();
|
||||
|
||||
editor
|
||||
.insert_snippet(&insertion_ranges, snippet, window, cx)
|
||||
.insert_snippet(
|
||||
&insertion_ranges
|
||||
.iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end))
|
||||
.collect::<Vec<_>>(),
|
||||
snippet,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_state(
|
||||
@@ -11646,7 +11737,7 @@ async fn test_redo_after_noop_format(cx: &mut TestAppContext) {
|
||||
});
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::default(), window, cx, |s| {
|
||||
s.select_ranges([0..0])
|
||||
s.select_ranges([MultiBufferOffset(0)..MultiBufferOffset(0)])
|
||||
});
|
||||
});
|
||||
assert!(!cx.read(|cx| editor.is_dirty(cx)));
|
||||
@@ -11812,7 +11903,7 @@ async fn test_multibuffer_format_during_save(cx: &mut TestAppContext) {
|
||||
SelectionEffects::scroll(Autoscroll::Next),
|
||||
window,
|
||||
cx,
|
||||
|s| s.select_ranges(Some(1..2)),
|
||||
|s| s.select_ranges(Some(MultiBufferOffset(1)..MultiBufferOffset(2))),
|
||||
);
|
||||
editor.insert("|one|two|three|", window, cx);
|
||||
});
|
||||
@@ -11822,7 +11913,7 @@ async fn test_multibuffer_format_during_save(cx: &mut TestAppContext) {
|
||||
SelectionEffects::scroll(Autoscroll::Next),
|
||||
window,
|
||||
cx,
|
||||
|s| s.select_ranges(Some(60..70)),
|
||||
|s| s.select_ranges(Some(MultiBufferOffset(60)..MultiBufferOffset(70))),
|
||||
);
|
||||
editor.insert("|four|five|six|", window, cx);
|
||||
});
|
||||
@@ -11990,7 +12081,7 @@ async fn test_autosave_with_dirty_buffers(cx: &mut TestAppContext) {
|
||||
SelectionEffects::scroll(Autoscroll::Next),
|
||||
window,
|
||||
cx,
|
||||
|s| s.select_ranges(Some(10..10)),
|
||||
|s| s.select_ranges(Some(MultiBufferOffset(10)..MultiBufferOffset(10))),
|
||||
);
|
||||
editor.insert("// edited", window, cx);
|
||||
});
|
||||
@@ -13428,7 +13519,7 @@ async fn test_signature_help(cx: &mut TestAppContext) {
|
||||
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([0..0])
|
||||
s.select_ranges([MultiBufferOffset(0)..MultiBufferOffset(0)])
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16413,7 +16504,11 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
|
||||
);
|
||||
assert_eq!(editor.text(cx), expected_text);
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges(selection_ranges)
|
||||
s.select_ranges(
|
||||
selection_ranges
|
||||
.iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end)),
|
||||
)
|
||||
});
|
||||
|
||||
editor.handle_input("X", window, cx);
|
||||
@@ -16431,6 +16526,9 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
expected_selections
|
||||
.iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end))
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
editor.newline(&Newline, window, cx);
|
||||
@@ -16451,6 +16549,9 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
expected_selections
|
||||
.iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end))
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -16826,7 +16927,7 @@ async fn test_following(cx: &mut TestAppContext) {
|
||||
// Update the selections only
|
||||
_ = leader.update(cx, |leader, window, cx| {
|
||||
leader.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([1..1])
|
||||
s.select_ranges([MultiBufferOffset(1)..MultiBufferOffset(1)])
|
||||
});
|
||||
});
|
||||
follower
|
||||
@@ -16844,7 +16945,7 @@ async fn test_following(cx: &mut TestAppContext) {
|
||||
_ = follower.update(cx, |follower, _, cx| {
|
||||
assert_eq!(
|
||||
follower.selections.ranges(&follower.display_snapshot(cx)),
|
||||
vec![1..1]
|
||||
vec![MultiBufferOffset(1)..MultiBufferOffset(1)]
|
||||
);
|
||||
});
|
||||
assert!(*is_still_following.borrow());
|
||||
@@ -16879,7 +16980,7 @@ async fn test_following(cx: &mut TestAppContext) {
|
||||
// via autoscroll, not via the leader's exact scroll position.
|
||||
_ = leader.update(cx, |leader, window, cx| {
|
||||
leader.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([0..0])
|
||||
s.select_ranges([MultiBufferOffset(0)..MultiBufferOffset(0)])
|
||||
});
|
||||
leader.request_autoscroll(Autoscroll::newest(), cx);
|
||||
leader.set_scroll_position(gpui::Point::new(1.5, 3.5), window, cx);
|
||||
@@ -16900,7 +17001,7 @@ async fn test_following(cx: &mut TestAppContext) {
|
||||
assert_eq!(follower.scroll_position(cx), gpui::Point::new(1.5, 0.0));
|
||||
assert_eq!(
|
||||
follower.selections.ranges(&follower.display_snapshot(cx)),
|
||||
vec![0..0]
|
||||
vec![MultiBufferOffset(0)..MultiBufferOffset(0)]
|
||||
);
|
||||
});
|
||||
assert!(*is_still_following.borrow());
|
||||
@@ -16908,7 +17009,7 @@ async fn test_following(cx: &mut TestAppContext) {
|
||||
// Creating a pending selection that precedes another selection
|
||||
_ = leader.update(cx, |leader, window, cx| {
|
||||
leader.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([1..1])
|
||||
s.select_ranges([MultiBufferOffset(1)..MultiBufferOffset(1)])
|
||||
});
|
||||
leader.begin_selection(DisplayPoint::new(DisplayRow(0), 0), true, 1, window, cx);
|
||||
});
|
||||
@@ -16927,7 +17028,10 @@ async fn test_following(cx: &mut TestAppContext) {
|
||||
_ = follower.update(cx, |follower, _, cx| {
|
||||
assert_eq!(
|
||||
follower.selections.ranges(&follower.display_snapshot(cx)),
|
||||
vec![0..0, 1..1]
|
||||
vec![
|
||||
MultiBufferOffset(0)..MultiBufferOffset(0),
|
||||
MultiBufferOffset(1)..MultiBufferOffset(1)
|
||||
]
|
||||
);
|
||||
});
|
||||
assert!(*is_still_following.borrow());
|
||||
@@ -16951,13 +17055,17 @@ async fn test_following(cx: &mut TestAppContext) {
|
||||
_ = follower.update(cx, |follower, _, cx| {
|
||||
assert_eq!(
|
||||
follower.selections.ranges(&follower.display_snapshot(cx)),
|
||||
vec![0..2]
|
||||
vec![MultiBufferOffset(0)..MultiBufferOffset(2)]
|
||||
);
|
||||
});
|
||||
|
||||
// Scrolling locally breaks the follow
|
||||
_ = follower.update(cx, |follower, window, cx| {
|
||||
let top_anchor = follower.buffer().read(cx).read(cx).anchor_after(0);
|
||||
let top_anchor = follower
|
||||
.buffer()
|
||||
.read(cx)
|
||||
.read(cx)
|
||||
.anchor_after(MultiBufferOffset(0));
|
||||
follower.set_scroll_anchor(
|
||||
ScrollAnchor {
|
||||
anchor: top_anchor,
|
||||
@@ -19451,7 +19559,7 @@ async fn test_multibuffer_in_navigation_history(cx: &mut TestAppContext) {
|
||||
SelectionEffects::scroll(Autoscroll::Next),
|
||||
window,
|
||||
cx,
|
||||
|s| s.select_ranges(Some(1..2)),
|
||||
|s| s.select_ranges(Some(MultiBufferOffset(1)..MultiBufferOffset(2))),
|
||||
);
|
||||
editor.open_excerpts(&OpenExcerpts, window, cx);
|
||||
});
|
||||
@@ -19507,7 +19615,7 @@ async fn test_multibuffer_in_navigation_history(cx: &mut TestAppContext) {
|
||||
SelectionEffects::scroll(Autoscroll::Next),
|
||||
window,
|
||||
cx,
|
||||
|s| s.select_ranges(Some(39..40)),
|
||||
|s| s.select_ranges(Some(MultiBufferOffset(39)..MultiBufferOffset(40))),
|
||||
);
|
||||
editor.open_excerpts(&OpenExcerpts, window, cx);
|
||||
});
|
||||
@@ -19567,7 +19675,7 @@ async fn test_multibuffer_in_navigation_history(cx: &mut TestAppContext) {
|
||||
SelectionEffects::scroll(Autoscroll::Next),
|
||||
window,
|
||||
cx,
|
||||
|s| s.select_ranges(Some(70..70)),
|
||||
|s| s.select_ranges(Some(MultiBufferOffset(70)..MultiBufferOffset(70))),
|
||||
);
|
||||
editor.open_excerpts(&OpenExcerpts, window, cx);
|
||||
});
|
||||
@@ -22357,7 +22465,7 @@ async fn test_find_enclosing_node_with_task(cx: &mut TestAppContext) {
|
||||
(buffer.read(cx).remote_id(), 3),
|
||||
RunnableTasks {
|
||||
templates: vec![],
|
||||
offset: snapshot.anchor_before(43),
|
||||
offset: snapshot.anchor_before(MultiBufferOffset(43)),
|
||||
column: 0,
|
||||
extra_variables: HashMap::default(),
|
||||
context_range: BufferOffset(43)..BufferOffset(85),
|
||||
@@ -22367,7 +22475,7 @@ async fn test_find_enclosing_node_with_task(cx: &mut TestAppContext) {
|
||||
(buffer.read(cx).remote_id(), 8),
|
||||
RunnableTasks {
|
||||
templates: vec![],
|
||||
offset: snapshot.anchor_before(86),
|
||||
offset: snapshot.anchor_before(MultiBufferOffset(86)),
|
||||
column: 0,
|
||||
extra_variables: HashMap::default(),
|
||||
context_range: BufferOffset(86)..BufferOffset(191),
|
||||
@@ -25749,7 +25857,10 @@ fn assert_selection_ranges(marked_text: &str, editor: &mut Editor, cx: &mut Cont
|
||||
assert_eq!(editor.text(cx), text);
|
||||
assert_eq!(
|
||||
editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
ranges,
|
||||
ranges
|
||||
.iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end))
|
||||
.collect::<Vec<_>>(),
|
||||
"Assert selections are {}",
|
||||
marked_text
|
||||
);
|
||||
@@ -25995,10 +26106,12 @@ pub fn handle_completion_request(
|
||||
vec![complete_from_marker.clone(), replace_range_marker.clone()],
|
||||
);
|
||||
|
||||
let complete_from_position =
|
||||
cx.to_lsp(marked_ranges.remove(&complete_from_marker).unwrap()[0].start);
|
||||
let complete_from_position = cx.to_lsp(MultiBufferOffset(
|
||||
marked_ranges.remove(&complete_from_marker).unwrap()[0].start,
|
||||
));
|
||||
let range = marked_ranges.remove(&replace_range_marker).unwrap()[0].clone();
|
||||
let replace_range =
|
||||
cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
|
||||
cx.to_lsp_range(MultiBufferOffset(range.start)..MultiBufferOffset(range.end));
|
||||
|
||||
let mut request =
|
||||
cx.set_request_handler::<lsp::request::Completion, _, _>(move |url, params, _| {
|
||||
@@ -26059,13 +26172,18 @@ pub fn handle_completion_request_with_insert_and_replace(
|
||||
],
|
||||
);
|
||||
|
||||
let complete_from_position =
|
||||
cx.to_lsp(marked_ranges.remove(&complete_from_marker).unwrap()[0].start);
|
||||
let complete_from_position = cx.to_lsp(MultiBufferOffset(
|
||||
marked_ranges.remove(&complete_from_marker).unwrap()[0].start,
|
||||
));
|
||||
let range = marked_ranges.remove(&replace_range_marker).unwrap()[0].clone();
|
||||
let replace_range =
|
||||
cx.to_lsp_range(marked_ranges.remove(&replace_range_marker).unwrap()[0].clone());
|
||||
cx.to_lsp_range(MultiBufferOffset(range.start)..MultiBufferOffset(range.end));
|
||||
|
||||
let insert_range = match marked_ranges.remove(&insert_range_marker) {
|
||||
Some(ranges) if !ranges.is_empty() => cx.to_lsp_range(ranges[0].clone()),
|
||||
Some(ranges) if !ranges.is_empty() => {
|
||||
let range1 = ranges[0].clone();
|
||||
cx.to_lsp_range(MultiBufferOffset(range1.start)..MultiBufferOffset(range1.end))
|
||||
}
|
||||
_ => lsp::Range {
|
||||
start: replace_range.start,
|
||||
end: complete_from_position,
|
||||
@@ -26115,7 +26233,10 @@ fn handle_resolve_completion_request(
|
||||
.iter()
|
||||
.map(|(marked_string, new_text)| {
|
||||
let (_, marked_ranges) = marked_text_ranges(marked_string, false);
|
||||
let replace_range = cx.to_lsp_range(marked_ranges[0].clone());
|
||||
let replace_range = cx.to_lsp_range(
|
||||
MultiBufferOffset(marked_ranges[0].start)
|
||||
..MultiBufferOffset(marked_ranges[0].end),
|
||||
);
|
||||
lsp::TextEdit::new(replace_range, new_text.to_string())
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
@@ -26199,7 +26320,7 @@ fn assert_hunk_revert(
|
||||
let snapshot = editor.snapshot(window, cx);
|
||||
let reverted_hunk_statuses = snapshot
|
||||
.buffer_snapshot()
|
||||
.diff_hunks_in_range(0..snapshot.buffer_snapshot().len())
|
||||
.diff_hunks_in_range(MultiBufferOffset(0)..snapshot.buffer_snapshot().len())
|
||||
.map(|hunk| hunk.status().kind)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -26823,7 +26944,9 @@ async fn test_newline_replacement_in_single_line(cx: &mut TestAppContext) {
|
||||
editor.update(cx, |editor, cx| {
|
||||
assert_eq!(editor.display_text(cx), "oops⋯⋯wow⋯");
|
||||
});
|
||||
editor.update(cx, |editor, cx| editor.edit([(3..5, "")], cx));
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.edit([(MultiBufferOffset(3)..MultiBufferOffset(5), "")], cx)
|
||||
});
|
||||
cx.run_until_parked();
|
||||
editor.update(cx, |editor, cx| {
|
||||
assert_eq!(editor.display_text(cx), "oop⋯wow⋯");
|
||||
@@ -27895,7 +28018,7 @@ async fn test_multibuffer_selections_with_folding(cx: &mut TestAppContext) {
|
||||
// Scenario 1: Unfolded buffers, position cursor on "2", select all matches, then insert
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.change_selections(None.into(), window, cx, |s| {
|
||||
s.select_ranges([2..3]);
|
||||
s.select_ranges([MultiBufferOffset(2)..MultiBufferOffset(3)]);
|
||||
});
|
||||
});
|
||||
cx.assert_excerpts_with_selections(indoc! {"
|
||||
@@ -27952,7 +28075,7 @@ async fn test_multibuffer_selections_with_folding(cx: &mut TestAppContext) {
|
||||
// Select "2" and select all matches
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.change_selections(None.into(), window, cx, |s| {
|
||||
s.select_ranges([2..3]);
|
||||
s.select_ranges([MultiBufferOffset(2)..MultiBufferOffset(3)]);
|
||||
});
|
||||
editor
|
||||
.select_all_matches(&SelectAllMatches, window, cx)
|
||||
@@ -28003,7 +28126,7 @@ async fn test_multibuffer_selections_with_folding(cx: &mut TestAppContext) {
|
||||
// Select "2" and select all matches
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.change_selections(None.into(), window, cx, |s| {
|
||||
s.select_ranges([2..3]);
|
||||
s.select_ranges([MultiBufferOffset(2)..MultiBufferOffset(3)]);
|
||||
});
|
||||
editor
|
||||
.select_all_matches(&SelectAllMatches, window, cx)
|
||||
|
||||
@@ -67,7 +67,7 @@ impl<'a> sum_tree::Dimension<'a, GitBlameEntrySummary> for u32 {
|
||||
struct GitBlameBuffer {
|
||||
entries: SumTree<GitBlameEntry>,
|
||||
buffer_snapshot: BufferSnapshot,
|
||||
buffer_edits: text::Subscription,
|
||||
buffer_edits: text::Subscription<usize>,
|
||||
commit_details: HashMap<Oid, ParsedCommitMessage>,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::{Editor, RangeToAnchorExt};
|
||||
use gpui::{Context, HighlightStyle, Window};
|
||||
use language::CursorShape;
|
||||
use multi_buffer::MultiBufferOffset;
|
||||
use theme::ActiveTheme;
|
||||
|
||||
enum MatchingBracketHighlight {}
|
||||
@@ -15,7 +16,7 @@ impl Editor {
|
||||
|
||||
let snapshot = self.snapshot(window, cx);
|
||||
let buffer_snapshot = snapshot.buffer_snapshot();
|
||||
let newest_selection = self.selections.newest::<usize>(&snapshot);
|
||||
let newest_selection = self.selections.newest::<MultiBufferOffset>(&snapshot);
|
||||
// Don't highlight brackets if the selection isn't empty
|
||||
if !newest_selection.is_empty() {
|
||||
return;
|
||||
|
||||
@@ -738,6 +738,7 @@ mod tests {
|
||||
use gpui::Modifiers;
|
||||
use indoc::indoc;
|
||||
use lsp::request::{GotoDefinition, GotoTypeDefinition};
|
||||
use multi_buffer::MultiBufferOffset;
|
||||
use settings::InlayHintSettingsContent;
|
||||
use util::{assert_set_eq, path};
|
||||
use workspace::item::Item;
|
||||
@@ -1067,8 +1068,8 @@ mod tests {
|
||||
.clone();
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
let snapshot = editor.buffer().read(cx).snapshot(cx);
|
||||
let anchor_range = snapshot.anchor_before(selection_range.start)
|
||||
..snapshot.anchor_after(selection_range.end);
|
||||
let anchor_range = snapshot.anchor_before(MultiBufferOffset(selection_range.start))
|
||||
..snapshot.anchor_after(MultiBufferOffset(selection_range.end));
|
||||
editor.change_selections(Default::default(), window, cx, |s| {
|
||||
s.set_pending_anchor_range(anchor_range, crate::SelectMode::Character)
|
||||
});
|
||||
@@ -1122,7 +1123,7 @@ mod tests {
|
||||
}
|
||||
"})[0]
|
||||
.start;
|
||||
let hint_position = cx.to_lsp(hint_start_offset);
|
||||
let hint_position = cx.to_lsp(MultiBufferOffset(hint_start_offset));
|
||||
let target_range = cx.lsp_range(indoc! {"
|
||||
struct «TestStruct»;
|
||||
|
||||
@@ -1179,8 +1180,8 @@ mod tests {
|
||||
.unwrap();
|
||||
let midpoint = cx.update_editor(|editor, window, cx| {
|
||||
let snapshot = editor.snapshot(window, cx);
|
||||
let previous_valid = inlay_range.start.to_display_point(&snapshot);
|
||||
let next_valid = inlay_range.end.to_display_point(&snapshot);
|
||||
let previous_valid = MultiBufferOffset(inlay_range.start).to_display_point(&snapshot);
|
||||
let next_valid = MultiBufferOffset(inlay_range.end).to_display_point(&snapshot);
|
||||
assert_eq!(previous_valid.row(), next_valid.row());
|
||||
assert!(previous_valid.column() < next_valid.column());
|
||||
DisplayPoint::new(
|
||||
@@ -1203,7 +1204,7 @@ mod tests {
|
||||
let buffer_snapshot = editor.buffer().update(cx, |buffer, cx| buffer.snapshot(cx));
|
||||
let expected_highlight = InlayHighlight {
|
||||
inlay: InlayId::Hint(0),
|
||||
inlay_position: buffer_snapshot.anchor_after(inlay_range.start),
|
||||
inlay_position: buffer_snapshot.anchor_after(MultiBufferOffset(inlay_range.start)),
|
||||
range: 0..hint_label.len(),
|
||||
};
|
||||
assert_set_eq!(actual_highlights, vec![&expected_highlight]);
|
||||
|
||||
@@ -17,7 +17,7 @@ use itertools::Itertools;
|
||||
use language::{DiagnosticEntry, Language, LanguageRegistry};
|
||||
use lsp::DiagnosticSeverity;
|
||||
use markdown::{Markdown, MarkdownElement, MarkdownStyle};
|
||||
use multi_buffer::{ToOffset, ToPoint};
|
||||
use multi_buffer::{MultiBufferOffset, ToOffset, ToPoint};
|
||||
use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart};
|
||||
use settings::Settings;
|
||||
use std::{borrow::Cow, cell::RefCell};
|
||||
@@ -106,7 +106,7 @@ pub fn find_hovered_hint_part(
|
||||
hovered_offset: InlayOffset,
|
||||
) -> Option<(InlayHintLabelPart, Range<InlayOffset>)> {
|
||||
if hovered_offset >= hint_start {
|
||||
let mut hovered_character = (hovered_offset - hint_start).0;
|
||||
let mut hovered_character = hovered_offset - hint_start;
|
||||
let mut part_start = hint_start;
|
||||
for part in label_parts {
|
||||
let part_len = part.value.chars().count();
|
||||
@@ -316,12 +316,12 @@ fn show_hover(
|
||||
} else {
|
||||
snapshot
|
||||
.buffer_snapshot()
|
||||
.diagnostics_with_buffer_ids_in_range::<usize>(offset..offset)
|
||||
.diagnostics_with_buffer_ids_in_range::<MultiBufferOffset>(offset..offset)
|
||||
.filter(|(_, diagnostic)| {
|
||||
Some(diagnostic.diagnostic.group_id) != active_group_id
|
||||
})
|
||||
// Find the entry with the most specific range
|
||||
.min_by_key(|(_, entry)| entry.range.len())
|
||||
.min_by_key(|(_, entry)| entry.range.end - entry.range.start)
|
||||
};
|
||||
|
||||
let diagnostic_popover = if let Some((buffer_id, local_diagnostic)) = local_diagnostic {
|
||||
@@ -1633,7 +1633,7 @@ mod tests {
|
||||
}
|
||||
"})[0]
|
||||
.start;
|
||||
let hint_position = cx.to_lsp(hint_start_offset);
|
||||
let hint_position = cx.to_lsp(MultiBufferOffset(hint_start_offset));
|
||||
let new_type_target_range = cx.lsp_range(indoc! {"
|
||||
struct TestStruct;
|
||||
|
||||
@@ -1708,8 +1708,8 @@ mod tests {
|
||||
.unwrap();
|
||||
let new_type_hint_part_hover_position = cx.update_editor(|editor, window, cx| {
|
||||
let snapshot = editor.snapshot(window, cx);
|
||||
let previous_valid = inlay_range.start.to_display_point(&snapshot);
|
||||
let next_valid = inlay_range.end.to_display_point(&snapshot);
|
||||
let previous_valid = MultiBufferOffset(inlay_range.start).to_display_point(&snapshot);
|
||||
let next_valid = MultiBufferOffset(inlay_range.end).to_display_point(&snapshot);
|
||||
assert_eq!(previous_valid.row(), next_valid.row());
|
||||
assert!(previous_valid.column() < next_valid.column());
|
||||
let exact_unclipped = DisplayPoint::new(
|
||||
@@ -1819,7 +1819,8 @@ mod tests {
|
||||
popover.symbol_range,
|
||||
RangeInEditor::Inlay(InlayHighlight {
|
||||
inlay: InlayId::Hint(0),
|
||||
inlay_position: buffer_snapshot.anchor_after(inlay_range.start),
|
||||
inlay_position: buffer_snapshot
|
||||
.anchor_after(MultiBufferOffset(inlay_range.start)),
|
||||
range: ": ".len()..": ".len() + new_type_label.len(),
|
||||
}),
|
||||
"Popover range should match the new type label part"
|
||||
@@ -1832,8 +1833,8 @@ mod tests {
|
||||
|
||||
let struct_hint_part_hover_position = cx.update_editor(|editor, window, cx| {
|
||||
let snapshot = editor.snapshot(window, cx);
|
||||
let previous_valid = inlay_range.start.to_display_point(&snapshot);
|
||||
let next_valid = inlay_range.end.to_display_point(&snapshot);
|
||||
let previous_valid = MultiBufferOffset(inlay_range.start).to_display_point(&snapshot);
|
||||
let next_valid = MultiBufferOffset(inlay_range.end).to_display_point(&snapshot);
|
||||
assert_eq!(previous_valid.row(), next_valid.row());
|
||||
assert!(previous_valid.column() < next_valid.column());
|
||||
let exact_unclipped = DisplayPoint::new(
|
||||
@@ -1873,7 +1874,8 @@ mod tests {
|
||||
popover.symbol_range,
|
||||
RangeInEditor::Inlay(InlayHighlight {
|
||||
inlay: InlayId::Hint(0),
|
||||
inlay_position: buffer_snapshot.anchor_after(inlay_range.start),
|
||||
inlay_position: buffer_snapshot
|
||||
.anchor_after(MultiBufferOffset(inlay_range.start)),
|
||||
range: ": ".len() + new_type_label.len() + "<".len()
|
||||
..": ".len() + new_type_label.len() + "<".len() + struct_label.len(),
|
||||
}),
|
||||
|
||||
@@ -645,9 +645,9 @@ impl Editor {
|
||||
)
|
||||
{
|
||||
let highlight_start =
|
||||
(part_range.start - hint_start).0 + extra_shift_left;
|
||||
(part_range.start - hint_start) + extra_shift_left;
|
||||
let highlight_end =
|
||||
(part_range.end - hint_start).0 + extra_shift_right;
|
||||
(part_range.end - hint_start) + extra_shift_right;
|
||||
let highlight = InlayHighlight {
|
||||
inlay: hovered_hint.id,
|
||||
inlay_position: hovered_hint.position,
|
||||
@@ -948,7 +948,7 @@ pub mod tests {
|
||||
use language::{Language, LanguageConfig, LanguageMatcher};
|
||||
use languages::rust_lang;
|
||||
use lsp::FakeLanguageServer;
|
||||
use multi_buffer::MultiBuffer;
|
||||
use multi_buffer::{MultiBuffer, MultiBufferOffset};
|
||||
use parking_lot::Mutex;
|
||||
use pretty_assertions::assert_eq;
|
||||
use project::{FakeFs, Project};
|
||||
@@ -1029,7 +1029,7 @@ pub mod tests {
|
||||
editor
|
||||
.update(cx, |editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([13..13])
|
||||
s.select_ranges([MultiBufferOffset(13)..MultiBufferOffset(13)])
|
||||
});
|
||||
editor.handle_input("some change", window, cx);
|
||||
})
|
||||
@@ -1429,7 +1429,7 @@ pub mod tests {
|
||||
rs_editor
|
||||
.update(cx, |editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([13..13])
|
||||
s.select_ranges([MultiBufferOffset(13)..MultiBufferOffset(13)])
|
||||
});
|
||||
editor.handle_input("some rs change", window, cx);
|
||||
})
|
||||
@@ -1461,7 +1461,7 @@ pub mod tests {
|
||||
md_editor
|
||||
.update(cx, |editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([13..13])
|
||||
s.select_ranges([MultiBufferOffset(13)..MultiBufferOffset(13)])
|
||||
});
|
||||
editor.handle_input("some md change", window, cx);
|
||||
})
|
||||
@@ -1909,7 +1909,7 @@ pub mod tests {
|
||||
editor
|
||||
.update(cx, |editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([13..13])
|
||||
s.select_ranges([MultiBufferOffset(13)..MultiBufferOffset(13)])
|
||||
});
|
||||
editor.handle_input(change_after_opening, window, cx);
|
||||
})
|
||||
@@ -1955,7 +1955,7 @@ pub mod tests {
|
||||
task_editor
|
||||
.update(&mut cx, |editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges([13..13])
|
||||
s.select_ranges([MultiBufferOffset(13)..MultiBufferOffset(13)])
|
||||
});
|
||||
editor.handle_input(async_later_change, window, cx);
|
||||
})
|
||||
@@ -2706,7 +2706,7 @@ let c = 3;"#
|
||||
let mut editor =
|
||||
Editor::for_multibuffer(multi_buffer, Some(project.clone()), window, cx);
|
||||
editor.change_selections(SelectionEffects::default(), window, cx, |s| {
|
||||
s.select_ranges([0..0])
|
||||
s.select_ranges([MultiBufferOffset(0)..MultiBufferOffset(0)])
|
||||
});
|
||||
editor
|
||||
});
|
||||
|
||||
@@ -21,6 +21,7 @@ use language::{
|
||||
SelectionGoal, proto::serialize_anchor as serialize_text_anchor,
|
||||
};
|
||||
use lsp::DiagnosticSeverity;
|
||||
use multi_buffer::MultiBufferOffset;
|
||||
use project::{
|
||||
Project, ProjectItem as _, ProjectPath, lsp_store::FormatTrigger,
|
||||
project_settings::ProjectSettings, search::SearchQuery,
|
||||
@@ -1735,7 +1736,7 @@ impl SearchableItem for Editor {
|
||||
let mut ranges = Vec::new();
|
||||
|
||||
let search_within_ranges = if search_within_ranges.is_empty() {
|
||||
vec![buffer.anchor_before(0)..buffer.anchor_after(buffer.len())]
|
||||
vec![buffer.anchor_before(MultiBufferOffset(0))..buffer.anchor_after(buffer.len())]
|
||||
} else {
|
||||
search_within_ranges
|
||||
};
|
||||
@@ -1746,7 +1747,10 @@ impl SearchableItem for Editor {
|
||||
{
|
||||
ranges.extend(
|
||||
query
|
||||
.search(search_buffer, Some(search_range.clone()))
|
||||
.search(
|
||||
search_buffer,
|
||||
Some(search_range.start.0..search_range.end.0),
|
||||
)
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|match_range| {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::{Context as _, Result, anyhow};
|
||||
use collections::HashMap;
|
||||
use gpui::{Context, Entity, Window};
|
||||
use multi_buffer::{MultiBuffer, ToOffset};
|
||||
use multi_buffer::{BufferOffset, MultiBuffer, ToOffset};
|
||||
use std::ops::Range;
|
||||
use util::ResultExt as _;
|
||||
|
||||
@@ -546,9 +546,10 @@ pub(crate) fn handle_from(
|
||||
if edit_range_offset.start != edit_range_offset.end {
|
||||
continue;
|
||||
}
|
||||
if let Some(selection) =
|
||||
buffer_selection_map.get_mut(&(edit_range_offset.start, edit_range_offset.end))
|
||||
{
|
||||
if let Some(selection) = buffer_selection_map.get_mut(&(
|
||||
BufferOffset(edit_range_offset.start),
|
||||
BufferOffset(edit_range_offset.end),
|
||||
)) {
|
||||
if selection.0.head().bias() != text::Bias::Right
|
||||
|| selection.0.tail().bias() != text::Bias::Right
|
||||
{
|
||||
@@ -621,7 +622,7 @@ mod jsx_tag_autoclose_tests {
|
||||
use super::*;
|
||||
use gpui::{AppContext as _, TestAppContext};
|
||||
use languages::language;
|
||||
use multi_buffer::ExcerptRange;
|
||||
use multi_buffer::{ExcerptRange, MultiBufferOffset};
|
||||
use text::Selection;
|
||||
|
||||
async fn test_setup(cx: &mut TestAppContext) -> EditorTestContext {
|
||||
@@ -842,9 +843,9 @@ mod jsx_tag_autoclose_tests {
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |selections| {
|
||||
selections.select(vec![
|
||||
Selection::from_offset(4),
|
||||
Selection::from_offset(9),
|
||||
Selection::from_offset(15),
|
||||
Selection::from_offset(MultiBufferOffset(4)),
|
||||
Selection::from_offset(MultiBufferOffset(9)),
|
||||
Selection::from_offset(MultiBufferOffset(15)),
|
||||
])
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use collections::HashMap;
|
||||
use gpui::{AppContext, Context, Window};
|
||||
use itertools::Itertools;
|
||||
use multi_buffer::MultiBufferOffset;
|
||||
use std::{ops::Range, time::Duration};
|
||||
use text::{AnchorRangeExt, BufferId, ToPoint};
|
||||
use util::ResultExt;
|
||||
@@ -60,7 +61,9 @@ pub(super) fn refresh_linked_ranges(
|
||||
editor
|
||||
.update(cx, |editor, cx| {
|
||||
let display_snapshot = editor.display_snapshot(cx);
|
||||
let selections = editor.selections.all::<usize>(&display_snapshot);
|
||||
let selections = editor
|
||||
.selections
|
||||
.all::<MultiBufferOffset>(&display_snapshot);
|
||||
let snapshot = display_snapshot.buffer_snapshot();
|
||||
let buffer = editor.buffer.read(cx);
|
||||
for selection in selections {
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
};
|
||||
use gpui::{Pixels, WindowTextSystem};
|
||||
use language::{CharClassifier, Point};
|
||||
use multi_buffer::{MultiBufferRow, MultiBufferSnapshot};
|
||||
use multi_buffer::{MultiBufferOffset, MultiBufferRow, MultiBufferSnapshot};
|
||||
use serde::Deserialize;
|
||||
use workspace::searchable::Direction;
|
||||
|
||||
@@ -358,28 +358,28 @@ pub fn adjust_greedy_deletion(
|
||||
|
||||
let mut whitespace_sequences = Vec::new();
|
||||
let mut current_offset = trimmed_delete_range.start;
|
||||
let mut whitespace_sequence_length = 0;
|
||||
let mut whitespace_sequence_start = 0;
|
||||
let mut whitespace_sequence_length = MultiBufferOffset(0);
|
||||
let mut whitespace_sequence_start = MultiBufferOffset(0);
|
||||
for ch in map
|
||||
.buffer_snapshot()
|
||||
.text_for_range(trimmed_delete_range.clone())
|
||||
.flat_map(str::chars)
|
||||
{
|
||||
if ch.is_whitespace() {
|
||||
if whitespace_sequence_length == 0 {
|
||||
if whitespace_sequence_length == MultiBufferOffset(0) {
|
||||
whitespace_sequence_start = current_offset;
|
||||
}
|
||||
whitespace_sequence_length += 1;
|
||||
} else {
|
||||
if whitespace_sequence_length >= 2 {
|
||||
if whitespace_sequence_length >= MultiBufferOffset(2) {
|
||||
whitespace_sequences.push((whitespace_sequence_start, current_offset));
|
||||
}
|
||||
whitespace_sequence_start = 0;
|
||||
whitespace_sequence_length = 0;
|
||||
whitespace_sequence_start = MultiBufferOffset(0);
|
||||
whitespace_sequence_length = MultiBufferOffset(0);
|
||||
}
|
||||
current_offset += ch.len_utf8();
|
||||
}
|
||||
if whitespace_sequence_length >= 2 {
|
||||
if whitespace_sequence_length >= MultiBufferOffset(2) {
|
||||
whitespace_sequences.push((whitespace_sequence_start, current_offset));
|
||||
}
|
||||
|
||||
@@ -731,7 +731,7 @@ pub fn find_preceding_boundary_trail(
|
||||
}
|
||||
|
||||
let trail = trail_offset
|
||||
.map(|trail_offset: usize| map.clip_point(trail_offset.to_display_point(map), Bias::Left));
|
||||
.map(|trail_offset| map.clip_point(trail_offset.to_display_point(map), Bias::Left));
|
||||
|
||||
(
|
||||
trail,
|
||||
@@ -779,7 +779,7 @@ pub fn find_boundary_trail(
|
||||
}
|
||||
|
||||
let trail = trail_offset
|
||||
.map(|trail_offset: usize| map.clip_point(trail_offset.to_display_point(map), Bias::Right));
|
||||
.map(|trail_offset| map.clip_point(trail_offset.to_display_point(map), Bias::Right));
|
||||
|
||||
(
|
||||
trail,
|
||||
@@ -810,8 +810,8 @@ pub fn find_boundary_exclusive(
|
||||
/// the [`DisplaySnapshot`]. The offsets are relative to the start of a buffer.
|
||||
pub fn chars_after(
|
||||
map: &DisplaySnapshot,
|
||||
mut offset: usize,
|
||||
) -> impl Iterator<Item = (char, Range<usize>)> + '_ {
|
||||
mut offset: MultiBufferOffset,
|
||||
) -> impl Iterator<Item = (char, Range<MultiBufferOffset>)> + '_ {
|
||||
map.buffer_snapshot().chars_at(offset).map(move |ch| {
|
||||
let before = offset;
|
||||
offset += ch.len_utf8();
|
||||
@@ -824,8 +824,8 @@ pub fn chars_after(
|
||||
/// the [`DisplaySnapshot`]. The offsets are relative to the start of a buffer.
|
||||
pub fn chars_before(
|
||||
map: &DisplaySnapshot,
|
||||
mut offset: usize,
|
||||
) -> impl Iterator<Item = (char, Range<usize>)> + '_ {
|
||||
mut offset: MultiBufferOffset,
|
||||
) -> impl Iterator<Item = (char, Range<MultiBufferOffset>)> + '_ {
|
||||
map.buffer_snapshot()
|
||||
.reversed_chars_at(offset)
|
||||
.map(move |ch| {
|
||||
@@ -1018,8 +1018,9 @@ mod tests {
|
||||
|
||||
// add all kinds of inlays between two word boundaries: we should be able to cross them all, when looking for another boundary
|
||||
let mut id = 0;
|
||||
let inlays = (0..buffer_snapshot.len())
|
||||
let inlays = (0..buffer_snapshot.len().0)
|
||||
.flat_map(|offset| {
|
||||
let offset = MultiBufferOffset(offset);
|
||||
[
|
||||
Inlay::edit_prediction(
|
||||
post_inc(&mut id),
|
||||
@@ -1058,7 +1059,7 @@ mod tests {
|
||||
),
|
||||
snapshot
|
||||
.buffer_snapshot()
|
||||
.offset_to_point(5)
|
||||
.offset_to_point(MultiBufferOffset(5))
|
||||
.to_display_point(&snapshot),
|
||||
"Should not stop at inlays when looking for boundaries"
|
||||
);
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
use std::{
|
||||
cmp, fmt, iter, mem,
|
||||
ops::{Deref, DerefMut, Range, Sub},
|
||||
ops::{AddAssign, Deref, DerefMut, Range, Sub},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use collections::HashMap;
|
||||
use gpui::Pixels;
|
||||
use itertools::Itertools as _;
|
||||
use language::{Bias, Point, Selection, SelectionGoal, TextDimension};
|
||||
use language::{Bias, Point, Selection, SelectionGoal};
|
||||
use multi_buffer::{MultiBufferDimension, MultiBufferOffset};
|
||||
use util::post_inc;
|
||||
|
||||
use crate::{
|
||||
Anchor, DisplayPoint, DisplayRow, ExcerptId, MultiBufferSnapshot, SelectMode, ToOffset,
|
||||
ToPoint,
|
||||
display_map::{DisplaySnapshot, ToDisplayPoint},
|
||||
movement::TextLayoutDetails,
|
||||
};
|
||||
@@ -97,7 +97,7 @@ impl SelectionsCollection {
|
||||
if self.pending.is_none() {
|
||||
self.disjoint_anchors_arc()
|
||||
} else {
|
||||
let all_offset_selections = self.all::<usize>(snapshot);
|
||||
let all_offset_selections = self.all::<MultiBufferOffset>(snapshot);
|
||||
all_offset_selections
|
||||
.into_iter()
|
||||
.map(|selection| selection_to_anchor_selection(selection, snapshot))
|
||||
@@ -113,10 +113,10 @@ impl SelectionsCollection {
|
||||
self.pending.as_mut().map(|pending| &mut pending.selection)
|
||||
}
|
||||
|
||||
pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>(
|
||||
&self,
|
||||
snapshot: &DisplaySnapshot,
|
||||
) -> Option<Selection<D>> {
|
||||
pub fn pending<D>(&self, snapshot: &DisplaySnapshot) -> Option<Selection<D>>
|
||||
where
|
||||
D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
|
||||
{
|
||||
resolve_selections_wrapping_blocks(self.pending_anchor(), &snapshot).next()
|
||||
}
|
||||
|
||||
@@ -124,9 +124,9 @@ impl SelectionsCollection {
|
||||
self.pending.as_ref().map(|pending| pending.mode.clone())
|
||||
}
|
||||
|
||||
pub fn all<'a, D>(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<D>>
|
||||
pub fn all<D>(&self, snapshot: &DisplaySnapshot) -> Vec<Selection<D>>
|
||||
where
|
||||
D: 'a + TextDimension + Ord + Sub<D, Output = D>,
|
||||
D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
|
||||
{
|
||||
let disjoint_anchors = &self.disjoint;
|
||||
let mut disjoint =
|
||||
@@ -204,13 +204,13 @@ impl SelectionsCollection {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn disjoint_in_range<'a, D>(
|
||||
pub fn disjoint_in_range<D>(
|
||||
&self,
|
||||
range: Range<Anchor>,
|
||||
snapshot: &DisplaySnapshot,
|
||||
) -> Vec<Selection<D>>
|
||||
where
|
||||
D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
|
||||
D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord + std::fmt::Debug,
|
||||
{
|
||||
let start_ix = match self
|
||||
.disjoint
|
||||
@@ -267,10 +267,10 @@ impl SelectionsCollection {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn newest<D: TextDimension + Ord + Sub<D, Output = D>>(
|
||||
&self,
|
||||
snapshot: &DisplaySnapshot,
|
||||
) -> Selection<D> {
|
||||
pub fn newest<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
|
||||
where
|
||||
D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
|
||||
{
|
||||
resolve_selections_wrapping_blocks([self.newest_anchor()], &snapshot)
|
||||
.next()
|
||||
.unwrap()
|
||||
@@ -290,10 +290,10 @@ impl SelectionsCollection {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn oldest<D: TextDimension + Ord + Sub<D, Output = D>>(
|
||||
&self,
|
||||
snapshot: &DisplaySnapshot,
|
||||
) -> Selection<D> {
|
||||
pub fn oldest<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
|
||||
where
|
||||
D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
|
||||
{
|
||||
resolve_selections_wrapping_blocks([self.oldest_anchor()], &snapshot)
|
||||
.next()
|
||||
.unwrap()
|
||||
@@ -306,27 +306,27 @@ impl SelectionsCollection {
|
||||
.unwrap_or_else(|| self.disjoint.first().cloned().unwrap())
|
||||
}
|
||||
|
||||
pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(
|
||||
&self,
|
||||
snapshot: &DisplaySnapshot,
|
||||
) -> Selection<D> {
|
||||
pub fn first<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
|
||||
where
|
||||
D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
|
||||
{
|
||||
self.all(snapshot).first().unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(
|
||||
&self,
|
||||
snapshot: &DisplaySnapshot,
|
||||
) -> Selection<D> {
|
||||
pub fn last<D>(&self, snapshot: &DisplaySnapshot) -> Selection<D>
|
||||
where
|
||||
D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
|
||||
{
|
||||
self.all(snapshot).last().unwrap().clone()
|
||||
}
|
||||
|
||||
/// Returns a list of (potentially backwards!) ranges representing the selections.
|
||||
/// Useful for test assertions, but prefer `.all()` instead.
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D>>(
|
||||
&self,
|
||||
snapshot: &DisplaySnapshot,
|
||||
) -> Vec<Range<D>> {
|
||||
pub fn ranges<D>(&self, snapshot: &DisplaySnapshot) -> Vec<Range<D>>
|
||||
where
|
||||
D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
|
||||
{
|
||||
self.all::<D>(snapshot)
|
||||
.iter()
|
||||
.map(|s| {
|
||||
@@ -509,7 +509,7 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
|
||||
};
|
||||
|
||||
if filtered_selections.is_empty() {
|
||||
let default_anchor = self.snapshot.anchor_before(0);
|
||||
let default_anchor = self.snapshot.anchor_before(MultiBufferOffset(0));
|
||||
self.collection.disjoint = Arc::from([Selection {
|
||||
id: post_inc(&mut self.collection.next_selection_id),
|
||||
start: default_anchor,
|
||||
@@ -590,7 +590,7 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
|
||||
|
||||
pub fn insert_range<T>(&mut self, range: Range<T>)
|
||||
where
|
||||
T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub<T, Output = T> + std::marker::Copy,
|
||||
T: ToOffset,
|
||||
{
|
||||
let display_map = self.display_snapshot();
|
||||
let mut selections = self.collection.all(&display_map);
|
||||
@@ -656,7 +656,8 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
|
||||
pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
|
||||
let map = self.display_snapshot();
|
||||
let resolved_selections =
|
||||
resolve_selections_wrapping_blocks::<usize, _>(&selections, &map).collect::<Vec<_>>();
|
||||
resolve_selections_wrapping_blocks::<MultiBufferOffset, _>(&selections, &map)
|
||||
.collect::<Vec<_>>();
|
||||
self.select(resolved_selections);
|
||||
}
|
||||
|
||||
@@ -673,7 +674,7 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
|
||||
|
||||
fn select_offset_ranges<I>(&mut self, ranges: I)
|
||||
where
|
||||
I: IntoIterator<Item = Range<usize>>,
|
||||
I: IntoIterator<Item = Range<MultiBufferOffset>>,
|
||||
{
|
||||
let selections = ranges
|
||||
.into_iter()
|
||||
@@ -808,13 +809,13 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
|
||||
|
||||
pub fn move_offsets_with(
|
||||
&mut self,
|
||||
mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<usize>),
|
||||
mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<MultiBufferOffset>),
|
||||
) {
|
||||
let mut changed = false;
|
||||
let display_map = self.display_snapshot();
|
||||
let selections = self
|
||||
.collection
|
||||
.all::<usize>(&display_map)
|
||||
.all::<MultiBufferOffset>(&display_map)
|
||||
.into_iter()
|
||||
.map(|selection| {
|
||||
let mut moved_selection = selection.clone();
|
||||
@@ -938,7 +939,7 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
|
||||
let map = self.display_snapshot();
|
||||
let resolved_selections =
|
||||
resolve_selections_wrapping_blocks(adjusted_disjoint.iter(), &map).collect();
|
||||
self.select::<usize>(resolved_selections);
|
||||
self.select::<MultiBufferOffset>(resolved_selections);
|
||||
}
|
||||
|
||||
if let Some(pending) = pending.as_mut() {
|
||||
@@ -981,7 +982,7 @@ impl DerefMut for MutableSelectionsCollection<'_, '_> {
|
||||
}
|
||||
|
||||
fn selection_to_anchor_selection(
|
||||
selection: Selection<usize>,
|
||||
selection: Selection<MultiBufferOffset>,
|
||||
buffer: &MultiBufferSnapshot,
|
||||
) -> Selection<Anchor> {
|
||||
let end_bias = if selection.start == selection.end {
|
||||
@@ -1054,7 +1055,7 @@ fn resolve_selections_display<'a>(
|
||||
coalesce_selections(selections)
|
||||
}
|
||||
|
||||
/// Resolves the passed in anchors to [`TextDimension`]s `D`
|
||||
/// Resolves the passed in anchors to [`MultiBufferDimension`]s `D`
|
||||
/// wrapping around blocks inbetween.
|
||||
///
|
||||
/// # Panics
|
||||
@@ -1065,7 +1066,7 @@ pub(crate) fn resolve_selections_wrapping_blocks<'a, D, I>(
|
||||
map: &'a DisplaySnapshot,
|
||||
) -> impl 'a + Iterator<Item = Selection<D>>
|
||||
where
|
||||
D: TextDimension + Ord + Sub<D, Output = D>,
|
||||
D: MultiBufferDimension + Sub + AddAssign<<D as Sub>::Output> + Ord,
|
||||
I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
|
||||
{
|
||||
// Transforms `Anchor -> DisplayPoint -> Point -> DisplayPoint -> D`
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crate::actions::ShowSignatureHelp;
|
||||
use crate::hover_popover::open_markdown_url;
|
||||
use crate::{Editor, EditorSettings, ToggleAutoSignatureHelp, hover_markdown_style};
|
||||
use crate::{BufferOffset, Editor, EditorSettings, ToggleAutoSignatureHelp, hover_markdown_style};
|
||||
use gpui::{
|
||||
App, Context, Entity, HighlightStyle, MouseButton, ScrollHandle, Size, StyledText, Task,
|
||||
TextStyle, Window, combine_highlights,
|
||||
};
|
||||
use language::BufferSnapshot;
|
||||
use markdown::{Markdown, MarkdownElement};
|
||||
use multi_buffer::{Anchor, ToOffset};
|
||||
use multi_buffer::{Anchor, MultiBufferOffset, ToOffset};
|
||||
use settings::Settings;
|
||||
use std::ops::Range;
|
||||
use text::Rope;
|
||||
@@ -82,7 +82,9 @@ impl Editor {
|
||||
if !(self.signature_help_state.is_shown() || self.auto_signature_help_enabled(cx)) {
|
||||
return false;
|
||||
}
|
||||
let newest_selection = self.selections.newest::<usize>(&self.display_snapshot(cx));
|
||||
let newest_selection = self
|
||||
.selections
|
||||
.newest::<MultiBufferOffset>(&self.display_snapshot(cx));
|
||||
let head = newest_selection.head();
|
||||
|
||||
if !newest_selection.is_empty() && head != newest_selection.tail() {
|
||||
@@ -92,14 +94,14 @@ impl Editor {
|
||||
}
|
||||
|
||||
let buffer_snapshot = self.buffer().read(cx).snapshot(cx);
|
||||
let bracket_range = |position: usize| match (position, position + 1) {
|
||||
(0, b) if b <= buffer_snapshot.len() => 0..b,
|
||||
(0, b) => 0..b - 1,
|
||||
let bracket_range = |position: MultiBufferOffset| match (position, position + 1usize) {
|
||||
(MultiBufferOffset(0), b) if b <= buffer_snapshot.len() => MultiBufferOffset(0)..b,
|
||||
(MultiBufferOffset(0), b) => MultiBufferOffset(0)..b - 1,
|
||||
(a, b) if b <= buffer_snapshot.len() => a - 1..b,
|
||||
(a, b) => a - 1..b - 1,
|
||||
};
|
||||
let not_quote_like_brackets =
|
||||
|buffer: &BufferSnapshot, start: Range<usize>, end: Range<usize>| {
|
||||
|buffer: &BufferSnapshot, start: Range<BufferOffset>, end: Range<BufferOffset>| {
|
||||
let text_start = buffer.text_for_range(start).collect::<String>();
|
||||
let text_end = buffer.text_for_range(end).collect::<String>();
|
||||
QUOTE_PAIRS
|
||||
|
||||
@@ -16,7 +16,7 @@ use gpui::{
|
||||
AppContext as _, Context, Entity, EntityId, Font, FontFeatures, FontStyle, FontWeight, Pixels,
|
||||
VisualTestContext, Window, font, size,
|
||||
};
|
||||
use multi_buffer::ToPoint;
|
||||
use multi_buffer::{MultiBufferOffset, ToPoint};
|
||||
use pretty_assertions::assert_eq;
|
||||
use project::{Project, project_settings::DiagnosticSeverity};
|
||||
use ui::{App, BorrowAppContext, px};
|
||||
@@ -78,7 +78,7 @@ pub fn marked_display_snapshot(
|
||||
let snapshot = display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let markers = markers
|
||||
.into_iter()
|
||||
.map(|offset| offset.to_display_point(&snapshot))
|
||||
.map(|offset| MultiBufferOffset(offset).to_display_point(&snapshot))
|
||||
.collect();
|
||||
|
||||
(snapshot, markers)
|
||||
@@ -94,7 +94,11 @@ pub fn select_ranges(
|
||||
let (unmarked_text, text_ranges) = marked_text_ranges(marked_text, true);
|
||||
assert_eq!(editor.text(cx), unmarked_text);
|
||||
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
|
||||
s.select_ranges(text_ranges)
|
||||
s.select_ranges(
|
||||
text_ranges
|
||||
.into_iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end)),
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -108,7 +112,12 @@ pub fn assert_text_with_selections(
|
||||
assert_eq!(editor.text(cx), unmarked_text, "text doesn't match");
|
||||
let actual = generate_marked_text(
|
||||
&editor.text(cx),
|
||||
&editor.selections.ranges(&editor.display_snapshot(cx)),
|
||||
&editor
|
||||
.selections
|
||||
.ranges::<MultiBufferOffset>(&editor.display_snapshot(cx))
|
||||
.into_iter()
|
||||
.map(|range| range.start.0..range.end.0)
|
||||
.collect::<Vec<_>>(),
|
||||
marked_text.contains("«"),
|
||||
);
|
||||
assert_eq!(actual, marked_text, "Selections don't match");
|
||||
|
||||
@@ -7,6 +7,7 @@ use std::{
|
||||
|
||||
use anyhow::Result;
|
||||
use language::{markdown_lang, rust_lang};
|
||||
use multi_buffer::MultiBufferOffset;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{Editor, ToPoint};
|
||||
@@ -333,50 +334,38 @@ impl EditorLspTestContext {
|
||||
#[track_caller]
|
||||
pub fn lsp_range(&mut self, marked_text: &str) -> lsp::Range {
|
||||
let ranges = self.ranges(marked_text);
|
||||
self.to_lsp_range(ranges[0].clone())
|
||||
self.to_lsp_range(MultiBufferOffset(ranges[0].start)..MultiBufferOffset(ranges[0].end))
|
||||
}
|
||||
|
||||
#[expect(clippy::wrong_self_convention, reason = "This is test code")]
|
||||
pub fn to_lsp_range(&mut self, range: Range<usize>) -> lsp::Range {
|
||||
pub fn to_lsp_range(&mut self, range: Range<MultiBufferOffset>) -> lsp::Range {
|
||||
use language::ToPointUtf16;
|
||||
let snapshot = self.update_editor(|editor, window, cx| editor.snapshot(window, cx));
|
||||
let start_point = range.start.to_point(&snapshot.buffer_snapshot());
|
||||
let end_point = range.end.to_point(&snapshot.buffer_snapshot());
|
||||
|
||||
self.editor(|editor, _, cx| {
|
||||
let buffer = editor.buffer().read(cx);
|
||||
let start = point_to_lsp(
|
||||
buffer
|
||||
.point_to_buffer_offset(start_point, cx)
|
||||
.unwrap()
|
||||
.1
|
||||
.to_point_utf16(&buffer.read(cx)),
|
||||
);
|
||||
let end = point_to_lsp(
|
||||
buffer
|
||||
.point_to_buffer_offset(end_point, cx)
|
||||
.unwrap()
|
||||
.1
|
||||
.to_point_utf16(&buffer.read(cx)),
|
||||
);
|
||||
|
||||
let (start_buffer, start_offset) =
|
||||
buffer.point_to_buffer_offset(start_point, cx).unwrap();
|
||||
let start = point_to_lsp(start_offset.to_point_utf16(&start_buffer.read(cx)));
|
||||
let (end_buffer, end_offset) = buffer.point_to_buffer_offset(end_point, cx).unwrap();
|
||||
let end = point_to_lsp(end_offset.to_point_utf16(&end_buffer.read(cx)));
|
||||
lsp::Range { start, end }
|
||||
})
|
||||
}
|
||||
|
||||
#[expect(clippy::wrong_self_convention, reason = "This is test code")]
|
||||
pub fn to_lsp(&mut self, offset: usize) -> lsp::Position {
|
||||
pub fn to_lsp(&mut self, offset: MultiBufferOffset) -> lsp::Position {
|
||||
use language::ToPointUtf16;
|
||||
|
||||
let snapshot = self.update_editor(|editor, window, cx| editor.snapshot(window, cx));
|
||||
let point = offset.to_point(&snapshot.buffer_snapshot());
|
||||
|
||||
self.editor(|editor, _, cx| {
|
||||
let buffer = editor.buffer().read(cx);
|
||||
point_to_lsp(
|
||||
buffer
|
||||
.point_to_buffer_offset(point, cx)
|
||||
.unwrap()
|
||||
.1
|
||||
.to_point_utf16(&buffer.read(cx)),
|
||||
)
|
||||
let (buffer, offset) = buffer.point_to_buffer_offset(point, cx).unwrap();
|
||||
point_to_lsp(offset.to_point_utf16(&buffer.read(cx)))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use gpui::{
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use language::{Buffer, BufferSnapshot, LanguageRegistry};
|
||||
use multi_buffer::{Anchor, ExcerptRange, MultiBufferRow};
|
||||
use multi_buffer::{Anchor, ExcerptRange, MultiBufferOffset, MultiBufferRow};
|
||||
use parking_lot::RwLock;
|
||||
use project::{FakeFs, Project};
|
||||
use std::{
|
||||
@@ -267,7 +267,7 @@ impl EditorTestContext {
|
||||
let snapshot = self.editor.update_in(&mut self.cx, |editor, window, cx| {
|
||||
editor.snapshot(window, cx)
|
||||
});
|
||||
ranges[0].start.to_display_point(&snapshot)
|
||||
MultiBufferOffset(ranges[0].start).to_display_point(&snapshot)
|
||||
}
|
||||
|
||||
pub fn pixel_position(&mut self, marked_text: &str) -> Point<Pixels> {
|
||||
@@ -373,7 +373,11 @@ impl EditorTestContext {
|
||||
self.editor.update_in(&mut self.cx, |editor, window, cx| {
|
||||
editor.set_text(unmarked_text, window, cx);
|
||||
editor.change_selections(Default::default(), window, cx, |s| {
|
||||
s.select_ranges(selection_ranges)
|
||||
s.select_ranges(
|
||||
selection_ranges
|
||||
.into_iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end)),
|
||||
)
|
||||
})
|
||||
});
|
||||
state_context
|
||||
@@ -390,7 +394,11 @@ impl EditorTestContext {
|
||||
self.editor.update_in(&mut self.cx, |editor, window, cx| {
|
||||
assert_eq!(editor.text(cx), unmarked_text);
|
||||
editor.change_selections(Default::default(), window, cx, |s| {
|
||||
s.select_ranges(selection_ranges)
|
||||
s.select_ranges(
|
||||
selection_ranges
|
||||
.into_iter()
|
||||
.map(|range| MultiBufferOffset(range.start)..MultiBufferOffset(range.end)),
|
||||
)
|
||||
})
|
||||
});
|
||||
state_context
|
||||
@@ -576,6 +584,7 @@ impl EditorTestContext {
|
||||
.unwrap_or_default()
|
||||
.iter()
|
||||
.map(|range| range.to_offset(&snapshot.buffer_snapshot()))
|
||||
.map(|range| range.start.0..range.end.0)
|
||||
.collect()
|
||||
});
|
||||
assert_set_eq!(actual_ranges, expected_ranges);
|
||||
@@ -591,6 +600,7 @@ impl EditorTestContext {
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|range| range.to_offset(&snapshot.buffer_snapshot()))
|
||||
.map(|range| range.start.0..range.end.0)
|
||||
.collect();
|
||||
assert_set_eq!(actual_ranges, expected_ranges);
|
||||
}
|
||||
@@ -608,14 +618,16 @@ impl EditorTestContext {
|
||||
fn editor_selections(&mut self) -> Vec<Range<usize>> {
|
||||
self.editor
|
||||
.update(&mut self.cx, |editor, cx| {
|
||||
editor.selections.all::<usize>(&editor.display_snapshot(cx))
|
||||
editor
|
||||
.selections
|
||||
.all::<MultiBufferOffset>(&editor.display_snapshot(cx))
|
||||
})
|
||||
.into_iter()
|
||||
.map(|s| {
|
||||
if s.reversed {
|
||||
s.end..s.start
|
||||
s.end.0..s.start.0
|
||||
} else {
|
||||
s.start..s.end
|
||||
s.start.0..s.end.0
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
@@ -711,7 +723,10 @@ pub fn assert_state_with_diff(
|
||||
snapshot.buffer_snapshot().clone(),
|
||||
editor
|
||||
.selections
|
||||
.ranges::<usize>(&snapshot.display_snapshot),
|
||||
.ranges::<MultiBufferOffset>(&snapshot.display_snapshot)
|
||||
.into_iter()
|
||||
.map(|range| range.start.0..range.end.0)
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user