about summary refs log tree commit diff
path: root/src/tools/rust-analyzer/crates/text-edit
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@dend.ro>2023-06-05 12:04:23 +0300
committerLaurențiu Nicola <lnicola@dend.ro>2023-06-05 12:04:23 +0300
commitb8a7d439db0cfd765ed4bfedd2bbaeeee58b05a5 (patch)
tree5adcbc6cf50af3bebc2cd4f42d5252a4d728690e /src/tools/rust-analyzer/crates/text-edit
parent51f714c8c5021fe25442e46798b1cbef2f2249ed (diff)
parentaa9bc8612514d216f84eec218dfd19ab83f3598a (diff)
downloadrust-b8a7d439db0cfd765ed4bfedd2bbaeeee58b05a5.tar.gz
rust-b8a7d439db0cfd765ed4bfedd2bbaeeee58b05a5.zip
Merge commit 'aa9bc8612514d216f84eec218dfd19ab83f3598a' into sync-from-ra
Diffstat (limited to 'src/tools/rust-analyzer/crates/text-edit')
-rw-r--r--src/tools/rust-analyzer/crates/text-edit/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/text-edit/src/lib.rs52
2 files changed, 53 insertions, 1 deletions
diff --git a/src/tools/rust-analyzer/crates/text-edit/Cargo.toml b/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
index 337cd234739..76d0ca5ccb6 100644
--- a/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
@@ -13,4 +13,4 @@ doctest = false
 
 [dependencies]
 itertools = "0.10.5"
-text-size = "1.1.0"
+text-size.workspace = true
diff --git a/src/tools/rust-analyzer/crates/text-edit/src/lib.rs b/src/tools/rust-analyzer/crates/text-edit/src/lib.rs
index 9bb4271b65f..4705d18187a 100644
--- a/src/tools/rust-analyzer/crates/text-edit/src/lib.rs
+++ b/src/tools/rust-analyzer/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));
+    }
 }