Respect excerpt's range when comparing two anchors both belonging to it

Antonio Scandurra created

Change summary

crates/editor/src/display_map/fold_map.rs |  8 ++++++
crates/editor/src/multi_buffer.rs         | 14 +++-------
crates/editor/src/multi_buffer/anchor.rs  | 32 +++++++++++-------------
3 files changed, 28 insertions(+), 26 deletions(-)

Detailed changes

crates/editor/src/display_map/fold_map.rs 🔗

@@ -241,6 +241,14 @@ impl FoldMap {
                 self.buffer.lock().len(),
                 "transform tree does not match buffer's length"
             );
+
+            let mut folds = self.folds.iter().peekable();
+            while let Some(fold) = folds.next() {
+                if let Some(next_fold) = folds.peek() {
+                    let comparison = fold.0.cmp(&next_fold.0, &self.buffer.lock()).unwrap();
+                    assert!(comparison.is_le());
+                }
+            }
         }
     }
 

crates/editor/src/multi_buffer.rs 🔗

@@ -1998,10 +1998,9 @@ impl MultiBufferSnapshot {
     pub fn can_resolve(&self, anchor: &Anchor) -> bool {
         if anchor.excerpt_id == ExcerptId::min() || anchor.excerpt_id == ExcerptId::max() {
             true
-        } else if let Some((buffer_id, buffer_snapshot)) =
-            self.buffer_snapshot_for_excerpt(&anchor.excerpt_id)
-        {
-            anchor.buffer_id == Some(buffer_id) && buffer_snapshot.can_resolve(&anchor.text_anchor)
+        } else if let Some(excerpt) = self.excerpt(&anchor.excerpt_id) {
+            anchor.buffer_id == Some(excerpt.buffer_id)
+                && excerpt.buffer.can_resolve(&anchor.text_anchor)
         } else {
             false
         }
@@ -2231,15 +2230,12 @@ impl MultiBufferSnapshot {
         ))
     }
 
-    fn buffer_snapshot_for_excerpt<'a>(
-        &'a self,
-        excerpt_id: &'a ExcerptId,
-    ) -> Option<(usize, &'a BufferSnapshot)> {
+    fn excerpt<'a>(&'a self, excerpt_id: &'a ExcerptId) -> Option<&'a Excerpt> {
         let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
         cursor.seek(&Some(excerpt_id), Bias::Left, &());
         if let Some(excerpt) = cursor.item() {
             if excerpt.id == *excerpt_id {
-                return Some((excerpt.buffer_id, &excerpt.buffer));
+                return Some(excerpt);
             }
         }
         None

crates/editor/src/multi_buffer/anchor.rs 🔗

@@ -40,17 +40,19 @@ impl Anchor {
         if excerpt_id_cmp.is_eq() {
             if self.excerpt_id == ExcerptId::min() || self.excerpt_id == ExcerptId::max() {
                 Ok(Ordering::Equal)
-            } else if let Some((buffer_id, buffer_snapshot)) =
-                snapshot.buffer_snapshot_for_excerpt(&self.excerpt_id)
-            {
+            } else if let Some(excerpt) = snapshot.excerpt(&self.excerpt_id) {
                 // Even though the anchor refers to a valid excerpt the underlying buffer might have
                 // changed. In that case, treat the anchor as if it were at the start of that
                 // excerpt.
-                if self.buffer_id == Some(buffer_id) && other.buffer_id == Some(buffer_id) {
-                    self.text_anchor.cmp(&other.text_anchor, buffer_snapshot)
-                } else if self.buffer_id == Some(buffer_id) {
+                if self.buffer_id == Some(excerpt.buffer_id)
+                    && other.buffer_id == Some(excerpt.buffer_id)
+                {
+                    let self_anchor = excerpt.clip_anchor(self.text_anchor.clone());
+                    let other_anchor = excerpt.clip_anchor(other.text_anchor.clone());
+                    self_anchor.cmp(&other_anchor, &excerpt.buffer)
+                } else if self.buffer_id == Some(excerpt.buffer_id) {
                     Ok(Ordering::Greater)
-                } else if other.buffer_id == Some(buffer_id) {
+                } else if other.buffer_id == Some(excerpt.buffer_id) {
                     Ok(Ordering::Less)
                 } else {
                     Ok(Ordering::Equal)
@@ -65,14 +67,12 @@ impl Anchor {
 
     pub fn bias_left(&self, snapshot: &MultiBufferSnapshot) -> Anchor {
         if self.text_anchor.bias != Bias::Left {
-            if let Some((buffer_id, buffer_snapshot)) =
-                snapshot.buffer_snapshot_for_excerpt(&self.excerpt_id)
-            {
-                if self.buffer_id == Some(buffer_id) {
+            if let Some(excerpt) = snapshot.excerpt(&self.excerpt_id) {
+                if self.buffer_id == Some(excerpt.buffer_id) {
                     return Self {
                         buffer_id: self.buffer_id,
                         excerpt_id: self.excerpt_id.clone(),
-                        text_anchor: self.text_anchor.bias_left(buffer_snapshot),
+                        text_anchor: self.text_anchor.bias_left(&excerpt.buffer),
                     };
                 }
             }
@@ -82,14 +82,12 @@ impl Anchor {
 
     pub fn bias_right(&self, snapshot: &MultiBufferSnapshot) -> Anchor {
         if self.text_anchor.bias != Bias::Right {
-            if let Some((buffer_id, buffer_snapshot)) =
-                snapshot.buffer_snapshot_for_excerpt(&self.excerpt_id)
-            {
-                if self.buffer_id == Some(buffer_id) {
+            if let Some(excerpt) = snapshot.excerpt(&self.excerpt_id) {
+                if self.buffer_id == Some(excerpt.buffer_id) {
                     return Self {
                         buffer_id: self.buffer_id,
                         excerpt_id: self.excerpt_id.clone(),
-                        text_anchor: self.text_anchor.bias_right(buffer_snapshot),
+                        text_anchor: self.text_anchor.bias_right(&excerpt.buffer),
                     };
                 }
             }