diagnostics: Reduce cloning of DiagnosticEntry (#39193)

Release Notes:

- N/A *or* Added/Fixed/Improved ...
This commit is contained in:
Lukas Wirth
2025-09-30 11:41:49 +00:00
committed by GitHub
parent d8cafdf937
commit 0811d48a7a
14 changed files with 172 additions and 93 deletions
+11 -9
View File
@@ -1,7 +1,7 @@
use crate::{
DebuggerTextObject, LanguageScope, Outline, OutlineConfig, RunnableCapture, RunnableTag,
TextObject, TreeSitterOptions,
diagnostic_set::{DiagnosticEntry, DiagnosticGroup},
diagnostic_set::{DiagnosticEntry, DiagnosticEntryRef, DiagnosticGroup},
language_settings::{LanguageSettings, language_settings},
outline::OutlineItem,
syntax_map::{
@@ -4519,7 +4519,7 @@ impl BufferSnapshot {
&'a self,
search_range: Range<T>,
reversed: bool,
) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
) -> impl 'a + Iterator<Item = DiagnosticEntryRef<'a, O>>
where
T: 'a + Clone + ToOffset,
O: 'a + FromAnchor,
@@ -4552,11 +4552,13 @@ impl BufferSnapshot {
})?;
iterators[next_ix]
.next()
.map(|DiagnosticEntry { range, diagnostic }| DiagnosticEntry {
diagnostic,
range: FromAnchor::from_anchor(&range.start, self)
..FromAnchor::from_anchor(&range.end, self),
})
.map(
|DiagnosticEntryRef { range, diagnostic }| DiagnosticEntryRef {
diagnostic,
range: FromAnchor::from_anchor(&range.start, self)
..FromAnchor::from_anchor(&range.end, self),
},
)
})
}
@@ -4572,7 +4574,7 @@ impl BufferSnapshot {
pub fn diagnostic_groups(
&self,
language_server_id: Option<LanguageServerId>,
) -> Vec<(LanguageServerId, DiagnosticGroup<Anchor>)> {
) -> Vec<(LanguageServerId, DiagnosticGroup<'_, Anchor>)> {
let mut groups = Vec::new();
if let Some(language_server_id) = language_server_id {
@@ -4603,7 +4605,7 @@ impl BufferSnapshot {
pub fn diagnostic_group<O>(
&self,
group_id: usize,
) -> impl Iterator<Item = DiagnosticEntry<O>> + '_
) -> impl Iterator<Item = DiagnosticEntryRef<'_, O>> + use<'_, O>
where
O: FromAnchor + 'static,
{
+83 -13
View File
@@ -34,19 +34,66 @@ pub struct DiagnosticEntry<T> {
pub diagnostic: Diagnostic,
}
/// A single diagnostic in a set. Generic over its range type, because
/// the diagnostics are stored internally as [`Anchor`]s, but can be
/// resolved to different coordinates types like [`usize`] byte offsets or
/// [`Point`](gpui::Point)s.
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub struct DiagnosticEntryRef<'a, T> {
/// The range of the buffer where the diagnostic applies.
pub range: Range<T>,
/// The information about the diagnostic.
pub diagnostic: &'a Diagnostic,
}
impl<T: PartialEq> PartialEq<DiagnosticEntry<T>> for DiagnosticEntryRef<'_, T> {
fn eq(&self, other: &DiagnosticEntry<T>) -> bool {
self.range == other.range && *self.diagnostic == other.diagnostic
}
}
impl<T: PartialEq> PartialEq<DiagnosticEntryRef<'_, T>> for DiagnosticEntry<T> {
fn eq(&self, other: &DiagnosticEntryRef<'_, T>) -> bool {
self.range == other.range && self.diagnostic == *other.diagnostic
}
}
impl<T: Clone> DiagnosticEntryRef<'_, T> {
pub fn to_owned(&self) -> DiagnosticEntry<T> {
DiagnosticEntry {
range: self.range.clone(),
diagnostic: self.diagnostic.clone(),
}
}
}
impl<'a> DiagnosticEntryRef<'a, Anchor> {
/// Converts the [DiagnosticEntry] to a different buffer coordinate type.
pub fn resolve<O: FromAnchor>(
&self,
buffer: &text::BufferSnapshot,
) -> DiagnosticEntryRef<'a, O> {
DiagnosticEntryRef {
range: O::from_anchor(&self.range.start, buffer)
..O::from_anchor(&self.range.end, buffer),
diagnostic: &self.diagnostic,
}
}
}
/// A group of related diagnostics, ordered by their start position
/// in the buffer.
#[derive(Debug, Serialize)]
pub struct DiagnosticGroup<T> {
pub struct DiagnosticGroup<'a, T> {
/// The diagnostics.
pub entries: Vec<DiagnosticEntry<T>>,
pub entries: Vec<DiagnosticEntryRef<'a, T>>,
/// The index into `entries` where the primary diagnostic is stored.
pub primary_ix: usize,
}
impl DiagnosticGroup<Anchor> {
impl<'a> DiagnosticGroup<'a, Anchor> {
/// Converts the entries in this [`DiagnosticGroup`] to a different buffer coordinate type.
pub fn resolve<O: FromAnchor>(&self, buffer: &text::BufferSnapshot) -> DiagnosticGroup<O> {
pub fn resolve<O: FromAnchor>(&self, buffer: &text::BufferSnapshot) -> DiagnosticGroup<'a, O> {
DiagnosticGroup {
entries: self
.entries
@@ -84,6 +131,23 @@ impl DiagnosticEntry<PointUtf16> {
})
}
}
impl DiagnosticEntryRef<'_, PointUtf16> {
/// Returns a raw LSP diagnostic used to provide diagnostic context to LSP
/// codeAction request
pub fn to_lsp_diagnostic_stub(&self) -> Result<lsp::Diagnostic> {
let range = range_to_lsp(self.range.clone())?;
Ok(lsp::Diagnostic {
range,
code: self.diagnostic.code.clone(),
severity: Some(self.diagnostic.severity),
source: self.diagnostic.source.clone(),
message: self.diagnostic.message.clone(),
data: self.diagnostic.data.clone(),
..Default::default()
})
}
}
impl DiagnosticSet {
/// Constructs a [DiagnosticSet] from a sequence of entries, ordered by
@@ -138,7 +202,7 @@ impl DiagnosticSet {
buffer: &'a text::BufferSnapshot,
inclusive: bool,
reversed: bool,
) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
) -> impl 'a + Iterator<Item = DiagnosticEntryRef<'a, O>>
where
T: 'a + ToOffset,
O: FromAnchor,
@@ -179,10 +243,10 @@ impl DiagnosticSet {
}
/// Adds all of this set's diagnostic groups to the given output vector.
pub fn groups(
&self,
pub fn groups<'a>(
&'a self,
language_server_id: LanguageServerId,
output: &mut Vec<(LanguageServerId, DiagnosticGroup<Anchor>)>,
output: &mut Vec<(LanguageServerId, DiagnosticGroup<'a, Anchor>)>,
buffer: &text::BufferSnapshot,
) {
let mut groups = HashMap::default();
@@ -190,7 +254,10 @@ impl DiagnosticSet {
groups
.entry(entry.diagnostic.group_id)
.or_insert(Vec::new())
.push(entry.clone());
.push(DiagnosticEntryRef {
range: entry.range.clone(),
diagnostic: &entry.diagnostic,
});
}
let start_ix = output.len();
@@ -224,7 +291,7 @@ impl DiagnosticSet {
&'a self,
group_id: usize,
buffer: &'a text::BufferSnapshot,
) -> impl 'a + Iterator<Item = DiagnosticEntry<O>> {
) -> impl 'a + Iterator<Item = DiagnosticEntryRef<'a, O>> {
self.iter()
.filter(move |entry| entry.diagnostic.group_id == group_id)
.map(|entry| entry.resolve(buffer))
@@ -247,11 +314,14 @@ impl sum_tree::Item for DiagnosticEntry<Anchor> {
impl DiagnosticEntry<Anchor> {
/// Converts the [DiagnosticEntry] to a different buffer coordinate type.
pub fn resolve<O: FromAnchor>(&self, buffer: &text::BufferSnapshot) -> DiagnosticEntry<O> {
DiagnosticEntry {
pub fn resolve<'a, O: FromAnchor>(
&'a self,
buffer: &text::BufferSnapshot,
) -> DiagnosticEntryRef<'a, O> {
DiagnosticEntryRef {
range: O::from_anchor(&self.range.start, buffer)
..O::from_anchor(&self.range.end, buffer),
diagnostic: self.diagnostic.clone(),
diagnostic: &self.diagnostic,
}
}
}
+1 -1
View File
@@ -75,7 +75,7 @@ use util::serde::default_true;
pub use buffer::Operation;
pub use buffer::*;
pub use diagnostic_set::{DiagnosticEntry, DiagnosticGroup};
pub use diagnostic_set::{DiagnosticEntry, DiagnosticEntryRef, DiagnosticGroup};
pub use language_registry::{
AvailableLanguage, BinaryStatus, LanguageNotFound, LanguageQueries, LanguageRegistry,
QUERY_FILENAME_PREFIXES,