Skip to content

Commit 68aa133

Browse files
committed
Auto merge of rust-lang#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.
2 parents eb791f3 + 28225cc commit 68aa133

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

crates/text-edit/src/lib.rs

+52
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ impl TextEditBuilder {
176176
pub fn finish(self) -> TextEdit {
177177
let mut indels = self.indels;
178178
assert_disjoint_or_equal(&mut indels);
179+
indels = coalesce_indels(indels);
179180
TextEdit { indels }
180181
}
181182
pub fn invalidates_offset(&self, offset: TextSize) -> bool {
@@ -205,6 +206,21 @@ where
205206
indels.clone().zip(indels.skip(1)).all(|(l, r)| l.delete.end() <= r.delete.start() || l == r)
206207
}
207208

209+
fn coalesce_indels(indels: Vec<Indel>) -> Vec<Indel> {
210+
indels
211+
.into_iter()
212+
.coalesce(|mut a, b| {
213+
if a.delete.end() == b.delete.start() {
214+
a.insert.push_str(&b.insert);
215+
a.delete = TextRange::new(a.delete.start(), b.delete.end());
216+
Ok(a)
217+
} else {
218+
Err((a, b))
219+
}
220+
})
221+
.collect_vec()
222+
}
223+
208224
#[cfg(test)]
209225
mod tests {
210226
use super::{TextEdit, TextEditBuilder, TextRange};
@@ -261,4 +277,40 @@ mod tests {
261277
let edit2 = TextEdit::delete(range(9, 13));
262278
assert!(edit1.union(edit2).is_err());
263279
}
280+
281+
#[test]
282+
fn test_coalesce_disjoint() {
283+
let mut builder = TextEditBuilder::default();
284+
builder.replace(range(1, 3), "aa".into());
285+
builder.replace(range(5, 7), "bb".into());
286+
let edit = builder.finish();
287+
288+
assert_eq!(edit.indels.len(), 2);
289+
}
290+
291+
#[test]
292+
fn test_coalesce_adjacent() {
293+
let mut builder = TextEditBuilder::default();
294+
builder.replace(range(1, 3), "aa".into());
295+
builder.replace(range(3, 5), "bb".into());
296+
297+
let edit = builder.finish();
298+
assert_eq!(edit.indels.len(), 1);
299+
assert_eq!(edit.indels[0].insert, "aabb");
300+
assert_eq!(edit.indels[0].delete, range(1, 5));
301+
}
302+
303+
#[test]
304+
fn test_coalesce_adjacent_series() {
305+
let mut builder = TextEditBuilder::default();
306+
builder.replace(range(1, 3), "au".into());
307+
builder.replace(range(3, 5), "www".into());
308+
builder.replace(range(5, 8), "".into());
309+
builder.replace(range(8, 9), "ub".into());
310+
311+
let edit = builder.finish();
312+
assert_eq!(edit.indels.len(), 1);
313+
assert_eq!(edit.indels[0].insert, "auwwwub");
314+
assert_eq!(edit.indels[0].delete, range(1, 9));
315+
}
264316
}

0 commit comments

Comments
 (0)