aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_text_edit
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-05-21 18:50:23 +0100
committerAleksey Kladov <[email protected]>2020-05-21 19:05:33 +0100
commit5b5ebec440841ee98a0aa70b71a135d94f5ca077 (patch)
tree5accb5fce10496334b49ed5a823d321572b375b4 /crates/ra_text_edit
parentba6cf638fbf3d0a025e804f2d354d91abc8afd28 (diff)
Formalize JoinLines protocol extension
Diffstat (limited to 'crates/ra_text_edit')
-rw-r--r--crates/ra_text_edit/src/lib.rs33
1 files changed, 23 insertions, 10 deletions
diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs
index 199fd1096..25554f583 100644
--- a/crates/ra_text_edit/src/lib.rs
+++ b/crates/ra_text_edit/src/lib.rs
@@ -17,7 +17,7 @@ pub struct Indel {
17 pub delete: TextRange, 17 pub delete: TextRange,
18} 18}
19 19
20#[derive(Debug, Clone)] 20#[derive(Default, Debug, Clone)]
21pub struct TextEdit { 21pub struct TextEdit {
22 indels: Vec<Indel>, 22 indels: Vec<Indel>,
23} 23}
@@ -64,14 +64,6 @@ impl TextEdit {
64 builder.finish() 64 builder.finish()
65 } 65 }
66 66
67 pub(crate) fn from_indels(mut indels: Vec<Indel>) -> TextEdit {
68 indels.sort_by_key(|a| (a.delete.start(), a.delete.end()));
69 for (a1, a2) in indels.iter().zip(indels.iter().skip(1)) {
70 assert!(a1.delete.end() <= a2.delete.start())
71 }
72 TextEdit { indels }
73 }
74
75 pub fn len(&self) -> usize { 67 pub fn len(&self) -> usize {
76 self.indels.len() 68 self.indels.len()
77 } 69 }
@@ -122,6 +114,17 @@ impl TextEdit {
122 *text = buf 114 *text = buf
123 } 115 }
124 116
117 pub fn union(&mut self, other: TextEdit) -> Result<(), TextEdit> {
118 // FIXME: can be done without allocating intermediate vector
119 let mut all = self.iter().chain(other.iter()).collect::<Vec<_>>();
120 if !check_disjoint(&mut all) {
121 return Err(other);
122 }
123 self.indels.extend(other.indels);
124 assert!(check_disjoint(&mut self.indels));
125 Ok(())
126 }
127
125 pub fn apply_to_offset(&self, offset: TextSize) -> Option<TextSize> { 128 pub fn apply_to_offset(&self, offset: TextSize) -> Option<TextSize> {
126 let mut res = offset; 129 let mut res = offset;
127 for indel in self.indels.iter() { 130 for indel in self.indels.iter() {
@@ -149,9 +152,19 @@ impl TextEditBuilder {
149 self.indels.push(Indel::insert(offset, text)) 152 self.indels.push(Indel::insert(offset, text))
150 } 153 }
151 pub fn finish(self) -> TextEdit { 154 pub fn finish(self) -> TextEdit {
152 TextEdit::from_indels(self.indels) 155 let mut indels = self.indels;
156 assert!(check_disjoint(&mut indels));
157 TextEdit { indels }
153 } 158 }
154 pub fn invalidates_offset(&self, offset: TextSize) -> bool { 159 pub fn invalidates_offset(&self, offset: TextSize) -> bool {
155 self.indels.iter().any(|indel| indel.delete.contains_inclusive(offset)) 160 self.indels.iter().any(|indel| indel.delete.contains_inclusive(offset))
156 } 161 }
157} 162}
163
164fn check_disjoint(indels: &mut [impl std::borrow::Borrow<Indel>]) -> bool {
165 indels.sort_by_key(|indel| (indel.borrow().delete.start(), indel.borrow().delete.end()));
166 indels
167 .iter()
168 .zip(indels.iter().skip(1))
169 .all(|(l, r)| l.borrow().delete.end() <= r.borrow().delete.start())
170}