diff options
| author | bors <bors@rust-lang.org> | 2023-03-25 13:16:43 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-03-25 13:16:43 +0000 |
| commit | 68aa1331087e51857e91be2a3dc38a5b7ac49bad (patch) | |
| tree | ddbab09ed7ffd030084c27e01d224b6a8daec143 | |
| parent | eb791f31e688ae00908eb75d4c704ef60c430a92 (diff) | |
| parent | 28225cc33d60615aaa140dc4b0d32e2a1c21462c (diff) | |
| download | rust-68aa1331087e51857e91be2a3dc38a5b7ac49bad.tar.gz rust-68aa1331087e51857e91be2a3dc38a5b7ac49bad.zip | |
Auto merge of #14380 - DropDemBits:coalesce-indels, r=Veykril
internal: Coalesce adjacent Indels Originally part of working on a structured snippet API (since sometimes the `$` bit of snippets would be broken off and would lead to it not being recognized), though since this is a pretty separate change, I thought it would make sense to put it into it's own PR. The implementation is relatively straight forward and not overly optimized, though it's pretty low hanging fruit to optimize it when need be.
| -rw-r--r-- | crates/text-edit/src/lib.rs | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/crates/text-edit/src/lib.rs b/crates/text-edit/src/lib.rs index 9bb4271b65f..4705d18187a 100644 --- a/crates/text-edit/src/lib.rs +++ b/crates/text-edit/src/lib.rs @@ -176,6 +176,7 @@ impl TextEditBuilder { 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 @@ where 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 @@ mod tests { 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)); + } } |
