From 88adddb3247d5735d31adb7b6a191055fdad87b9 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 2 Feb 2022 16:33:04 -0800 Subject: [PATCH] Remove theme parameters from buffer/display map's chunks methods Change Chunks to contain highlight ids instead of actual highlight styles. Retrieve the actual highlight style from the theme in the editor element layer. This is to set us up to perform syntax highlighting in other code paths where the theme is not available. --- crates/editor/src/display_map.rs | 17 ++- crates/editor/src/display_map/block_map.rs | 15 +-- crates/editor/src/display_map/fold_map.rs | 17 +-- crates/editor/src/display_map/tab_map.rs | 19 ++- crates/editor/src/display_map/wrap_map.rs | 19 +-- crates/editor/src/editor.rs | 2 +- crates/editor/src/element.rs | 49 ++++---- crates/editor/src/multi_buffer.rs | 30 ++--- crates/find/src/find.rs | 2 +- crates/language/src/buffer.rs | 137 +++++++++++---------- crates/language/src/tests.rs | 2 +- 11 files changed, 141 insertions(+), 168 deletions(-) diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 8757e7593b58137d57c9cb341149e1e069576726..b1f11f42757269293a8d1a2c27fd7572229749e1 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -12,7 +12,6 @@ use language::{Point, Subscription as BufferSubscription}; use std::ops::Range; use sum_tree::Bias; use tab_map::TabMap; -use theme::SyntaxTheme; use wrap_map::WrapMap; pub use block_map::{ @@ -251,16 +250,12 @@ impl DisplaySnapshot { pub fn text_chunks(&self, display_row: u32) -> impl Iterator { self.blocks_snapshot - .chunks(display_row..self.max_point().row() + 1, None) + .chunks(display_row..self.max_point().row() + 1) .map(|h| h.text) } - pub fn chunks<'a>( - &'a self, - display_rows: Range, - theme: Option<&'a SyntaxTheme>, - ) -> DisplayChunks<'a> { - self.blocks_snapshot.chunks(display_rows, theme) + pub fn chunks<'a>(&'a self, display_rows: Range) -> DisplayChunks<'a> { + self.blocks_snapshot.chunks(display_rows) } pub fn chars_at<'a>(&'a self, point: DisplayPoint) -> impl Iterator + 'a { @@ -1122,8 +1117,10 @@ mod tests { ) -> Vec<(String, Option)> { let snapshot = map.update(cx, |map, cx| map.snapshot(cx)); let mut chunks: Vec<(String, Option)> = Vec::new(); - for chunk in snapshot.chunks(rows, Some(theme)) { - let color = chunk.highlight_style.map(|s| s.color); + for chunk in snapshot.chunks(rows) { + let color = chunk + .highlight_id + .and_then(|id| id.style(theme).map(|s| s.color)); if let Some((last_chunk, last_color)) = chunks.last_mut() { if color == *last_color { last_chunk.push_str(chunk.text); diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index f00dd8965186034b8cda189670c87b0fed0b9032..600bfbfad1159b00739dc528ddf474d927fcabb1 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -15,7 +15,6 @@ use std::{ }; use sum_tree::{Bias, SumTree}; use text::{Edit, Point}; -use theme::SyntaxTheme; const NEWLINES: &'static [u8] = &[b'\n'; u8::MAX as usize]; @@ -461,16 +460,12 @@ impl<'a> BlockMapWriter<'a> { impl BlockSnapshot { #[cfg(test)] pub fn text(&self) -> String { - self.chunks(0..self.transforms.summary().output_rows, None) + self.chunks(0..self.transforms.summary().output_rows) .map(|chunk| chunk.text) .collect() } - pub fn chunks<'a>( - &'a self, - rows: Range, - theme: Option<&'a SyntaxTheme>, - ) -> BlockChunks<'a> { + pub fn chunks<'a>(&'a self, rows: Range) -> BlockChunks<'a> { let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows); let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>(); let input_end = { @@ -498,7 +493,7 @@ impl BlockSnapshot { cursor.start().1 .0 + overshoot }; BlockChunks { - input_chunks: self.wrap_snapshot.chunks(input_start..input_end, theme), + input_chunks: self.wrap_snapshot.chunks(input_start..input_end), input_chunk: Default::default(), transforms: cursor, output_row: rows.start, @@ -715,7 +710,7 @@ impl<'a> Iterator for BlockChunks<'a> { return Some(Chunk { text: unsafe { std::str::from_utf8_unchecked(&NEWLINES[..line_count as usize]) }, - highlight_style: None, + highlight_id: None, diagnostic: None, }); } @@ -1340,7 +1335,7 @@ mod tests { for start_row in 0..expected_row_count { let expected_text = expected_lines[start_row..].join("\n"); let actual_text = blocks_snapshot - .chunks(start_row as u32..expected_row_count as u32, None) + .chunks(start_row as u32..expected_row_count as u32) .map(|chunk| chunk.text) .collect::(); assert_eq!( diff --git a/crates/editor/src/display_map/fold_map.rs b/crates/editor/src/display_map/fold_map.rs index fd5f1de8f810ca0d1eb0d1c86f90627a0985cc83..ab21977dfa64aa3f090a4d574175316dfc31521b 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -11,7 +11,6 @@ use std::{ sync::atomic::{AtomicUsize, Ordering::SeqCst}, }; use sum_tree::{Bias, Cursor, FilterCursor, SumTree}; -use theme::SyntaxTheme; pub trait ToFoldPoint { fn to_fold_point(&self, snapshot: &FoldSnapshot, bias: Bias) -> FoldPoint; @@ -490,7 +489,7 @@ impl FoldSnapshot { #[cfg(test)] pub fn text(&self) -> String { - self.chunks(FoldOffset(0)..self.len(), None) + self.chunks(FoldOffset(0)..self.len()) .map(|c| c.text) .collect() } @@ -630,15 +629,11 @@ impl FoldSnapshot { pub fn chars_at(&self, start: FoldPoint) -> impl '_ + Iterator { let start = start.to_offset(self); - self.chunks(start..self.len(), None) + self.chunks(start..self.len()) .flat_map(|chunk| chunk.text.chars()) } - pub fn chunks<'a>( - &'a self, - range: Range, - theme: Option<&'a SyntaxTheme>, - ) -> FoldChunks<'a> { + pub fn chunks<'a>(&'a self, range: Range) -> FoldChunks<'a> { let mut transform_cursor = self.transforms.cursor::<(FoldOffset, usize)>(); transform_cursor.seek(&range.end, Bias::Right, &()); @@ -651,7 +646,7 @@ impl FoldSnapshot { FoldChunks { transform_cursor, - buffer_chunks: self.buffer_snapshot.chunks(buffer_start..buffer_end, theme), + buffer_chunks: self.buffer_snapshot.chunks(buffer_start..buffer_end), buffer_chunk: None, buffer_offset: buffer_start, output_offset: range.start.0, @@ -976,7 +971,7 @@ impl<'a> Iterator for FoldChunks<'a> { self.output_offset += output_text.len(); return Some(Chunk { text: output_text, - highlight_style: None, + highlight_id: None, diagnostic: None, }); } @@ -1398,7 +1393,7 @@ mod tests { let text = &expected_text[start.0..end.0]; assert_eq!( snapshot - .chunks(start..end, None) + .chunks(start..end) .map(|c| c.text) .collect::(), text, diff --git a/crates/editor/src/display_map/tab_map.rs b/crates/editor/src/display_map/tab_map.rs index 9b33a10b149e9eb1e3431c4bd8f0ae8c36cd066a..9d58e87d8d348355ef59ee22a7484d78d9cc13d6 100644 --- a/crates/editor/src/display_map/tab_map.rs +++ b/crates/editor/src/display_map/tab_map.rs @@ -5,7 +5,6 @@ use parking_lot::Mutex; use std::{cmp, mem, ops::Range}; use sum_tree::Bias; use text::Point; -use theme::SyntaxTheme; pub struct TabMap(Mutex); @@ -35,7 +34,7 @@ impl TabMap { let mut delta = 0; for chunk in old_snapshot .fold_snapshot - .chunks(fold_edit.old.end..max_offset, None) + .chunks(fold_edit.old.end..max_offset) { let patterns: &[_] = &['\t', '\n']; if let Some(ix) = chunk.text.find(patterns) { @@ -110,7 +109,7 @@ impl TabSnapshot { self.max_point() }; for c in self - .chunks(range.start..line_end, None) + .chunks(range.start..line_end) .flat_map(|chunk| chunk.text.chars()) { if c == '\n' { @@ -124,7 +123,7 @@ impl TabSnapshot { last_line_chars = first_line_chars; } else { for _ in self - .chunks(TabPoint::new(range.end.row(), 0)..range.end, None) + .chunks(TabPoint::new(range.end.row(), 0)..range.end) .flat_map(|chunk| chunk.text.chars()) { last_line_chars += 1; @@ -144,11 +143,7 @@ impl TabSnapshot { self.fold_snapshot.version } - pub fn chunks<'a>( - &'a self, - range: Range, - theme: Option<&'a SyntaxTheme>, - ) -> TabChunks<'a> { + pub fn chunks<'a>(&'a self, range: Range) -> TabChunks<'a> { let (input_start, expanded_char_column, to_next_stop) = self.to_fold_point(range.start, Bias::Left); let input_start = input_start.to_offset(&self.fold_snapshot); @@ -163,7 +158,7 @@ impl TabSnapshot { }; TabChunks { - fold_chunks: self.fold_snapshot.chunks(input_start..input_end, theme), + fold_chunks: self.fold_snapshot.chunks(input_start..input_end), column: expanded_char_column, output_position: range.start.0, max_output_position: range.end.0, @@ -182,7 +177,7 @@ impl TabSnapshot { #[cfg(test)] pub fn text(&self) -> String { - self.chunks(TabPoint::zero()..self.max_point(), None) + self.chunks(TabPoint::zero()..self.max_point()) .map(|chunk| chunk.text) .collect() } @@ -495,7 +490,7 @@ mod tests { assert_eq!( expected_text, tabs_snapshot - .chunks(start..end, None) + .chunks(start..end) .map(|c| c.text) .collect::(), "chunks({:?}..{:?})", diff --git a/crates/editor/src/display_map/wrap_map.rs b/crates/editor/src/display_map/wrap_map.rs index 8b02dbbd15c72297ee28ba02632d097dde8ec8e8..df1d17c5006c63c006c208fe35bd2a766d78a955 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -13,7 +13,6 @@ use smol::future::yield_now; use std::{cmp, collections::VecDeque, mem, ops::Range, time::Duration}; use sum_tree::{Bias, Cursor, SumTree}; use text::Patch; -use theme::SyntaxTheme; pub use super::tab_map::TextSummary; pub type WrapEdit = text::Edit; @@ -434,10 +433,8 @@ impl WrapSnapshot { let mut line = String::new(); let mut remaining = None; - let mut chunks = new_tab_snapshot.chunks( - TabPoint::new(edit.new_rows.start, 0)..new_tab_snapshot.max_point(), - None, - ); + let mut chunks = new_tab_snapshot + .chunks(TabPoint::new(edit.new_rows.start, 0)..new_tab_snapshot.max_point()); let mut edit_transforms = Vec::::new(); for _ in edit.new_rows.start..edit.new_rows.end { while let Some(chunk) = @@ -562,15 +559,11 @@ impl WrapSnapshot { } pub fn text_chunks(&self, wrap_row: u32) -> impl Iterator { - self.chunks(wrap_row..self.max_point().row() + 1, None) + self.chunks(wrap_row..self.max_point().row() + 1) .map(|h| h.text) } - pub fn chunks<'a>( - &'a self, - rows: Range, - theme: Option<&'a SyntaxTheme>, - ) -> WrapChunks<'a> { + pub fn chunks<'a>(&'a self, rows: Range) -> WrapChunks<'a> { let output_start = WrapPoint::new(rows.start, 0); let output_end = WrapPoint::new(rows.end, 0); let mut transforms = self.transforms.cursor::<(WrapPoint, TabPoint)>(); @@ -583,7 +576,7 @@ impl WrapSnapshot { .to_tab_point(output_end) .min(self.tab_snapshot.max_point()); WrapChunks { - input_chunks: self.tab_snapshot.chunks(input_start..input_end, theme), + input_chunks: self.tab_snapshot.chunks(input_start..input_end), input_chunk: Default::default(), output_position: output_start, max_output_row: rows.end, @@ -1295,7 +1288,7 @@ mod tests { } let actual_text = self - .chunks(start_row..end_row, None) + .chunks(start_row..end_row) .map(|c| c.text) .collect::(); assert_eq!( diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 9db6fa0a0cd262284f876132496b483f4692299c..d97d1f864bbea1180fa5f4f30d8ca07d503fe9d6 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1628,7 +1628,7 @@ impl Editor { .map(|(id, completion)| { StringMatchCandidate::new( id, - completion.label()[completion.filter_range()].into(), + completion.lsp_completion.label[completion.filter_range()].into(), ) }) .collect(), diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 5fc294bac414c84f71924b94af12fc82f2289a6c..53175c917c2e32234130270c26733e27c495c881 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -598,31 +598,32 @@ impl EditorElement { .collect(); } else { let style = &self.settings.style; - let chunks = snapshot - .chunks(rows.clone(), Some(&style.syntax)) - .map(|chunk| { - let highlight = if let Some(severity) = chunk.diagnostic { - let diagnostic_style = super::diagnostic_style(severity, true, style); - let underline = Some(Underline { - color: diagnostic_style.message.text.color, - thickness: 1.0.into(), - squiggly: true, - }); - if let Some(mut highlight) = chunk.highlight_style { - highlight.underline = underline; - Some(highlight) - } else { - Some(HighlightStyle { - underline, - color: style.text.color, - font_properties: style.text.font_properties, - }) - } + let chunks = snapshot.chunks(rows.clone()).map(|chunk| { + let highlight_style = chunk + .highlight_id + .and_then(|highlight_id| highlight_id.style(&style.syntax)); + let highlight = if let Some(severity) = chunk.diagnostic { + let diagnostic_style = super::diagnostic_style(severity, true, style); + let underline = Some(Underline { + color: diagnostic_style.message.text.color, + thickness: 1.0.into(), + squiggly: true, + }); + if let Some(mut highlight) = highlight_style { + highlight.underline = underline; + Some(highlight) } else { - chunk.highlight_style - }; - (chunk.text, highlight) - }); + Some(HighlightStyle { + underline, + color: style.text.color, + font_properties: style.text.font_properties, + }) + } + } else { + highlight_style + }; + (chunk.text, highlight) + }); layout_highlighted_chunks( chunks, &style.text, diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index ebac70b73b1ddd5cb20f8bda0e1bb400fe44a640..8e649b919fa1a47676c7c6e674ff139e27b5ff57 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -125,7 +125,6 @@ pub struct MultiBufferChunks<'a> { range: Range, excerpts: Cursor<'a, Excerpt, usize>, excerpt_chunks: Option>, - theme: Option<&'a SyntaxTheme>, } pub struct MultiBufferBytes<'a> { @@ -1113,9 +1112,7 @@ impl Entity for MultiBuffer { impl MultiBufferSnapshot { pub fn text(&self) -> String { - self.chunks(0..self.len(), None) - .map(|chunk| chunk.text) - .collect() + self.chunks(0..self.len()).map(|chunk| chunk.text).collect() } pub fn reversed_chars_at<'a, T: ToOffset>( @@ -1165,7 +1162,7 @@ impl MultiBufferSnapshot { &'a self, range: Range, ) -> impl Iterator { - self.chunks(range, None).map(|chunk| chunk.text) + self.chunks(range).map(|chunk| chunk.text) } pub fn is_line_blank(&self, row: u32) -> bool { @@ -1323,17 +1320,12 @@ impl MultiBufferSnapshot { result } - pub fn chunks<'a, T: ToOffset>( - &'a self, - range: Range, - theme: Option<&'a SyntaxTheme>, - ) -> MultiBufferChunks<'a> { + pub fn chunks<'a, T: ToOffset>(&'a self, range: Range) -> MultiBufferChunks<'a> { let range = range.start.to_offset(self)..range.end.to_offset(self); let mut chunks = MultiBufferChunks { range: range.clone(), excerpts: self.excerpts.cursor(), excerpt_chunks: None, - theme, }; chunks.seek(range.start); chunks @@ -2116,11 +2108,7 @@ impl Excerpt { } } - fn chunks_in_range<'a>( - &'a self, - range: Range, - theme: Option<&'a SyntaxTheme>, - ) -> ExcerptChunks<'a> { + fn chunks_in_range<'a>(&'a self, range: Range) -> ExcerptChunks<'a> { let content_start = self.range.start.to_offset(&self.buffer); let chunks_start = content_start + range.start; let chunks_end = content_start + cmp::min(range.end, self.text_summary.bytes); @@ -2134,7 +2122,7 @@ impl Excerpt { 0 }; - let content_chunks = self.buffer.chunks(chunks_start..chunks_end, theme); + let content_chunks = self.buffer.chunks(chunks_start..chunks_end); ExcerptChunks { content_chunks, @@ -2333,7 +2321,6 @@ impl<'a> MultiBufferChunks<'a> { if let Some(excerpt) = self.excerpts.item() { self.excerpt_chunks = Some(excerpt.chunks_in_range( self.range.start - self.excerpts.start()..self.range.end - self.excerpts.start(), - self.theme, )); } else { self.excerpt_chunks = None; @@ -2353,9 +2340,8 @@ impl<'a> Iterator for MultiBufferChunks<'a> { } else { self.excerpts.next(&()); let excerpt = self.excerpts.item()?; - self.excerpt_chunks = Some( - excerpt.chunks_in_range(0..self.range.end - self.excerpts.start(), self.theme), - ); + self.excerpt_chunks = + Some(excerpt.chunks_in_range(0..self.range.end - self.excerpts.start())); self.next() } } @@ -3110,7 +3096,7 @@ mod tests { let mut buffer_point_utf16 = buffer_start_point_utf16; for ch in buffer .snapshot() - .chunks(buffer_range.clone(), None) + .chunks(buffer_range.clone()) .flat_map(|c| c.text.chars()) { for _ in 0..ch.len_utf8() { diff --git a/crates/find/src/find.rs b/crates/find/src/find.rs index 859e9f4923f1804daf5de5202b59d278de90e61b..354016e576e98e2a2cf899fa55d133c00ecfc151 100644 --- a/crates/find/src/find.rs +++ b/crates/find/src/find.rs @@ -607,7 +607,7 @@ async fn regex_search( let mut line = String::new(); let mut line_offset = 0; for (chunk_ix, chunk) in buffer - .chunks(0..buffer.len(), None) + .chunks(0..buffer.len()) .map(|c| c.text) .chain(["\n"]) .enumerate() diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 23b2a752c611a4bf28550e46ae1e9f018dfd8fcc..635f2973c663d77f7b8bcf0d03477513313321c0 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -12,7 +12,7 @@ use crate::{ use anyhow::{anyhow, Result}; use clock::ReplicaId; use futures::FutureExt as _; -use gpui::{fonts::HighlightStyle, AppContext, Entity, ModelContext, MutableAppContext, Task}; +use gpui::{AppContext, Entity, ModelContext, MutableAppContext, Task}; use lazy_static::lazy_static; use lsp::LanguageServer; use parking_lot::Mutex; @@ -358,7 +358,6 @@ struct BufferChunkHighlights<'a> { next_capture: Option<(tree_sitter::QueryMatch<'a, 'a>, usize)>, stack: Vec<(usize, HighlightId)>, highlight_map: HighlightMap, - theme: &'a SyntaxTheme, _query_cursor: QueryCursorHandle, } @@ -376,7 +375,7 @@ pub struct BufferChunks<'a> { #[derive(Clone, Copy, Debug, Default)] pub struct Chunk<'a> { pub text: &'a str, - pub highlight_style: Option, + pub highlight_id: Option, pub diagnostic: Option, } @@ -387,7 +386,7 @@ pub(crate) struct Diff { } #[derive(Clone, Copy)] -struct DiagnosticEndpoint { +pub(crate) struct DiagnosticEndpoint { offset: usize, is_start: bool, severity: DiagnosticSeverity, @@ -2117,67 +2116,31 @@ impl BufferSnapshot { None } - pub fn chunks<'a, T: ToOffset>( - &'a self, - range: Range, - theme: Option<&'a SyntaxTheme>, - ) -> BufferChunks<'a> { + pub fn chunks<'a, T: ToOffset>(&'a self, range: Range) -> BufferChunks<'a> { let range = range.start.to_offset(self)..range.end.to_offset(self); - let mut highlights = None; let mut diagnostic_endpoints = Vec::::new(); - if let Some(theme) = theme { - for entry in self.diagnostics_in_range::<_, usize>(range.clone()) { - diagnostic_endpoints.push(DiagnosticEndpoint { - offset: entry.range.start, - is_start: true, - severity: entry.diagnostic.severity, - }); - diagnostic_endpoints.push(DiagnosticEndpoint { - offset: entry.range.end, - is_start: false, - severity: entry.diagnostic.severity, - }); - } - diagnostic_endpoints - .sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start)); - - if let Some((grammar, tree)) = self.grammar().zip(self.tree.as_ref()) { - let mut query_cursor = QueryCursorHandle::new(); - - // TODO - add a Tree-sitter API to remove the need for this. - let cursor = unsafe { - std::mem::transmute::<_, &'static mut QueryCursor>(query_cursor.deref_mut()) - }; - let captures = cursor.set_byte_range(range.clone()).captures( - &grammar.highlights_query, - tree.root_node(), - TextProvider(self.text.as_rope()), - ); - highlights = Some(BufferChunkHighlights { - captures, - next_capture: None, - stack: Default::default(), - highlight_map: grammar.highlight_map(), - _query_cursor: query_cursor, - theme, - }) - } + for entry in self.diagnostics_in_range::<_, usize>(range.clone()) { + diagnostic_endpoints.push(DiagnosticEndpoint { + offset: entry.range.start, + is_start: true, + severity: entry.diagnostic.severity, + }); + diagnostic_endpoints.push(DiagnosticEndpoint { + offset: entry.range.end, + is_start: false, + severity: entry.diagnostic.severity, + }); } + diagnostic_endpoints.sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start)); - let diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable(); - let chunks = self.text.as_rope().chunks_in_range(range.clone()); - - BufferChunks { + BufferChunks::new( + self.text.as_rope(), range, - chunks, + self.tree.as_ref(), + self.grammar(), diagnostic_endpoints, - error_depth: 0, - warning_depth: 0, - information_depth: 0, - hint_depth: 0, - highlights, - } + ) } pub fn language(&self) -> Option<&Arc> { @@ -2218,7 +2181,7 @@ impl BufferSnapshot { TextProvider(self.as_rope()), ); - let mut chunks = self.chunks(0..self.len(), theme); + let mut chunks = self.chunks(0..self.len()); let item_capture_ix = grammar.outline_query.capture_index_for_name("item")?; let name_capture_ix = grammar.outline_query.capture_index_for_name("name")?; @@ -2272,7 +2235,11 @@ impl BufferSnapshot { } else { offset += chunk.text.len(); } - if let Some(style) = chunk.highlight_style { + let style = chunk + .highlight_id + .zip(theme) + .and_then(|(highlight, theme)| highlight.style(theme)); + if let Some(style) = style { let start = text.len(); let end = start + chunk.text.len(); highlight_ranges.push((start..end, style)); @@ -2460,6 +2427,50 @@ impl<'a> Iterator for ByteChunks<'a> { unsafe impl<'a> Send for BufferChunks<'a> {} impl<'a> BufferChunks<'a> { + pub(crate) fn new( + text: &'a Rope, + range: Range, + tree: Option<&'a Tree>, + grammar: Option<&'a Arc>, + diagnostic_endpoints: Vec, + ) -> Self { + let mut highlights = None; + if let Some((grammar, tree)) = grammar.zip(tree) { + let mut query_cursor = QueryCursorHandle::new(); + + // TODO - add a Tree-sitter API to remove the need for this. + let cursor = unsafe { + std::mem::transmute::<_, &'static mut QueryCursor>(query_cursor.deref_mut()) + }; + let captures = cursor.set_byte_range(range.clone()).captures( + &grammar.highlights_query, + tree.root_node(), + TextProvider(text), + ); + highlights = Some(BufferChunkHighlights { + captures, + next_capture: None, + stack: Default::default(), + highlight_map: grammar.highlight_map(), + _query_cursor: query_cursor, + }) + } + + let diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable(); + let chunks = text.chunks_in_range(range.clone()); + + BufferChunks { + range, + chunks, + diagnostic_endpoints, + error_depth: 0, + warning_depth: 0, + information_depth: 0, + hint_depth: 0, + highlights, + } + } + pub fn seek(&mut self, offset: usize) { self.range.start = offset; self.chunks.seek(self.range.start); @@ -2568,11 +2579,11 @@ impl<'a> Iterator for BufferChunks<'a> { let mut chunk_end = (self.chunks.offset() + chunk.len()) .min(next_capture_start) .min(next_diagnostic_endpoint); - let mut highlight_style = None; + let mut highlight_id = None; if let Some(highlights) = self.highlights.as_ref() { if let Some((parent_capture_end, parent_highlight_id)) = highlights.stack.last() { chunk_end = chunk_end.min(*parent_capture_end); - highlight_style = parent_highlight_id.style(highlights.theme); + highlight_id = Some(*parent_highlight_id); } } @@ -2585,7 +2596,7 @@ impl<'a> Iterator for BufferChunks<'a> { Some(Chunk { text: slice, - highlight_style, + highlight_id, diagnostic: self.current_diagnostic_severity(), }) } else { diff --git a/crates/language/src/tests.rs b/crates/language/src/tests.rs index 065ca28cec4d5aa3474e975e6290e3baac377bcf..bab62c23502ce39e01d506e9108b85160ca4b627 100644 --- a/crates/language/src/tests.rs +++ b/crates/language/src/tests.rs @@ -1090,7 +1090,7 @@ fn chunks_with_diagnostics( range: Range, ) -> Vec<(String, Option)> { let mut chunks: Vec<(String, Option)> = Vec::new(); - for chunk in buffer.snapshot().chunks(range, Some(&Default::default())) { + for chunk in buffer.snapshot().chunks(range) { if chunks .last() .map_or(false, |prev_chunk| prev_chunk.1 == chunk.diagnostic)