diff --git a/Cargo.lock b/Cargo.lock index d4508ba73c7efe19f166225c601355af7bc852d8..3fd01281a504d683f81b531a75467380e1cbe7a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4857,6 +4857,7 @@ dependencies = [ "ctor", "env_logger", "gpui", + "lazy_static", "log", "parking_lot", "rand 0.8.3", diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index f2cc7f1e86d3def9ab0541c39334d881172b2b89..56d887e2e2277aa98761ce4cce7beefcc9754669 100644 --- a/crates/language/src/buffer.rs +++ b/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(); diff --git a/crates/language/src/diagnostic_set.rs b/crates/language/src/diagnostic_set.rs index 0a04ef17e88cab5d74548b4ca3af5c1e3310de58..b67a2fe835597e543c99409943439ae34f07194f 100644 --- a/crates/language/src/diagnostic_set.rs +++ b/crates/language/src/diagnostic_set.rs @@ -37,20 +37,22 @@ impl DiagnosticSet { } } - pub fn reset(&mut self, iter: I, buffer: &text::Snapshot) + pub fn new(iter: I, buffer: &text::Snapshot) -> Self where I: IntoIterator>, { let mut entries = iter.into_iter().collect::>(); 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> { diff --git a/crates/text/Cargo.toml b/crates/text/Cargo.toml index 2b68a71a080ea412ee534d662b85e656fa51edc3..f4b7d7453f0d0902ca855da31f549ee1a48bef40 100644 --- a/crates/text/Cargo.toml +++ b/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 } diff --git a/crates/text/src/anchor.rs b/crates/text/src/anchor.rs index 2be0058999264f6410a54bdf285b8a6fde0a62e8..738de690b451b8b87a2138047047fdcc1112ec8c 100644 --- a/crates/text/src/anchor.rs +++ b/crates/text/src/anchor.rs @@ -28,16 +28,18 @@ impl Anchor { } } - pub fn cmp<'a>(&self, other: &Anchor, buffer: &BufferSnapshot) -> Result { - let offset_comparison = if self.timestamp == other.timestamp { - self.offset.cmp(&other.offset) + pub fn cmp(&self, other: &Anchor, buffer: &BufferSnapshot) -> Result { + 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 { diff --git a/crates/text/src/locator.rs b/crates/text/src/locator.rs index 249e79b6fd866a149bc54187651e17235c97b7ad..e4feaf99ac2e4252e8c002387faf7abce52c9467 100644 --- a/crates/text/src/locator.rs +++ b/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]>); diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index ac06182939de41a37873847e3bd3d57e74ff5af7..69439c7aa39f6d758154dc537ae7a73587838e3a 100644 --- a/crates/text/src/text.rs +++ b/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 } }