Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-syntax/src/highlighter.rs')
-rw-r--r--helix-syntax/src/highlighter.rs877
1 files changed, 438 insertions, 439 deletions
diff --git a/helix-syntax/src/highlighter.rs b/helix-syntax/src/highlighter.rs
index 1b53672f..8801b13f 100644
--- a/helix-syntax/src/highlighter.rs
+++ b/helix-syntax/src/highlighter.rs
@@ -1,439 +1,438 @@
-use std::borrow::Cow;
-use std::cell::RefCell;
-use std::sync::atomic::{self, AtomicUsize};
-use std::{fmt, iter, mem, ops};
-
-use ropey::RopeSlice;
-use tree_sitter::{QueryCaptures, QueryCursor, Tree};
-
-use crate::ropey::RopeProvider;
-use crate::{
- byte_range_to_str, Error, HighlightConfiguration, Syntax, PARSER, TREE_SITTER_MATCH_LIMIT,
-};
-
-const CANCELLATION_CHECK_INTERVAL: usize = 100;
-
-/// Indicates which highlight should be applied to a region of source code.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct Highlight(pub usize);
-
-/// Represents a single step in rendering a syntax-highlighted document.
-#[derive(Copy, Clone, Debug)]
-pub enum HighlightEvent {
- Source { start: usize, end: usize },
- HighlightStart(Highlight),
- HighlightEnd,
-}
-
-#[derive(Debug)]
-struct LocalDef<'a> {
- name: Cow<'a, str>,
- value_range: ops::Range<usize>,
- highlight: Option<Highlight>,
-}
-
-#[derive(Debug)]
-struct LocalScope<'a> {
- inherits: bool,
- range: ops::Range<usize>,
- local_defs: Vec<LocalDef<'a>>,
-}
-
-#[derive(Debug)]
-struct HighlightIter<'a> {
- source: RopeSlice<'a>,
- byte_offset: usize,
- cancellation_flag: Option<&'a AtomicUsize>,
- layers: Vec<HighlightIterLayer<'a>>,
- iter_count: usize,
- next_event: Option<HighlightEvent>,
- last_highlight_range: Option<(usize, usize, u32)>,
-}
-
-struct HighlightIterLayer<'a> {
- _tree: Option<Tree>,
- cursor: QueryCursor,
- captures: RefCell<iter::Peekable<QueryCaptures<'a, 'a, RopeProvider<'a>, &'a [u8]>>>,
- config: &'a HighlightConfiguration,
- highlight_end_stack: Vec<usize>,
- scope_stack: Vec<LocalScope<'a>>,
- depth: u32,
-}
-
-impl<'a> fmt::Debug for HighlightIterLayer<'a> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("HighlightIterLayer").finish()
- }
-}
-
-impl<'a> HighlightIterLayer<'a> {
- // First, sort scope boundaries by their byte offset in the document. At a
- // given position, emit scope endings before scope beginnings. Finally, emit
- // scope boundaries from deeper layers first.
- fn sort_key(&self) -> Option<(usize, bool, isize)> {
- let depth = -(self.depth as isize);
- let next_start = self
- .captures
- .borrow_mut()
- .peek()
- .map(|(m, i)| m.captures[*i].node.start_byte());
- let next_end = self.highlight_end_stack.last().cloned();
- match (next_start, next_end) {
- (Some(start), Some(end)) => {
- if start < end {
- Some((start, true, depth))
- } else {
- Some((end, false, depth))
- }
- }
- (Some(i), None) => Some((i, true, depth)),
- (None, Some(j)) => Some((j, false, depth)),
- _ => None,
- }
- }
-}
-
-impl<'a> HighlightIter<'a> {
- fn emit_event(
- &mut self,
- offset: usize,
- event: Option<HighlightEvent>,
- ) -> Option<Result<HighlightEvent, Error>> {
- let result;
- if self.byte_offset < offset {
- result = Some(Ok(HighlightEvent::Source {
- start: self.byte_offset,
- end: offset,
- }));
- self.byte_offset = offset;
- self.next_event = event;
- } else {
- result = event.map(Ok);
- }
- self.sort_layers();
- result
- }
-
- fn sort_layers(&mut self) {
- while !self.layers.is_empty() {
- if let Some(sort_key) = self.layers[0].sort_key() {
- let mut i = 0;
- while i + 1 < self.layers.len() {
- if let Some(next_offset) = self.layers[i + 1].sort_key() {
- if next_offset < sort_key {
- i += 1;
- continue;
- }
- } else {
- let layer = self.layers.remove(i + 1);
- PARSER.with(|ts_parser| {
- let highlighter = &mut ts_parser.borrow_mut();
- highlighter.cursors.push(layer.cursor);
- });
- }
- break;
- }
- if i > 0 {
- self.layers[0..(i + 1)].rotate_left(1);
- }
- break;
- } else {
- let layer = self.layers.remove(0);
- PARSER.with(|ts_parser| {
- let highlighter = &mut ts_parser.borrow_mut();
- highlighter.cursors.push(layer.cursor);
- });
- }
- }
- }
-}
-
-impl<'a> Iterator for HighlightIter<'a> {
- type Item = Result<HighlightEvent, Error>;
-
- fn next(&mut self) -> Option<Self::Item> {
- 'main: loop {
- // If we've already determined the next highlight boundary, just return it.
- if let Some(e) = self.next_event.take() {
- return Some(Ok(e));
- }
-
- // Periodically check for cancellation, returning `Cancelled` error if the
- // cancellation flag was flipped.
- if let Some(cancellation_flag) = self.cancellation_flag {
- self.iter_count += 1;
- if self.iter_count >= CANCELLATION_CHECK_INTERVAL {
- self.iter_count = 0;
- if cancellation_flag.load(atomic::Ordering::Relaxed) != 0 {
- return Some(Err(Error::Cancelled));
- }
- }
- }
-
- // If none of the layers have any more highlight boundaries, terminate.
- if self.layers.is_empty() {
- let len = self.source.len_bytes();
- return if self.byte_offset < len {
- let result = Some(Ok(HighlightEvent::Source {
- start: self.byte_offset,
- end: len,
- }));
- self.byte_offset = len;
- result
- } else {
- None
- };
- }
-
- // Get the next capture from whichever layer has the earliest highlight boundary.
- let range;
- let layer = &mut self.layers[0];
- let captures = layer.captures.get_mut();
- if let Some((next_match, capture_index)) = captures.peek() {
- let next_capture = next_match.captures[*capture_index];
- range = next_capture.node.byte_range();
-
- // If any previous highlight ends before this node starts, then before
- // processing this capture, emit the source code up until the end of the
- // previous highlight, and an end event for that highlight.
- if let Some(end_byte) = layer.highlight_end_stack.last().cloned() {
- if end_byte <= range.start {
- layer.highlight_end_stack.pop();
- return self.emit_event(end_byte, Some(HighlightEvent::HighlightEnd));
- }
- }
- }
- // If there are no more captures, then emit any remaining highlight end events.
- // And if there are none of those, then just advance to the end of the document.
- else if let Some(end_byte) = layer.highlight_end_stack.last().cloned() {
- layer.highlight_end_stack.pop();
- return self.emit_event(end_byte, Some(HighlightEvent::HighlightEnd));
- } else {
- return self.emit_event(self.source.len_bytes(), None);
- };
-
- let (mut match_, capture_index) = captures.next().unwrap();
- let mut capture = match_.captures[capture_index];
-
- // Remove from the local scope stack any local scopes that have already ended.
- while range.start > layer.scope_stack.last().unwrap().range.end {
- layer.scope_stack.pop();
- }
-
- // If this capture is for tracking local variables, then process the
- // local variable info.
- let mut reference_highlight = None;
- let mut definition_highlight = None;
- while match_.pattern_index < layer.config.highlights_pattern_index {
- // If the node represents a local scope, push a new local scope onto
- // the scope stack.
- if Some(capture.index) == layer.config.local_scope_capture_index {
- definition_highlight = None;
- let mut scope = LocalScope {
- inherits: true,
- range: range.clone(),
- local_defs: Vec::new(),
- };
- for prop in layer.config.query.property_settings(match_.pattern_index) {
- if let "local.scope-inherits" = prop.key.as_ref() {
- scope.inherits =
- prop.value.as_ref().map_or(true, |r| r.as_ref() == "true");
- }
- }
- layer.scope_stack.push(scope);
- }
- // If the node represents a definition, add a new definition to the
- // local scope at the top of the scope stack.
- else if Some(capture.index) == layer.config.local_def_capture_index {
- reference_highlight = None;
- let scope = layer.scope_stack.last_mut().unwrap();
-
- let mut value_range = 0..0;
- for capture in match_.captures {
- if Some(capture.index) == layer.config.local_def_value_capture_index {
- value_range = capture.node.byte_range();
- }
- }
-
- let name = byte_range_to_str(range.clone(), self.source);
- scope.local_defs.push(LocalDef {
- name,
- value_range,
- highlight: None,
- });
- definition_highlight = scope.local_defs.last_mut().map(|s| &mut s.highlight);
- }
- // If the node represents a reference, then try to find the corresponding
- // definition in the scope stack.
- else if Some(capture.index) == layer.config.local_ref_capture_index
- && definition_highlight.is_none()
- {
- definition_highlight = None;
- let name = byte_range_to_str(range.clone(), self.source);
- for scope in layer.scope_stack.iter().rev() {
- if let Some(highlight) = scope.local_defs.iter().rev().find_map(|def| {
- if def.name == name && range.start >= def.value_range.end {
- Some(def.highlight)
- } else {
- None
- }
- }) {
- reference_highlight = highlight;
- break;
- }
- if !scope.inherits {
- break;
- }
- }
- }
-
- // Continue processing any additional matches for the same node.
- if let Some((next_match, next_capture_index)) = captures.peek() {
- let next_capture = next_match.captures[*next_capture_index];
- if next_capture.node == capture.node {
- capture = next_capture;
- match_ = captures.next().unwrap().0;
- continue;
- }
- }
-
- self.sort_layers();
- continue 'main;
- }
-
- // Otherwise, this capture must represent a highlight.
- // If this exact range has already been highlighted by an earlier pattern, or by
- // a different layer, then skip over this one.
- if let Some((last_start, last_end, last_depth)) = self.last_highlight_range {
- if range.start == last_start && range.end == last_end && layer.depth < last_depth {
- self.sort_layers();
- continue 'main;
- }
- }
-
- // If the current node was found to be a local variable, then skip over any
- // highlighting patterns that are disabled for local variables.
- if definition_highlight.is_some() || reference_highlight.is_some() {
- while layer.config.non_local_variable_patterns[match_.pattern_index] {
- match_.remove();
- if let Some((next_match, next_capture_index)) = captures.peek() {
- let next_capture = next_match.captures[*next_capture_index];
- if next_capture.node == capture.node {
- capture = next_capture;
- match_ = captures.next().unwrap().0;
- continue;
- }
- }
-
- self.sort_layers();
- continue 'main;
- }
- }
-
- // Once a highlighting pattern is found for the current node, skip over
- // any later highlighting patterns that also match this node. Captures
- // for a given node are ordered by pattern index, so these subsequent
- // captures are guaranteed to be for highlighting, not injections or
- // local variables.
- while let Some((next_match, next_capture_index)) = captures.peek() {
- let next_capture = next_match.captures[*next_capture_index];
- if next_capture.node == capture.node {
- captures.next();
- } else {
- break;
- }
- }
-
- let current_highlight = layer.config.highlight_indices.load()[capture.index as usize];
-
- // If this node represents a local definition, then store the current
- // highlight value on the local scope entry representing this node.
- if let Some(definition_highlight) = definition_highlight {
- *definition_highlight = current_highlight;
- }
-
- // Emit a scope start event and push the node's end position to the stack.
- if let Some(highlight) = reference_highlight.or(current_highlight) {
- self.last_highlight_range = Some((range.start, range.end, layer.depth));
- layer.highlight_end_stack.push(range.end);
- return self
- .emit_event(range.start, Some(HighlightEvent::HighlightStart(highlight)));
- }
-
- self.sort_layers();
- }
- }
-}
-
-impl Syntax {
- /// Iterate over the highlighted regions for a given slice of source code.
- pub fn highlight_iter<'a>(
- &'a self,
- source: RopeSlice<'a>,
- range: Option<std::ops::Range<usize>>,
- cancellation_flag: Option<&'a AtomicUsize>,
- ) -> impl Iterator<Item = Result<HighlightEvent, Error>> + 'a {
- let mut layers = self
- .layers
- .iter()
- .filter_map(|(_, layer)| {
- // TODO: if range doesn't overlap layer range, skip it
-
- // Reuse a cursor from the pool if available.
- let mut cursor = PARSER.with(|ts_parser| {
- let highlighter = &mut ts_parser.borrow_mut();
- highlighter.cursors.pop().unwrap_or_else(QueryCursor::new)
- });
-
- // The `captures` iterator borrows the `Tree` and the `QueryCursor`, which
- // prevents them from being moved. But both of these values are really just
- // pointers, so it's actually ok to move them.
- let cursor_ref =
- unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) };
-
- // if reusing cursors & no range this resets to whole range
- cursor_ref.set_byte_range(range.clone().unwrap_or(0..usize::MAX));
- cursor_ref.set_match_limit(TREE_SITTER_MATCH_LIMIT);
-
- let mut captures = cursor_ref
- .captures(
- &layer.config.query,
- layer.tree().root_node(),
- RopeProvider(source),
- )
- .peekable();
-
- // If there's no captures, skip the layer
- captures.peek()?;
-
- Some(HighlightIterLayer {
- highlight_end_stack: Vec::new(),
- scope_stack: vec![LocalScope {
- inherits: false,
- range: 0..usize::MAX,
- local_defs: Vec::new(),
- }],
- cursor,
- _tree: None,
- captures: RefCell::new(captures),
- config: layer.config.as_ref(), // TODO: just reuse `layer`
- depth: layer.depth, // TODO: just reuse `layer`
- })
- })
- .collect::<Vec<_>>();
-
- layers.sort_unstable_by_key(|layer| layer.sort_key());
-
- let mut result = HighlightIter {
- source,
- byte_offset: range.map_or(0, |r| r.start),
- cancellation_flag,
- iter_count: 0,
- layers,
- next_event: None,
- last_highlight_range: None,
- };
- result.sort_layers();
- result
- }
-}
+pub use super::highlighter2::*;
+
+// use std::borrow::Cow;
+// use std::cell::RefCell;
+// use std::sync::atomic::{self, AtomicUsize};
+// use std::{fmt, iter, mem, ops};
+
+// use ropey::RopeSlice;
+// use tree_sitter::{QueryCaptures, QueryCursor, Tree};
+
+// use crate::{byte_range_to_str, Error, HighlightConfiguration, Syntax, TREE_SITTER_MATCH_LIMIT};
+
+// const CANCELLATION_CHECK_INTERVAL: usize = 100;
+
+// /// Indicates which highlight should be applied to a region of source code.
+// #[derive(Copy, Clone, Debug, PartialEq, Eq)]
+// pub struct Highlight(pub usize);
+
+// /// Represents a single step in rendering a syntax-highlighted document.
+// #[derive(Copy, Clone, Debug)]
+// pub enum HighlightEvent {
+// Source { start: usize, end: usize },
+// HighlightStart(Highlight),
+// HighlightEnd,
+// }
+
+// #[derive(Debug)]
+// struct LocalDef<'a> {
+// name: Cow<'a, str>,
+// value_range: ops::Range<usize>,
+// highlight: Option<Highlight>,
+// }
+
+// #[derive(Debug)]
+// struct LocalScope<'a> {
+// inherits: bool,
+// range: ops::Range<usize>,
+// local_defs: Vec<LocalDef<'a>>,
+// }
+
+// #[derive(Debug)]
+// struct HighlightIter<'a> {
+// source: RopeSlice<'a>,
+// byte_offset: usize,
+// cancellation_flag: Option<&'a AtomicUsize>,
+// layers: Vec<HighlightIterLayer<'a>>,
+// iter_count: usize,
+// next_event: Option<HighlightEvent>,
+// last_highlight_range: Option<(usize, usize, u32)>,
+// }
+
+// struct HighlightIterLayer<'a> {
+// _tree: Option<Tree>,
+// cursor: QueryCursor,
+// captures: RefCell<iter::Peekable<QueryCaptures<'a, 'a, RopeProvider<'a>, &'a [u8]>>>,
+// config: &'a HighlightConfiguration,
+// highlight_end_stack: Vec<usize>,
+// scope_stack: Vec<LocalScope<'a>>,
+// depth: u32,
+// }
+
+// impl<'a> fmt::Debug for HighlightIterLayer<'a> {
+// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+// f.debug_struct("HighlightIterLayer").finish()
+// }
+// }
+
+// impl<'a> HighlightIterLayer<'a> {
+// // First, sort scope boundaries by their byte offset in the document. At a
+// // given position, emit scope endings before scope beginnings. Finally, emit
+// // scope boundaries from deeper layers first.
+// fn sort_key(&self) -> Option<(usize, bool, isize)> {
+// let depth = -(self.depth as isize);
+// let next_start = self
+// .captures
+// .borrow_mut()
+// .peek()
+// .map(|(m, i)| m.captures[*i].node.start_byte());
+// let next_end = self.highlight_end_stack.last().cloned();
+// match (next_start, next_end) {
+// (Some(start), Some(end)) => {
+// if start < end {
+// Some((start, true, depth))
+// } else {
+// Some((end, false, depth))
+// }
+// }
+// (Some(i), None) => Some((i, true, depth)),
+// (None, Some(j)) => Some((j, false, depth)),
+// _ => None,
+// }
+// }
+// }
+
+// impl<'a> HighlightIter<'a> {
+// fn emit_event(
+// &mut self,
+// offset: usize,
+// event: Option<HighlightEvent>,
+// ) -> Option<Result<HighlightEvent, Error>> {
+// let result;
+// if self.byte_offset < offset {
+// result = Some(Ok(HighlightEvent::Source {
+// start: self.byte_offset,
+// end: offset,
+// }));
+// self.byte_offset = offset;
+// self.next_event = event;
+// } else {
+// result = event.map(Ok);
+// }
+// self.sort_layers();
+// result
+// }
+
+// fn sort_layers(&mut self) {
+// while !self.layers.is_empty() {
+// if let Some(sort_key) = self.layers[0].sort_key() {
+// let mut i = 0;
+// while i + 1 < self.layers.len() {
+// if let Some(next_offset) = self.layers[i + 1].sort_key() {
+// if next_offset < sort_key {
+// i += 1;
+// continue;
+// }
+// } else {
+// let layer = self.layers.remove(i + 1);
+// PARSER.with(|ts_parser| {
+// let highlighter = &mut ts_parser.borrow_mut();
+// highlighter.cursors.push(layer.cursor);
+// });
+// }
+// break;
+// }
+// if i > 0 {
+// self.layers[0..(i + 1)].rotate_left(1);
+// }
+// break;
+// } else {
+// let layer = self.layers.remove(0);
+// PARSER.with(|ts_parser| {
+// let highlighter = &mut ts_parser.borrow_mut();
+// highlighter.cursors.push(layer.cursor);
+// });
+// }
+// }
+// }
+// }
+
+// impl<'a> Iterator for HighlightIter<'a> {
+// type Item = Result<HighlightEvent, Error>;
+
+// fn next(&mut self) -> Option<Self::Item> {
+// 'main: loop {
+// // If we've already determined the next highlight boundary, just return it.
+// if let Some(e) = self.next_event.take() {
+// return Some(Ok(e));
+// }
+
+// // Periodically check for cancellation, returning `Cancelled` error if the
+// // cancellation flag was flipped.
+// if let Some(cancellation_flag) = self.cancellation_flag {
+// self.iter_count += 1;
+// if self.iter_count >= CANCELLATION_CHECK_INTERVAL {
+// self.iter_count = 0;
+// if cancellation_flag.load(atomic::Ordering::Relaxed) != 0 {
+// return Some(Err(Error::Cancelled));
+// }
+// }
+// }
+
+// // If none of the layers have any more highlight boundaries, terminate.
+// if self.layers.is_empty() {
+// let len = self.source.len_bytes();
+// return if self.byte_offset < len {
+// let result = Some(Ok(HighlightEvent::Source {
+// start: self.byte_offset,
+// end: len,
+// }));
+// self.byte_offset = len;
+// result
+// } else {
+// None
+// };
+// }
+
+// // Get the next capture from whichever layer has the earliest highlight boundary.
+// let range;
+// let layer = &mut self.layers[0];
+// let captures = layer.captures.get_mut();
+// if let Some((next_match, capture_index)) = captures.peek() {
+// let next_capture = next_match.captures[*capture_index];
+// range = next_capture.node.byte_range();
+
+// // If any previous highlight ends before this node starts, then before
+// // processing this capture, emit the source code up until the end of the
+// // previous highlight, and an end event for that highlight.
+// if let Some(end_byte) = layer.highlight_end_stack.last().cloned() {
+// if end_byte <= range.start {
+// layer.highlight_end_stack.pop();
+// return self.emit_event(end_byte, Some(HighlightEvent::HighlightEnd));
+// }
+// }
+// }
+// // If there are no more captures, then emit any remaining highlight end events.
+// // And if there are none of those, then just advance to the end of the document.
+// else if let Some(end_byte) = layer.highlight_end_stack.last().cloned() {
+// layer.highlight_end_stack.pop();
+// return self.emit_event(end_byte, Some(HighlightEvent::HighlightEnd));
+// } else {
+// return self.emit_event(self.source.len_bytes(), None);
+// };
+
+// let (mut match_, capture_index) = captures.next().unwrap();
+// let mut capture = match_.captures[capture_index];
+
+// // Remove from the local scope stack any local scopes that have already ended.
+// while range.start > layer.scope_stack.last().unwrap().range.end {
+// layer.scope_stack.pop();
+// }
+
+// // If this capture is for tracking local variables, then process the
+// // local variable info.
+// let mut reference_highlight = None;
+// let mut definition_highlight = None;
+// while match_.pattern_index < layer.config.highlights_pattern_index {
+// // If the node represents a local scope, push a new local scope onto
+// // the scope stack.
+// if Some(capture.index) == layer.config.local_scope_capture_index {
+// definition_highlight = None;
+// let mut scope = LocalScope {
+// inherits: true,
+// range: range.clone(),
+// local_defs: Vec::new(),
+// };
+// for prop in layer.config.query.property_settings(match_.pattern_index) {
+// if let "local.scope-inherits" = prop.key.as_ref() {
+// scope.inherits =
+// prop.value.as_ref().map_or(true, |r| r.as_ref() == "true");
+// }
+// }
+// layer.scope_stack.push(scope);
+// }
+// // If the node represents a definition, add a new definition to the
+// // local scope at the top of the scope stack.
+// else if Some(capture.index) == layer.config.local_def_capture_index {
+// reference_highlight = None;
+// let scope = layer.scope_stack.last_mut().unwrap();
+
+// let mut value_range = 0..0;
+// for capture in match_.captures {
+// if Some(capture.index) == layer.config.local_def_value_capture_index {
+// value_range = capture.node.byte_range();
+// }
+// }
+
+// let name = byte_range_to_str(range.clone(), self.source);
+// scope.local_defs.push(LocalDef {
+// name,
+// value_range,
+// highlight: None,
+// });
+// definition_highlight = scope.local_defs.last_mut().map(|s| &mut s.highlight);
+// }
+// // If the node represents a reference, then try to find the corresponding
+// // definition in the scope stack.
+// else if Some(capture.index) == layer.config.local_ref_capture_index
+// && definition_highlight.is_none()
+// {
+// definition_highlight = None;
+// let name = byte_range_to_str(range.clone(), self.source);
+// for scope in layer.scope_stack.iter().rev() {
+// if let Some(highlight) = scope.local_defs.iter().rev().find_map(|def| {
+// if def.name == name && range.start >= def.value_range.end {
+// Some(def.highlight)
+// } else {
+// None
+// }
+// }) {
+// reference_highlight = highlight;
+// break;
+// }
+// if !scope.inherits {
+// break;
+// }
+// }
+// }
+
+// // Continue processing any additional matches for the same node.
+// if let Some((next_match, next_capture_index)) = captures.peek() {
+// let next_capture = next_match.captures[*next_capture_index];
+// if next_capture.node == capture.node {
+// capture = next_capture;
+// match_ = captures.next().unwrap().0;
+// continue;
+// }
+// }
+
+// self.sort_layers();
+// continue 'main;
+// }
+
+// // Otherwise, this capture must represent a highlight.
+// // If this exact range has already been highlighted by an earlier pattern, or by
+// // a different layer, then skip over this one.
+// if let Some((last_start, last_end, last_depth)) = self.last_highlight_range {
+// if range.start == last_start && range.end == last_end && layer.depth < last_depth {
+// self.sort_layers();
+// continue 'main;
+// }
+// }
+
+// // If the current node was found to be a local variable, then skip over any
+// // highlighting patterns that are disabled for local variables.
+// if definition_highlight.is_some() || reference_highlight.is_some() {
+// while layer.config.non_local_variable_patterns[match_.pattern_index] {
+// match_.remove();
+// if let Some((next_match, next_capture_index)) = captures.peek() {
+// let next_capture = next_match.captures[*next_capture_index];
+// if next_capture.node == capture.node {
+// capture = next_capture;
+// match_ = captures.next().unwrap().0;
+// continue;
+// }
+// }
+
+// self.sort_layers();
+// continue 'main;
+// }
+// }
+
+// // Once a highlighting pattern is found for the current node, skip over
+// // any later highlighting patterns that also match this node. Captures
+// // for a given node are ordered by pattern index, so these subsequent
+// // captures are guaranteed to be for highlighting, not injections or
+// // local variables.
+// while let Some((next_match, next_capture_index)) = captures.peek() {
+// let next_capture = next_match.captures[*next_capture_index];
+// if next_capture.node == capture.node {
+// captures.next();
+// } else {
+// break;
+// }
+// }
+
+// let current_highlight = layer.config.highlight_indices.load()[capture.index as usize];
+
+// // If this node represents a local definition, then store the current
+// // highlight value on the local scope entry representing this node.
+// if let Some(definition_highlight) = definition_highlight {
+// *definition_highlight = current_highlight;
+// }
+
+// // Emit a scope start event and push the node's end position to the stack.
+// if let Some(highlight) = reference_highlight.or(current_highlight) {
+// self.last_highlight_range = Some((range.start, range.end, layer.depth));
+// layer.highlight_end_stack.push(range.end);
+// return self
+// .emit_event(range.start, Some(HighlightEvent::HighlightStart(highlight)));
+// }
+
+// self.sort_layers();
+// }
+// }
+// }
+
+// impl Syntax {
+// /// Iterate over the highlighted regions for a given slice of source code.
+// pub fn highlight_iter<'a>(
+// &'a self,
+// source: RopeSlice<'a>,
+// range: Option<std::ops::Range<usize>>,
+// cancellation_flag: Option<&'a AtomicUsize>,
+// ) -> impl Iterator<Item = Result<HighlightEvent, Error>> + 'a {
+// let mut layers = self
+// .layers
+// .iter()
+// .filter_map(|(_, layer)| {
+// // TODO: if range doesn't overlap layer range, skip it
+
+// // Reuse a cursor from the pool if available.
+// let mut cursor = PARSER.with(|ts_parser| {
+// let highlighter = &mut ts_parser.borrow_mut();
+// highlighter.cursors.pop().unwrap_or_else(QueryCursor::new)
+// });
+
+// // The `captures` iterator borrows the `Tree` and the `QueryCursor`, which
+// // prevents them from being moved. But both of these values are really just
+// // pointers, so it's actually ok to move them.
+// let cursor_ref =
+// unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) };
+
+// // if reusing cursors & no range this resets to whole range
+// cursor_ref.set_byte_range(range.clone().unwrap_or(0..usize::MAX));
+// cursor_ref.set_match_limit(TREE_SITTER_MATCH_LIMIT);
+
+// let mut captures = cursor_ref
+// .captures(
+// &layer.config.query,
+// layer.tree().root_node(),
+// RopeProvider(source),
+// )
+// .peekable();
+
+// // If there's no captures, skip the layer
+// captures.peek()?;
+
+// Some(HighlightIterLayer {
+// highlight_end_stack: Vec::new(),
+// scope_stack: vec![LocalScope {
+// inherits: false,
+// range: 0..usize::MAX,
+// local_defs: Vec::new(),
+// }],
+// cursor,
+// _tree: None,
+// captures: RefCell::new(captures),
+// config: layer.config.as_ref(), // TODO: just reuse `layer`
+// depth: layer.depth, // TODO: just reuse `layer`
+// })
+// })
+// .collect::<Vec<_>>();
+
+// layers.sort_unstable_by_key(|layer| layer.sort_key());
+
+// let mut result = HighlightIter {
+// source,
+// byte_offset: range.map_or(0, |r| r.start),
+// cancellation_flag,
+// iter_count: 0,
+// layers,
+// next_event: None,
+// last_highlight_range: None,
+// };
+// result.sort_layers();
+// result
+// }
+// }