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.rs438
1 files changed, 438 insertions, 0 deletions
diff --git a/helix-syntax/src/highlighter.rs b/helix-syntax/src/highlighter.rs
new file mode 100644
index 00000000..8801b13f
--- /dev/null
+++ b/helix-syntax/src/highlighter.rs
@@ -0,0 +1,438 @@
+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
+// }
+// }