language: Do not fetch diagnostics when iterating over text without language awareness (#16824)
This PR fixes a regression from https://github.com/zed-industries/zed/pull/15646 where we've started fetching diagnostic spans unconditionally (whereas previously that wasn't done when iterating over raw text). Closes #16764 Release Notes: - Fixed performance regression in handling buffers with large quantities of diagnostics.
This commit is contained in:
parent
14f8d3a33a
commit
5e55d5507f
2 changed files with 40 additions and 30 deletions
|
@ -452,7 +452,7 @@ pub struct BufferChunks<'a> {
|
||||||
buffer_snapshot: Option<&'a BufferSnapshot>,
|
buffer_snapshot: Option<&'a BufferSnapshot>,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
chunks: text::Chunks<'a>,
|
chunks: text::Chunks<'a>,
|
||||||
diagnostic_endpoints: Peekable<vec::IntoIter<DiagnosticEndpoint>>,
|
diagnostic_endpoints: Option<Peekable<vec::IntoIter<DiagnosticEndpoint>>>,
|
||||||
error_depth: usize,
|
error_depth: usize,
|
||||||
warning_depth: usize,
|
warning_depth: usize,
|
||||||
information_depth: usize,
|
information_depth: usize,
|
||||||
|
@ -2578,8 +2578,9 @@ impl BufferSnapshot {
|
||||||
if language_aware {
|
if language_aware {
|
||||||
syntax = Some(self.get_highlights(range.clone()));
|
syntax = Some(self.get_highlights(range.clone()));
|
||||||
}
|
}
|
||||||
|
// We want to look at diagnostic spans only when iterating over language-annotated chunks.
|
||||||
BufferChunks::new(self.text.as_rope(), range, syntax, Some(self))
|
let diagnostics = language_aware;
|
||||||
|
BufferChunks::new(self.text.as_rope(), range, syntax, diagnostics, Some(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invokes the given callback for each line of text in the given range of the buffer.
|
/// Invokes the given callback for each line of text in the given range of the buffer.
|
||||||
|
@ -3798,6 +3799,7 @@ impl<'a> BufferChunks<'a> {
|
||||||
text: &'a Rope,
|
text: &'a Rope,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
syntax: Option<(SyntaxMapCaptures<'a>, Vec<HighlightMap>)>,
|
syntax: Option<(SyntaxMapCaptures<'a>, Vec<HighlightMap>)>,
|
||||||
|
diagnostics: bool,
|
||||||
buffer_snapshot: Option<&'a BufferSnapshot>,
|
buffer_snapshot: Option<&'a BufferSnapshot>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut highlights = None;
|
let mut highlights = None;
|
||||||
|
@ -3810,7 +3812,7 @@ impl<'a> BufferChunks<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let diagnostic_endpoints = Vec::new().into_iter().peekable();
|
let diagnostic_endpoints = diagnostics.then(|| Vec::new().into_iter().peekable());
|
||||||
let chunks = text.chunks_in_range(range.clone());
|
let chunks = text.chunks_in_range(range.clone());
|
||||||
|
|
||||||
let mut this = BufferChunks {
|
let mut this = BufferChunks {
|
||||||
|
@ -3871,25 +3873,27 @@ impl<'a> BufferChunks<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_diagnostic_endpoints(&mut self) {
|
fn initialize_diagnostic_endpoints(&mut self) {
|
||||||
if let Some(buffer) = self.buffer_snapshot {
|
if let Some(diagnostics) = self.diagnostic_endpoints.as_mut() {
|
||||||
let mut diagnostic_endpoints = Vec::new();
|
if let Some(buffer) = self.buffer_snapshot {
|
||||||
for entry in buffer.diagnostics_in_range::<_, usize>(self.range.clone(), false) {
|
let mut diagnostic_endpoints = Vec::new();
|
||||||
diagnostic_endpoints.push(DiagnosticEndpoint {
|
for entry in buffer.diagnostics_in_range::<_, usize>(self.range.clone(), false) {
|
||||||
offset: entry.range.start,
|
diagnostic_endpoints.push(DiagnosticEndpoint {
|
||||||
is_start: true,
|
offset: entry.range.start,
|
||||||
severity: entry.diagnostic.severity,
|
is_start: true,
|
||||||
is_unnecessary: entry.diagnostic.is_unnecessary,
|
severity: entry.diagnostic.severity,
|
||||||
});
|
is_unnecessary: entry.diagnostic.is_unnecessary,
|
||||||
diagnostic_endpoints.push(DiagnosticEndpoint {
|
});
|
||||||
offset: entry.range.end,
|
diagnostic_endpoints.push(DiagnosticEndpoint {
|
||||||
is_start: false,
|
offset: entry.range.end,
|
||||||
severity: entry.diagnostic.severity,
|
is_start: false,
|
||||||
is_unnecessary: entry.diagnostic.is_unnecessary,
|
severity: entry.diagnostic.severity,
|
||||||
});
|
is_unnecessary: entry.diagnostic.is_unnecessary,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
diagnostic_endpoints
|
||||||
|
.sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));
|
||||||
|
*diagnostics = diagnostic_endpoints.into_iter().peekable();
|
||||||
}
|
}
|
||||||
diagnostic_endpoints
|
|
||||||
.sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start));
|
|
||||||
self.diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3975,15 +3979,19 @@ impl<'a> Iterator for BufferChunks<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Some(endpoint) = self.diagnostic_endpoints.peek().copied() {
|
let mut diagnostic_endpoints = std::mem::take(&mut self.diagnostic_endpoints);
|
||||||
if endpoint.offset <= self.range.start {
|
if let Some(diagnostic_endpoints) = diagnostic_endpoints.as_mut() {
|
||||||
self.update_diagnostic_depths(endpoint);
|
while let Some(endpoint) = diagnostic_endpoints.peek().copied() {
|
||||||
self.diagnostic_endpoints.next();
|
if endpoint.offset <= self.range.start {
|
||||||
} else {
|
self.update_diagnostic_depths(endpoint);
|
||||||
next_diagnostic_endpoint = endpoint.offset;
|
diagnostic_endpoints.next();
|
||||||
break;
|
} else {
|
||||||
|
next_diagnostic_endpoint = endpoint.offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.diagnostic_endpoints = diagnostic_endpoints;
|
||||||
|
|
||||||
if let Some(chunk) = self.chunks.peek() {
|
if let Some(chunk) = self.chunks.peek() {
|
||||||
let chunk_start = self.range.start;
|
let chunk_start = self.range.start;
|
||||||
|
|
|
@ -1358,7 +1358,9 @@ impl Language {
|
||||||
});
|
});
|
||||||
let highlight_maps = vec![grammar.highlight_map()];
|
let highlight_maps = vec![grammar.highlight_map()];
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for chunk in BufferChunks::new(text, range, Some((captures, highlight_maps)), None) {
|
for chunk in
|
||||||
|
BufferChunks::new(text, range, Some((captures, highlight_maps)), false, None)
|
||||||
|
{
|
||||||
let end_offset = offset + chunk.text.len();
|
let end_offset = offset + chunk.text.len();
|
||||||
if let Some(highlight_id) = chunk.syntax_highlight_id {
|
if let Some(highlight_id) = chunk.syntax_highlight_id {
|
||||||
if !highlight_id.is_default() {
|
if !highlight_id.is_default() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue