Merge branch 'fragment-locators' into project-diagnostics

Antonio Scandurra created

Change summary

Cargo.lock                            |  1 +
crates/language/src/buffer.rs         |  8 +++-----
crates/language/src/diagnostic_set.rs | 20 +++++++++++---------
crates/text/Cargo.toml                |  1 +
crates/text/src/anchor.rs             | 14 ++++++++------
crates/text/src/locator.rs            |  6 ++++++
crates/text/src/text.rs               | 12 ++++--------
7 files changed, 34 insertions(+), 28 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -4857,6 +4857,7 @@ dependencies = [
  "ctor",
  "env_logger",
  "gpui",
+ "lazy_static",
  "log",
  "parking_lot",
  "rand 0.8.3",

crates/language/src/buffer.rs 🔗

@@ -23,7 +23,6 @@ use std::{
     ffi::OsString,
     future::Future,
     iter::{Iterator, Peekable},
-    mem,
     ops::{Deref, DerefMut, Range},
     path::{Path, PathBuf},
     str,
@@ -794,8 +793,7 @@ impl Buffer {
         }
 
         drop(edits_since_save);
-        let mut diagnostics = mem::take(&mut self.diagnostics);
-        diagnostics.reset(
+        let new_diagnostics = DiagnosticSet::new(
             diagnostics_by_group_id
                 .into_values()
                 .flat_map(|mut diagnostics| {
@@ -806,9 +804,9 @@ impl Buffer {
                     primary.diagnostic.is_primary = true;
                     diagnostics
                 }),
-            self,
+            content,
         );
-        self.diagnostics = diagnostics;
+        self.diagnostics = new_diagnostics;
 
         if let Some(version) = version {
             let language_server = self.language_server.as_mut().unwrap();

crates/language/src/diagnostic_set.rs 🔗

@@ -37,20 +37,22 @@ impl DiagnosticSet {
         }
     }
 
-    pub fn reset<I>(&mut self, iter: I, buffer: &text::Snapshot)
+    pub fn new<I>(iter: I, buffer: &text::Snapshot) -> Self
     where
         I: IntoIterator<Item = DiagnosticEntry<PointUtf16>>,
     {
         let mut entries = iter.into_iter().collect::<Vec<_>>();
         entries.sort_unstable_by_key(|entry| (entry.range.start, Reverse(entry.range.end)));
-        self.diagnostics = SumTree::from_iter(
-            entries.into_iter().map(|entry| DiagnosticEntry {
-                range: buffer.anchor_before(entry.range.start)
-                    ..buffer.anchor_after(entry.range.end),
-                diagnostic: entry.diagnostic,
-            }),
-            buffer,
-        );
+        Self {
+            diagnostics: SumTree::from_iter(
+                entries.into_iter().map(|entry| DiagnosticEntry {
+                    range: buffer.anchor_before(entry.range.start)
+                        ..buffer.anchor_after(entry.range.end),
+                    diagnostic: entry.diagnostic,
+                }),
+                buffer,
+            ),
+        }
     }
 
     pub fn iter(&self) -> impl Iterator<Item = &DiagnosticEntry<Anchor>> {

crates/text/Cargo.toml 🔗

@@ -15,6 +15,7 @@ collections = { path = "../collections" }
 sum_tree = { path = "../sum_tree" }
 anyhow = "1.0.38"
 arrayvec = "0.7.1"
+lazy_static = "1.4"
 log = "0.4"
 parking_lot = "0.11"
 rand = { version = "0.8.3", optional = true }

crates/text/src/anchor.rs 🔗

@@ -28,16 +28,18 @@ impl Anchor {
         }
     }
 
-    pub fn cmp<'a>(&self, other: &Anchor, buffer: &BufferSnapshot) -> Result<Ordering> {
-        let offset_comparison = if self.timestamp == other.timestamp {
-            self.offset.cmp(&other.offset)
+    pub fn cmp(&self, other: &Anchor, buffer: &BufferSnapshot) -> Result<Ordering> {
+        let fragment_id_comparison = if self.timestamp == other.timestamp {
+            Ordering::Equal
         } else {
             buffer
-                .full_offset_for_anchor(self)
-                .cmp(&buffer.full_offset_for_anchor(other))
+                .fragment_id_for_anchor(self)
+                .cmp(&buffer.fragment_id_for_anchor(other))
         };
 
-        Ok(offset_comparison.then_with(|| self.bias.cmp(&other.bias)))
+        Ok(fragment_id_comparison
+            .then_with(|| self.offset.cmp(&other.offset))
+            .then_with(|| self.bias.cmp(&other.bias)))
     }
 
     pub fn bias_left(&self, buffer: &BufferSnapshot) -> Anchor {

crates/text/src/locator.rs 🔗

@@ -1,6 +1,12 @@
+use lazy_static::lazy_static;
 use smallvec::{smallvec, SmallVec};
 use std::iter;
 
+lazy_static! {
+    pub static ref MIN: Locator = Locator::min();
+    pub static ref MAX: Locator = Locator::max();
+}
+
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Locator(SmallVec<[u64; 4]>);
 

crates/text/src/text.rs 🔗

@@ -1768,12 +1768,11 @@ impl BufferSnapshot {
         }
     }
 
-    fn full_offset_for_anchor(&self, anchor: &Anchor) -> FullOffset {
+    fn fragment_id_for_anchor(&self, anchor: &Anchor) -> &Locator {
         if *anchor == Anchor::min() {
-            Default::default()
+            &locator::MIN
         } else if *anchor == Anchor::max() {
-            let text = self.fragments.summary().text;
-            FullOffset(text.visible + text.deleted)
+            &locator::MAX
         } else {
             let anchor_key = InsertionFragmentKey {
                 timestamp: anchor.timestamp,
@@ -1795,10 +1794,7 @@ impl BufferSnapshot {
             }
             let insertion = insertion_cursor.item().expect("invalid insertion");
             debug_assert_eq!(insertion.timestamp, anchor.timestamp, "invalid insertion");
-
-            let mut fragment_cursor = self.fragments.cursor::<(Option<&Locator>, FullOffset)>();
-            fragment_cursor.seek(&Some(&insertion.fragment_id), Bias::Left, &None);
-            fragment_cursor.start().1 + (anchor.offset - insertion.split_offset)
+            &insertion.fragment_id
         }
     }