Building, but failing test WIP

This commit is contained in:
Keith Simmons 2022-04-27 17:25:38 -07:00
parent 065734e1de
commit 04fc1d5982
14 changed files with 492 additions and 419 deletions

View file

@ -255,38 +255,41 @@ impl MultiBuffer {
self.subscriptions.subscribe()
}
pub fn edit<I, S, T>(&mut self, ranges: I, new_text: T, cx: &mut ModelContext<Self>)
pub fn edit<S, T>(&mut self, range: Range<S>, new_text: T, cx: &mut ModelContext<Self>)
where
I: IntoIterator<Item = Range<S>>,
S: ToOffset,
T: Into<String>,
T: Into<Arc<str>>,
{
self.edit_internal(ranges, new_text, false, cx)
self.edit_internal([(range, new_text)], false, cx);
}
pub fn edit_with_autoindent<I, S, T>(
&mut self,
ranges: I,
new_text: T,
cx: &mut ModelContext<Self>,
) where
I: IntoIterator<Item = Range<S>>,
pub fn edit_batched<I, S, T>(&mut self, edits: I, cx: &mut ModelContext<Self>)
where
I: IntoIterator<Item = (Range<S>, T)>,
S: ToOffset,
T: Into<String>,
T: Into<Arc<str>>,
{
self.edit_internal(ranges, new_text, true, cx)
self.edit_internal(edits, false, cx)
}
pub fn edit_with_autoindent_batched<I, S, T>(&mut self, edits: I, cx: &mut ModelContext<Self>)
where
I: IntoIterator<Item = (Range<S>, T)>,
S: ToOffset,
T: Into<Arc<str>>,
{
self.edit_internal(edits, true, cx)
}
pub fn edit_internal<I, S, T>(
&mut self,
ranges_iter: I,
new_text: T,
edits_iter: I,
autoindent: bool,
cx: &mut ModelContext<Self>,
) where
I: IntoIterator<Item = Range<S>>,
I: IntoIterator<Item = (Range<S>, T)>,
S: ToOffset,
T: Into<String>,
T: Into<Arc<str>>,
{
if self.buffers.borrow().is_empty() {
return;
@ -294,24 +297,29 @@ impl MultiBuffer {
if let Some(buffer) = self.as_singleton() {
let snapshot = self.read(cx);
let ranges = ranges_iter
.into_iter()
.map(|range| range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot));
let edits = edits_iter.into_iter().map(|(range, new_text)| {
(
range.start.to_offset(&snapshot)..range.end.to_offset(&snapshot),
new_text,
)
});
return buffer.update(cx, |buffer, cx| {
let language_name = buffer.language().map(|language| language.name());
let indent_size = cx.global::<Settings>().tab_size(language_name.as_deref());
if autoindent {
buffer.edit_with_autoindent(ranges, new_text, indent_size, cx);
buffer.edit_with_autoindent_batched(edits, indent_size, cx);
} else {
buffer.edit(ranges, new_text, cx);
buffer.edit_batched(edits, cx);
}
});
}
let snapshot = self.read(cx);
let mut buffer_edits: HashMap<usize, Vec<(Range<usize>, bool)>> = Default::default();
let mut buffer_edits: HashMap<usize, Vec<(Range<usize>, Arc<str>, bool)>> =
Default::default();
let mut cursor = snapshot.excerpts.cursor::<usize>();
for range in ranges_iter {
for (range, new_text) in edits_iter {
let new_text: Arc<str> = new_text.into();
let start = range.start.to_offset(&snapshot);
let end = range.end.to_offset(&snapshot);
cursor.seek(&start, Bias::Right, &());
@ -335,7 +343,7 @@ impl MultiBuffer {
buffer_edits
.entry(start_excerpt.buffer_id)
.or_insert(Vec::new())
.push((buffer_start..buffer_end, true));
.push((buffer_start..buffer_end, new_text, true));
} else {
let start_excerpt_range =
buffer_start..start_excerpt.range.end.to_offset(&start_excerpt.buffer);
@ -344,11 +352,11 @@ impl MultiBuffer {
buffer_edits
.entry(start_excerpt.buffer_id)
.or_insert(Vec::new())
.push((start_excerpt_range, true));
.push((start_excerpt_range, new_text.clone(), true));
buffer_edits
.entry(end_excerpt.buffer_id)
.or_insert(Vec::new())
.push((end_excerpt_range, false));
.push((end_excerpt_range, new_text.clone(), false));
cursor.seek(&start, Bias::Right, &());
cursor.next(&());
@ -359,25 +367,31 @@ impl MultiBuffer {
buffer_edits
.entry(excerpt.buffer_id)
.or_insert(Vec::new())
.push((excerpt.range.to_offset(&excerpt.buffer), false));
.push((
excerpt.range.to_offset(&excerpt.buffer),
new_text.clone(),
false,
));
cursor.next(&());
}
}
}
let new_text = new_text.into();
for (buffer_id, mut edits) in buffer_edits {
edits.sort_unstable_by_key(|(range, _)| range.start);
edits.sort_unstable_by_key(|(range, _, _)| range.start);
self.buffers.borrow()[&buffer_id]
.buffer
.update(cx, |buffer, cx| {
let mut edits = edits.into_iter().peekable();
let mut insertions = Vec::new();
let mut deletions = Vec::new();
while let Some((mut range, mut is_insertion)) = edits.next() {
while let Some((next_range, next_is_insertion)) = edits.peek() {
while let Some((mut range, mut new_text, mut is_insertion)) = edits.next() {
while let Some((next_range, next_new_text, next_is_insertion)) =
edits.peek()
{
if range.end >= next_range.start {
range.end = cmp::max(next_range.end, range.end);
new_text = format!("{new_text}{next_new_text}").into();
is_insertion |= *next_is_insertion;
edits.next();
} else {
@ -386,24 +400,26 @@ impl MultiBuffer {
}
if is_insertion {
insertions.push(
insertions.push((
buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
);
new_text,
));
} else if !range.is_empty() {
deletions.push(
deletions.push((
buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
);
"",
));
}
}
let language_name = buffer.language().map(|l| l.name());
let indent_size = cx.global::<Settings>().tab_size(language_name.as_deref());
if autoindent {
buffer.edit_with_autoindent(deletions, "", indent_size, cx);
buffer.edit_with_autoindent(insertions, new_text.clone(), indent_size, cx);
buffer.edit_with_autoindent_batched(deletions, indent_size, cx);
buffer.edit_with_autoindent_batched(insertions, indent_size, cx);
} else {
buffer.edit(deletions, "", cx);
buffer.edit(insertions, new_text.clone(), cx);
buffer.edit_batched(deletions, cx);
buffer.edit_batched(insertions, cx);
}
})
}
@ -1249,28 +1265,34 @@ impl MultiBuffer {
pub fn randomly_edit(
&mut self,
rng: &mut impl rand::Rng,
count: usize,
edit_count: usize,
cx: &mut ModelContext<Self>,
) {
use text::RandomCharIter;
let snapshot = self.read(cx);
let mut old_ranges: Vec<Range<usize>> = Vec::new();
for _ in 0..count {
let last_end = old_ranges.last().map_or(0, |last_range| last_range.end + 1);
if last_end > snapshot.len() {
let mut edits: Vec<(Range<usize>, Arc<str>)> = Vec::new();
let mut last_end = None;
for _ in 0..edit_count {
if last_end.map_or(false, |last_end| last_end >= snapshot.len()) {
break;
}
let end_ix = snapshot.clip_offset(rng.gen_range(0..=last_end), Bias::Right);
let start_ix = snapshot.clip_offset(rng.gen_range(0..=end_ix), Bias::Left);
old_ranges.push(start_ix..end_ix);
let new_start = last_end.map_or(0, |last_end| last_end + 1);
let end = snapshot.clip_offset(rng.gen_range(new_start..=snapshot.len()), Bias::Right);
let start = snapshot.clip_offset(rng.gen_range(new_start..=end), Bias::Right);
last_end = Some(end);
let range = start..end;
let new_text_len = rng.gen_range(0..10);
let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
edits.push((range, new_text.into()));
}
let new_text_len = rng.gen_range(0..10);
let new_text: String = RandomCharIter::new(&mut *rng).take(new_text_len).collect();
log::info!("mutating multi-buffer at {:?}: {:?}", old_ranges, new_text);
log::info!("mutating multi-buffer with {:?}", edits);
drop(snapshot);
self.edit(old_ranges.iter().cloned(), new_text.as_str(), cx);
self.edit_batched(edits, cx);
}
pub fn randomly_edit_excerpts(
@ -2950,7 +2972,7 @@ mod tests {
.collect::<Vec<_>>()
);
buffer.update(cx, |buffer, cx| buffer.edit([1..3], "XXX\n", cx));
buffer.update(cx, |buffer, cx| buffer.edit(1..3, "XXX\n", cx));
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), buffer.read(cx).text());
@ -2973,11 +2995,11 @@ mod tests {
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), "a");
guest_buffer.update(cx, |buffer, cx| buffer.edit([1..1], "b", cx));
guest_buffer.update(cx, |buffer, cx| buffer.edit(1..1, "b", cx));
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), "ab");
guest_buffer.update(cx, |buffer, cx| buffer.edit([2..2], "c", cx));
guest_buffer.update(cx, |buffer, cx| buffer.edit(2..2, "c", cx));
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), "abc");
}
@ -3091,12 +3113,12 @@ mod tests {
);
buffer_1.update(cx, |buffer, cx| {
buffer.edit(
let text = "\n";
buffer.edit_batched(
[
Point::new(0, 0)..Point::new(0, 0),
Point::new(2, 1)..Point::new(2, 3),
(Point::new(0, 0)..Point::new(0, 0), text),
(Point::new(2, 1)..Point::new(2, 3), text),
],
"\n",
cx,
);
});
@ -3234,8 +3256,8 @@ mod tests {
let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
let old_snapshot = multibuffer.read(cx).snapshot(cx);
buffer.update(cx, |buffer, cx| {
buffer.edit([0..0], "X", cx);
buffer.edit([5..5], "Y", cx);
buffer.edit(0..0, "X", cx);
buffer.edit(5..5, "Y", cx);
});
let new_snapshot = multibuffer.read(cx).snapshot(cx);
@ -3268,12 +3290,12 @@ mod tests {
assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
buffer_1.update(cx, |buffer, cx| {
buffer.edit([0..0], "W", cx);
buffer.edit([5..5], "X", cx);
buffer.edit(0..0, "W", cx);
buffer.edit(5..5, "X", cx);
});
buffer_2.update(cx, |buffer, cx| {
buffer.edit([0..0], "Y", cx);
buffer.edit([6..0], "Z", cx);
buffer.edit(0..0, "Y", cx);
buffer.edit(6..0, "Z", cx);
});
let new_snapshot = multibuffer.read(cx).snapshot(cx);
@ -3302,7 +3324,7 @@ mod tests {
// Create an insertion id in buffer 1 that doesn't exist in buffer 2.
// Add an excerpt from buffer 1 that spans this new insertion.
buffer_1.update(cx, |buffer, cx| buffer.edit([4..4], "123", cx));
buffer_1.update(cx, |buffer, cx| buffer.edit(4..4, "123", cx));
let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
multibuffer
.push_excerpts(buffer_1.clone(), [0..7], cx)
@ -3821,20 +3843,18 @@ mod tests {
multibuffer.update(cx, |multibuffer, cx| {
multibuffer.start_transaction_at(now, cx);
multibuffer.edit(
multibuffer.edit_batched(
[
Point::new(0, 0)..Point::new(0, 0),
Point::new(1, 0)..Point::new(1, 0),
(Point::new(0, 0)..Point::new(0, 0), "A"),
(Point::new(1, 0)..Point::new(1, 0), "A"),
],
"A",
cx,
);
multibuffer.edit(
multibuffer.edit_batched(
[
Point::new(0, 1)..Point::new(0, 1),
Point::new(1, 1)..Point::new(1, 1),
(Point::new(0, 1)..Point::new(0, 1), "B"),
(Point::new(1, 1)..Point::new(1, 1), "B"),
],
"B",
cx,
);
multibuffer.end_transaction_at(now, cx);
@ -3843,19 +3863,19 @@ mod tests {
// Edit buffer 1 through the multibuffer
now += 2 * group_interval;
multibuffer.start_transaction_at(now, cx);
multibuffer.edit([2..2], "C", cx);
multibuffer.edit(2..2, "C", cx);
multibuffer.end_transaction_at(now, cx);
assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
// Edit buffer 1 independently
buffer_1.update(cx, |buffer_1, cx| {
buffer_1.start_transaction_at(now);
buffer_1.edit([3..3], "D", cx);
buffer_1.edit(3..3, "D", cx);
buffer_1.end_transaction_at(now, cx);
now += 2 * group_interval;
buffer_1.start_transaction_at(now);
buffer_1.edit([4..4], "E", cx);
buffer_1.edit(4..4, "E", cx);
buffer_1.end_transaction_at(now, cx);
});
assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");