3
3
//! `rust-analyzer` never mutates text itself and only sends diffs to clients,
4
4
//! so `TextEdit` is the ultimate representation of the work done by
5
5
//! rust-analyzer.
6
+ use std:: collections:: HashSet ;
7
+
6
8
pub use text_size:: { TextRange , TextSize } ;
7
9
8
10
/// `InsertDelete` -- a single "atomic" change to text
9
11
///
10
12
/// Must not overlap with other `InDel`s
11
- #[ derive( Debug , Clone ) ]
13
+ #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
12
14
pub struct Indel {
13
15
pub insert : String ,
14
16
/// Refers to offsets in the original text
@@ -114,13 +116,20 @@ impl TextEdit {
114
116
}
115
117
116
118
pub fn union ( & mut self , other : TextEdit ) -> Result < ( ) , TextEdit > {
119
+ dbg ! ( & self , & other) ;
117
120
// FIXME: can be done without allocating intermediate vector
118
121
let mut all = self . iter ( ) . chain ( other. iter ( ) ) . collect :: < Vec < _ > > ( ) ;
119
- if !check_disjoint ( & mut all) {
122
+ if !check_disjoint_or_equal ( & mut all) {
120
123
return Err ( other) ;
121
124
}
122
- self . indels . extend ( other. indels ) ;
123
- assert_disjoint ( & mut self . indels ) ;
125
+
126
+ // remove duplicates
127
+ // FIXME: maybe make indels a HashSet instead to get rid of this?
128
+ let our_indels = self . indels . clone ( ) ;
129
+ let our_indels = our_indels. iter ( ) . collect :: < HashSet < _ > > ( ) ;
130
+ let other_indels = other. indels . into_iter ( ) . filter ( |i| !our_indels. contains ( i) ) ;
131
+
132
+ self . indels . extend ( other_indels) ;
124
133
Ok ( ( ) )
125
134
}
126
135
@@ -173,7 +182,7 @@ impl TextEditBuilder {
173
182
}
174
183
pub fn finish ( self ) -> TextEdit {
175
184
let mut indels = self . indels ;
176
- assert_disjoint ( & mut indels) ;
185
+ assert_disjoint_or_equal ( & mut indels) ;
177
186
TextEdit { indels }
178
187
}
179
188
pub fn invalidates_offset ( & self , offset : TextSize ) -> bool {
@@ -182,18 +191,19 @@ impl TextEditBuilder {
182
191
fn indel ( & mut self , indel : Indel ) {
183
192
self . indels . push ( indel) ;
184
193
if self . indels . len ( ) <= 16 {
185
- assert_disjoint ( & mut self . indels ) ;
194
+ assert_disjoint_or_equal ( & mut self . indels ) ;
186
195
}
187
196
}
188
197
}
189
198
190
- fn assert_disjoint ( indels : & mut [ impl std:: borrow:: Borrow < Indel > ] ) {
191
- assert ! ( check_disjoint ( indels) ) ;
199
+ fn assert_disjoint_or_equal ( indels : & mut [ impl std:: borrow:: Borrow < Indel > ] ) {
200
+ assert ! ( check_disjoint_or_equal ( indels) ) ;
192
201
}
193
- fn check_disjoint ( indels : & mut [ impl std:: borrow:: Borrow < Indel > ] ) -> bool {
202
+ fn check_disjoint_or_equal ( indels : & mut [ impl std:: borrow:: Borrow < Indel > ] ) -> bool {
194
203
indels. sort_by_key ( |indel| ( indel. borrow ( ) . delete . start ( ) , indel. borrow ( ) . delete . end ( ) ) ) ;
195
- indels
196
- . iter ( )
197
- . zip ( indels. iter ( ) . skip ( 1 ) )
198
- . all ( |( l, r) | l. borrow ( ) . delete . end ( ) <= r. borrow ( ) . delete . start ( ) )
204
+ indels. iter ( ) . zip ( indels. iter ( ) . skip ( 1 ) ) . all ( |( l, r) | {
205
+ let l = l. borrow ( ) ;
206
+ let r = r. borrow ( ) ;
207
+ l. delete . end ( ) <= r. delete . start ( ) || l == r
208
+ } )
199
209
}
0 commit comments