diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index a0182902f1..69a4d1235f 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -278,7 +278,8 @@ impl ProjectDiagnosticsEditor { prev_excerpt_id = excerpt_id.clone(); first_excerpt_id.get_or_insert_with(|| prev_excerpt_id.clone()); group_state.excerpts.push(excerpt_id.clone()); - let header_position = (excerpt_id.clone(), language::Anchor::min()); + let header_position = + (excerpt_id.clone(), language::Anchor::build_min()); if is_first_excerpt_for_group { is_first_excerpt_for_group = false; diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index ba95d33d39..634851bd82 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2399,7 +2399,7 @@ impl Editor { ) -> Result<()> { let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx)); - // If the code action's edits are all contained within this editor, then + // If the project transaction's edits are all contained within this editor, then // avoid opening a new editor to display them. let mut entries = transaction.0.iter(); if let Some((buffer, transaction)) = entries.next() { @@ -2521,7 +2521,6 @@ impl Editor { } let buffer_id = cursor_position.buffer_id; - let excerpt_id = cursor_position.excerpt_id.clone(); let style = this.style(cx); let read_background = style.document_highlight_read_background; let write_background = style.document_highlight_write_background; @@ -2533,22 +2532,39 @@ impl Editor { return; } + let cursor_buffer_snapshot = cursor_buffer.read(cx); let mut write_ranges = Vec::new(); let mut read_ranges = Vec::new(); for highlight in highlights { - let range = Anchor { - buffer_id, - excerpt_id: excerpt_id.clone(), - text_anchor: highlight.range.start, - }..Anchor { - buffer_id, - excerpt_id: excerpt_id.clone(), - text_anchor: highlight.range.end, - }; - if highlight.kind == lsp::DocumentHighlightKind::WRITE { - write_ranges.push(range); - } else { - read_ranges.push(range); + for (excerpt_id, excerpt_range) in + buffer.excerpts_for_buffer(&cursor_buffer, cx) + { + let start = highlight + .range + .start + .max(&excerpt_range.start, cursor_buffer_snapshot); + let end = highlight + .range + .end + .min(&excerpt_range.end, cursor_buffer_snapshot); + if start.cmp(&end, cursor_buffer_snapshot).unwrap().is_ge() { + continue; + } + + let range = Anchor { + buffer_id, + excerpt_id: excerpt_id.clone(), + text_anchor: start, + }..Anchor { + buffer_id, + excerpt_id, + text_anchor: end, + }; + if highlight.kind == lsp::DocumentHighlightKind::WRITE { + write_ranges.push(range); + } else { + read_ranges.push(range); + } } } @@ -4413,7 +4429,6 @@ impl Editor { .iter() .map(|range| range.to_point(&snapshot)) .collect::>(); - dbg!(point_ranges); this.highlight_text::( ranges, diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 594e3fafb7..398f7da99e 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -211,7 +211,11 @@ impl MultiBuffer { pub fn singleton(buffer: ModelHandle, cx: &mut ModelContext) -> Self { let mut this = Self::new(buffer.read(cx).replica_id()); this.singleton = true; - this.push_excerpts(buffer, [text::Anchor::min()..text::Anchor::max()], cx); + this.push_excerpts( + buffer, + [text::Anchor::build_min()..text::Anchor::build_max()], + cx, + ); this.snapshot.borrow_mut().singleton = true; this } @@ -814,11 +818,30 @@ impl MultiBuffer { cx.notify(); } - pub fn excerpt_ids_for_buffer(&self, buffer: &ModelHandle) -> Vec { - self.buffers - .borrow() + pub fn excerpts_for_buffer( + &self, + buffer: &ModelHandle, + cx: &AppContext, + ) -> Vec<(ExcerptId, Range)> { + let mut excerpts = Vec::new(); + let snapshot = self.read(cx); + let buffers = self.buffers.borrow(); + let mut cursor = snapshot.excerpts.cursor::>(); + for excerpt_id in buffers .get(&buffer.id()) - .map_or(Vec::new(), |state| state.excerpts.clone()) + .map(|state| &state.excerpts) + .into_iter() + .flatten() + { + cursor.seek_forward(&Some(excerpt_id), Bias::Left, &()); + if let Some(excerpt) = cursor.item() { + if excerpt.id == *excerpt_id { + excerpts.push((excerpt.id.clone(), excerpt.range.clone())); + } + } + } + + excerpts } pub fn excerpt_ids(&self) -> Vec { @@ -3070,7 +3093,8 @@ mod tests { ); let snapshot = multibuffer.update(cx, |multibuffer, cx| { - let buffer_2_excerpt_id = multibuffer.excerpt_ids_for_buffer(&buffer_2)[0].clone(); + let (buffer_2_excerpt_id, _) = + multibuffer.excerpts_for_buffer(&buffer_2, cx)[0].clone(); multibuffer.remove_excerpts(&[buffer_2_excerpt_id], cx); multibuffer.snapshot(cx) }); diff --git a/crates/editor/src/multi_buffer/anchor.rs b/crates/editor/src/multi_buffer/anchor.rs index 33147ce285..847a38f500 100644 --- a/crates/editor/src/multi_buffer/anchor.rs +++ b/crates/editor/src/multi_buffer/anchor.rs @@ -19,7 +19,7 @@ impl Anchor { Self { buffer_id: None, excerpt_id: ExcerptId::min(), - text_anchor: text::Anchor::min(), + text_anchor: text::Anchor::build_min(), } } @@ -27,7 +27,7 @@ impl Anchor { Self { buffer_id: None, excerpt_id: ExcerptId::max(), - text_anchor: text::Anchor::max(), + text_anchor: text::Anchor::build_max(), } } diff --git a/crates/editor/src/repro.rs b/crates/editor/src/repro.rs new file mode 100644 index 0000000000..0dfa9ecbfc --- /dev/null +++ b/crates/editor/src/repro.rs @@ -0,0 +1,9 @@ +fn test(complicated: i32, test: i32) { + complicated; + test; + // 1 + // 2 + // 3 + complicated; + test; +} diff --git a/crates/language/src/diagnostic_set.rs b/crates/language/src/diagnostic_set.rs index e25551ee3a..017f117bbe 100644 --- a/crates/language/src/diagnostic_set.rs +++ b/crates/language/src/diagnostic_set.rs @@ -187,10 +187,10 @@ impl DiagnosticEntry { impl Default for Summary { fn default() -> Self { Self { - start: Anchor::min(), - end: Anchor::max(), - min_start: Anchor::max(), - max_end: Anchor::min(), + start: Anchor::build_min(), + end: Anchor::build_max(), + min_start: Anchor::build_max(), + max_end: Anchor::build_min(), count: 0, } } diff --git a/crates/language/src/tests.rs b/crates/language/src/tests.rs index d36771c44f..3dbe8508a5 100644 --- a/crates/language/src/tests.rs +++ b/crates/language/src/tests.rs @@ -789,7 +789,7 @@ fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) { for buffer in &buffers { let buffer = buffer.read(cx).snapshot(); let actual_remote_selections = buffer - .remote_selections_in_range(Anchor::min()..Anchor::max()) + .remote_selections_in_range(Anchor::build_min()..Anchor::build_max()) .map(|(replica_id, selections)| (replica_id, selections.collect::>())) .collect::>(); let expected_remote_selections = active_selections diff --git a/crates/text/src/anchor.rs b/crates/text/src/anchor.rs index 28da998d67..c7de6bc882 100644 --- a/crates/text/src/anchor.rs +++ b/crates/text/src/anchor.rs @@ -12,7 +12,7 @@ pub struct Anchor { } impl Anchor { - pub fn min() -> Self { + pub fn build_min() -> Self { Self { timestamp: clock::Local::MIN, offset: usize::MIN, @@ -20,7 +20,7 @@ impl Anchor { } } - pub fn max() -> Self { + pub fn build_max() -> Self { Self { timestamp: clock::Local::MAX, offset: usize::MAX, @@ -42,6 +42,22 @@ impl Anchor { .then_with(|| self.bias.cmp(&other.bias))) } + pub fn min(&self, other: &Self, buffer: &BufferSnapshot) -> Self { + if self.cmp(other, buffer).unwrap().is_le() { + self.clone() + } else { + other.clone() + } + } + + pub fn max(&self, other: &Self, buffer: &BufferSnapshot) -> Self { + if self.cmp(other, buffer).unwrap().is_ge() { + self.clone() + } else { + other.clone() + } + } + pub fn bias(&self, bias: Bias, buffer: &BufferSnapshot) -> Anchor { if bias == Bias::Left { self.bias_left(buffer) diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index 338a5c0ad1..8cb9629d07 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -1318,8 +1318,8 @@ impl Buffer { let mut futures = Vec::new(); for anchor in anchors { if !self.version.observed(anchor.timestamp) - && *anchor != Anchor::max() - && *anchor != Anchor::min() + && *anchor != Anchor::build_max() + && *anchor != Anchor::build_min() { let (tx, rx) = oneshot::channel(); self.edit_id_resolvers @@ -1638,9 +1638,9 @@ impl BufferSnapshot { let mut position = D::default(); anchors.map(move |anchor| { - if *anchor == Anchor::min() { + if *anchor == Anchor::build_min() { return D::default(); - } else if *anchor == Anchor::max() { + } else if *anchor == Anchor::build_max() { return D::from_text_summary(&self.visible_text.summary()); } @@ -1680,9 +1680,9 @@ impl BufferSnapshot { where D: TextDimension, { - if *anchor == Anchor::min() { + if *anchor == Anchor::build_min() { D::default() - } else if *anchor == Anchor::max() { + } else if *anchor == Anchor::build_max() { D::from_text_summary(&self.visible_text.summary()) } else { let anchor_key = InsertionFragmentKey { @@ -1718,9 +1718,9 @@ impl BufferSnapshot { } fn fragment_id_for_anchor(&self, anchor: &Anchor) -> &Locator { - if *anchor == Anchor::min() { + if *anchor == Anchor::build_min() { &locator::MIN - } else if *anchor == Anchor::max() { + } else if *anchor == Anchor::build_max() { &locator::MAX } else { let anchor_key = InsertionFragmentKey { @@ -1758,9 +1758,9 @@ impl BufferSnapshot { pub fn anchor_at(&self, position: T, bias: Bias) -> Anchor { let offset = position.to_offset(self); if bias == Bias::Left && offset == 0 { - Anchor::min() + Anchor::build_min() } else if bias == Bias::Right && offset == self.len() { - Anchor::max() + Anchor::build_max() } else { let mut fragment_cursor = self.fragments.cursor::(); fragment_cursor.seek(&offset, bias, &None); @@ -1775,8 +1775,8 @@ impl BufferSnapshot { } pub fn can_resolve(&self, anchor: &Anchor) -> bool { - *anchor == Anchor::min() - || *anchor == Anchor::max() + *anchor == Anchor::build_min() + || *anchor == Anchor::build_max() || self.version.observed(anchor.timestamp) } @@ -1799,7 +1799,7 @@ impl BufferSnapshot { where D: TextDimension + Ord, { - self.edits_since_in_range(since, Anchor::min()..Anchor::max()) + self.edits_since_in_range(since, Anchor::build_min()..Anchor::build_max()) } pub fn edited_ranges_for_transaction<'a, D>(