@@ -276,16 +276,6 @@ fn byte_range_to_str(range: std::ops::Range<usize>, source: RopeSlice) -> Cow<st
276 Cow::from(source.slice(start_char..end_char))
276 Cow::from(source.slice(start_char..end_char))
279−fn node_to_bytes<'a>(node: Node, source: RopeSlice<'a>) -> Cow<'a, [u8]> {
280− let start_char = source.byte_to_char(node.start_byte());
281− let end_char = source.byte_to_char(node.end_byte());
282− let fragment = source.slice(start_char..end_char);
283− match fragment.as_str() {
284− Some(fragment) => Cow::Borrowed(fragment.as_bytes()),
285− None => Cow::Owned(String::from(fragment).into_bytes()),
289impl Syntax {
279impl Syntax {
290 // buffer, grammar, config, grammars, sync_timeout?
280 // buffer, grammar, config, grammars, sync_timeout?
291 pub fn new(
281 pub fn new(
@@ -380,14 +370,11 @@ impl Syntax {
381 // TODO: if reusing cursors this might need resetting
371 // TODO: if reusing cursors this might need resetting
382 if let Some(range) = &range {
372 if let Some(range) = &range {
383− cursor_ref.set_byte_range(range.start, range.end);
373+ cursor_ref.set_byte_range(range.clone());
386 let captures = cursor_ref
376 let captures = cursor_ref
387− .captures(query_ref, tree_ref.root_node(), move |n: Node| {
377+ .captures(query_ref, tree_ref.root_node(), RopeProvider(source))
388− // &source[n.byte_range()]
389− node_to_bytes(n, source)
391 .peekable();
378 .peekable();
393 // manually craft the root layer based on the existing tree
380 // manually craft the root layer based on the existing tree
@@ -501,10 +488,7 @@ impl LanguageLayer {
501 // let mut injections_by_pattern_index =
488 // let mut injections_by_pattern_index =
502 // vec![(None, Vec::new(), false); combined_injections_query.pattern_count()];
489 // vec![(None, Vec::new(), false); combined_injections_query.pattern_count()];
503 // let matches =
490 // let matches =
504− // cursor.matches(combined_injections_query, tree.root_node(), |n: Node| {
491+ // cursor.matches(combined_injections_query, tree.root_node(), RopeProvider(source));
505− // // &source[n.byte_range()]
506− // node_to_bytes(n, source)
508 // for mat in matches {
492 // for mat in matches {
509 // let entry = &mut injections_by_pattern_index[mat.pattern_index];
493 // let entry = &mut injections_by_pattern_index[mat.pattern_index];
510 // let (language_name, content_node, include_children) =
494 // let (language_name, content_node, include_children) =
@@ -716,7 +700,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
716use std::{iter, mem, ops, str, usize};
700use std::{iter, mem, ops, str, usize};
717use tree_sitter::{
701use tree_sitter::{
718 Language as Grammar, Node, Parser, Point, Query, QueryCaptures, QueryCursor, QueryError,
702 Language as Grammar, Node, Parser, Point, Query, QueryCaptures, QueryCursor, QueryError,
719− QueryMatch, Range, Tree,
703+ QueryMatch, Range, TextProvider, Tree,
722const CANCELLATION_CHECK_INTERVAL: usize = 100;
706const CANCELLATION_CHECK_INTERVAL: usize = 100;
@@ -776,7 +760,7 @@ struct LocalScope<'a> {
778#[derive(Debug)]
762#[derive(Debug)]
779−struct HighlightIter<'a, 'tree: 'a, F>
763+struct HighlightIter<'a, F>
781 F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
765 F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
@@ -784,16 +768,41 @@ where
784 byte_offset: usize,
768 byte_offset: usize,
785 injection_callback: F,
769 injection_callback: F,
786 cancellation_flag: Option<&'a AtomicUsize>,
770 cancellation_flag: Option<&'a AtomicUsize>,
787− layers: Vec<HighlightIterLayer<'a, 'tree>>,
771+ layers: Vec<HighlightIterLayer<'a>>,
788 iter_count: usize,
772 iter_count: usize,
789 next_event: Option<HighlightEvent>,
773 next_event: Option<HighlightEvent>,
790 last_highlight_range: Option<(usize, usize, usize)>,
774 last_highlight_range: Option<(usize, usize, usize)>,
777+// Adapter to convert rope chunks to bytes
778+struct ChunksBytes<'a> {
779+ chunks: ropey::iter::Chunks<'a>,
781+impl<'a> Iterator for ChunksBytes<'a> {
782+ type Item = &'a [u8];
783+ fn next(&mut self) -> Option<Self::Item> {
784+ self.chunks.next().map(str::as_bytes)
788+struct RopeProvider<'a>(RopeSlice<'a>);
789+impl<'a> TextProvider<'a> for RopeProvider<'a> {
790+ type I = ChunksBytes<'a>;
792+ fn text(&mut self, node: Node) -> Self::I {
793+ let start_char = self.0.byte_to_char(node.start_byte());
794+ let end_char = self.0.byte_to_char(node.end_byte());
795+ let fragment = self.0.slice(start_char..end_char);
797+ chunks: fragment.chunks(),
793−struct HighlightIterLayer<'a, 'tree: 'a> {
802+struct HighlightIterLayer<'a> {
794 _tree: Option<Tree>,
803 _tree: Option<Tree>,
795 cursor: QueryCursor,
804 cursor: QueryCursor,
796− captures: iter::Peekable<QueryCaptures<'a, 'tree, Cow<'a, [u8]>>>,
805+ captures: iter::Peekable<QueryCaptures<'a, 'a, RopeProvider<'a>>>,
797 config: &'a HighlightConfiguration,
806 config: &'a HighlightConfiguration,
798 highlight_end_stack: Vec<usize>,
807 highlight_end_stack: Vec<usize>,
799 scope_stack: Vec<LocalScope<'a>>,
808 scope_stack: Vec<LocalScope<'a>>,
@@ -801,7 +810,7 @@ struct HighlightIterLayer<'a, 'tree: 'a> {
801 depth: usize,
810 depth: usize,
804−impl<'a, 'tree: 'a> fmt::Debug for HighlightIterLayer<'a, 'tree> {
813+impl<'a> fmt::Debug for HighlightIterLayer<'a> {
805 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
814 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
806 f.debug_struct("HighlightIterLayer").finish()
815 f.debug_struct("HighlightIterLayer").finish()
@@ -972,7 +981,7 @@ impl HighlightConfiguration {
975−impl<'a, 'tree: 'a> HighlightIterLayer<'a, 'tree> {
984+impl<'a> HighlightIterLayer<'a> {
976 /// Create a new 'layer' of highlighting for this document.
985 /// Create a new 'layer' of highlighting for this document.
978 /// In the even that the new layer contains "combined injections" (injections where multiple
987 /// In the even that the new layer contains "combined injections" (injections where multiple
@@ -1029,10 +1038,7 @@ impl<'a, 'tree: 'a> HighlightIterLayer<'a, 'tree> {
1029 let matches = cursor.matches(
1038 let matches = cursor.matches(
1030 combined_injections_query,
1039 combined_injections_query,
1031 tree.root_node(),
1040 tree.root_node(),
1032− |n: Node| {
1041+ RopeProvider(source),
1033− // &source[n.byte_range()]
1034− node_to_bytes(n, source)
1037 for mat in matches {
1043 for mat in matches {
1038 let entry = &mut injections_by_pattern_index[mat.pattern_index];
1044 let entry = &mut injections_by_pattern_index[mat.pattern_index];
@@ -1079,10 +1085,7 @@ impl<'a, 'tree: 'a> HighlightIterLayer<'a, 'tree> {
1079 let cursor_ref =
1085 let cursor_ref =
1080 unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) };
1086 unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) };
1081 let captures = cursor_ref
1087 let captures = cursor_ref
1082− .captures(&config.query, tree_ref.root_node(), move |n: Node| {
1088+ .captures(&config.query, tree_ref.root_node(), RopeProvider(source))
1083− // &source[n.byte_range()]
1084− node_to_bytes(n, source)
1086 .peekable();
1089 .peekable();
1088 result.push(HighlightIterLayer {
1091 result.push(HighlightIterLayer {
@@ -1236,7 +1239,7 @@ impl<'a, 'tree: 'a> HighlightIterLayer<'a, 'tree> {
1239−impl<'a, 'tree: 'a, F> HighlightIter<'a, 'tree, F>
1242+impl<'a, F> HighlightIter<'a, F>
1241 F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
1244 F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
@@ -1287,7 +1290,7 @@ where
1290− fn insert_layer(&mut self, mut layer: HighlightIterLayer<'a, 'tree>) {
1293+ fn insert_layer(&mut self, mut layer: HighlightIterLayer<'a>) {
1291 if let Some(sort_key) = layer.sort_key() {
1294 if let Some(sort_key) = layer.sort_key() {
1292 let mut i = 1;
1295 let mut i = 1;
1293 while i < self.layers.len() {
1296 while i < self.layers.len() {
@@ -1306,7 +1309,7 @@ where
1309−impl<'a, 'tree: 'a, F> Iterator for HighlightIter<'a, 'tree, F>
1312+impl<'a, F> Iterator for HighlightIter<'a, F>
1311 F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
1314 F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
@@ -1570,7 +1573,7 @@ where
1570fn injection_for_match<'a>(
1573fn injection_for_match<'a>(
1571 config: &HighlightConfiguration,
1574 config: &HighlightConfiguration,
1572 query: &'a Query,
1575 query: &'a Query,
1573− query_match: &QueryMatch<'a>,
1576+ query_match: &QueryMatch<'a, 'a>,
1574 source: RopeSlice<'a>,
1577 source: RopeSlice<'a>,
1575) -> (Option<Cow<'a, str>>, Option<Node<'a>>, bool) {
1578) -> (Option<Cow<'a, str>>, Option<Node<'a>>, bool) {
1576 let content_capture_index = config.injection_content_capture_index;
1579 let content_capture_index = config.injection_content_capture_index;