internal: Coalesce adjacent Indels

This commit is contained in:
DropDemBits 2023-03-18 11:41:38 -04:00
parent 924d277f32
commit 28225cc33d
No known key found for this signature in database
GPG Key ID: 7FE02A6C1EDFA075

View File

@ -176,6 +176,7 @@ pub fn insert(&mut self, offset: TextSize, text: String) {
pub fn finish(self) -> TextEdit {
let mut indels = self.indels;
assert_disjoint_or_equal(&mut indels);
indels = coalesce_indels(indels);
TextEdit { indels }
}
pub fn invalidates_offset(&self, offset: TextSize) -> bool {
@ -205,6 +206,21 @@ fn check_disjoint<'a, I>(indels: &mut I) -> bool
indels.clone().zip(indels.skip(1)).all(|(l, r)| l.delete.end() <= r.delete.start() || l == r)
}
fn coalesce_indels(indels: Vec<Indel>) -> Vec<Indel> {
indels
.into_iter()
.coalesce(|mut a, b| {
if a.delete.end() == b.delete.start() {
a.insert.push_str(&b.insert);
a.delete = TextRange::new(a.delete.start(), b.delete.end());
Ok(a)
} else {
Err((a, b))
}
})
.collect_vec()
}
#[cfg(test)]
mod tests {
use super::{TextEdit, TextEditBuilder, TextRange};
@ -261,4 +277,40 @@ fn test_union_panics() {
let edit2 = TextEdit::delete(range(9, 13));
assert!(edit1.union(edit2).is_err());
}
#[test]
fn test_coalesce_disjoint() {
let mut builder = TextEditBuilder::default();
builder.replace(range(1, 3), "aa".into());
builder.replace(range(5, 7), "bb".into());
let edit = builder.finish();
assert_eq!(edit.indels.len(), 2);
}
#[test]
fn test_coalesce_adjacent() {
let mut builder = TextEditBuilder::default();
builder.replace(range(1, 3), "aa".into());
builder.replace(range(3, 5), "bb".into());
let edit = builder.finish();
assert_eq!(edit.indels.len(), 1);
assert_eq!(edit.indels[0].insert, "aabb");
assert_eq!(edit.indels[0].delete, range(1, 5));
}
#[test]
fn test_coalesce_adjacent_series() {
let mut builder = TextEditBuilder::default();
builder.replace(range(1, 3), "au".into());
builder.replace(range(3, 5), "www".into());
builder.replace(range(5, 8), "".into());
builder.replace(range(8, 9), "ub".into());
let edit = builder.finish();
assert_eq!(edit.indels.len(), 1);
assert_eq!(edit.indels[0].insert, "auwwwub");
assert_eq!(edit.indels[0].delete, range(1, 9));
}
}