Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-core/src/syntax/tree_cursor.rs')
| -rw-r--r-- | helix-core/src/syntax/tree_cursor.rs | 264 |
1 files changed, 0 insertions, 264 deletions
diff --git a/helix-core/src/syntax/tree_cursor.rs b/helix-core/src/syntax/tree_cursor.rs deleted file mode 100644 index d82ea74d..00000000 --- a/helix-core/src/syntax/tree_cursor.rs +++ /dev/null @@ -1,264 +0,0 @@ -use std::{cmp::Reverse, ops::Range}; - -use super::{LanguageLayer, LayerId}; - -use slotmap::HopSlotMap; -use tree_sitter::Node; - -/// The byte range of an injection layer. -/// -/// Injection ranges may overlap, but all overlapping parts are subsets of their parent ranges. -/// This allows us to sort the ranges ahead of time in order to efficiently find a range that -/// contains a point with maximum depth. -#[derive(Debug)] -struct InjectionRange { - start: usize, - end: usize, - layer_id: LayerId, - depth: u32, -} - -pub struct TreeCursor<'a> { - layers: &'a HopSlotMap<LayerId, LanguageLayer>, - root: LayerId, - current: LayerId, - injection_ranges: Vec<InjectionRange>, - // TODO: Ideally this would be a `tree_sitter::TreeCursor<'a>` but - // that returns very surprising results in testing. - cursor: Node<'a>, -} - -impl<'a> TreeCursor<'a> { - pub(super) fn new(layers: &'a HopSlotMap<LayerId, LanguageLayer>, root: LayerId) -> Self { - let mut injection_ranges = Vec::new(); - - for (layer_id, layer) in layers.iter() { - // Skip the root layer - if layer.parent.is_none() { - continue; - } - for byte_range in layer.ranges.iter() { - let range = InjectionRange { - start: byte_range.start_byte, - end: byte_range.end_byte, - layer_id, - depth: layer.depth, - }; - injection_ranges.push(range); - } - } - - injection_ranges.sort_unstable_by_key(|range| (range.end, Reverse(range.depth))); - - let cursor = layers[root].tree().root_node(); - - Self { - layers, - root, - current: root, - injection_ranges, - cursor, - } - } - - pub fn node(&self) -> Node<'a> { - self.cursor - } - - pub fn goto_parent(&mut self) -> bool { - if let Some(parent) = self.node().parent() { - self.cursor = parent; - return true; - } - - // If we are already on the root layer, we cannot ascend. - if self.current == self.root { - return false; - } - - // Ascend to the parent layer. - let range = self.node().byte_range(); - let parent_id = self.layers[self.current] - .parent - .expect("non-root layers have a parent"); - self.current = parent_id; - let root = self.layers[self.current].tree().root_node(); - self.cursor = root - .descendant_for_byte_range(range.start, range.end) - .unwrap_or(root); - - true - } - - pub fn goto_parent_with<P>(&mut self, predicate: P) -> bool - where - P: Fn(&Node) -> bool, - { - while self.goto_parent() { - if predicate(&self.node()) { - return true; - } - } - - false - } - - /// Finds the injection layer that has exactly the same range as the given `range`. - fn layer_id_of_byte_range(&self, search_range: Range<usize>) -> Option<LayerId> { - let start_idx = self - .injection_ranges - .partition_point(|range| range.end < search_range.end); - - self.injection_ranges[start_idx..] - .iter() - .take_while(|range| range.end == search_range.end) - .find_map(|range| (range.start == search_range.start).then_some(range.layer_id)) - } - - fn goto_first_child_impl(&mut self, named: bool) -> bool { - // Check if the current node's range is an exact injection layer range. - if let Some(layer_id) = self - .layer_id_of_byte_range(self.node().byte_range()) - .filter(|&layer_id| layer_id != self.current) - { - // Switch to the child layer. - self.current = layer_id; - self.cursor = self.layers[self.current].tree().root_node(); - return true; - } - - let child = if named { - self.cursor.named_child(0) - } else { - self.cursor.child(0) - }; - - if let Some(child) = child { - // Otherwise descend in the current tree. - self.cursor = child; - true - } else { - false - } - } - - pub fn goto_first_child(&mut self) -> bool { - self.goto_first_child_impl(false) - } - - pub fn goto_first_named_child(&mut self) -> bool { - self.goto_first_child_impl(true) - } - - fn goto_next_sibling_impl(&mut self, named: bool) -> bool { - let sibling = if named { - self.cursor.next_named_sibling() - } else { - self.cursor.next_sibling() - }; - - if let Some(sibling) = sibling { - self.cursor = sibling; - true - } else { - false - } - } - - pub fn goto_next_sibling(&mut self) -> bool { - self.goto_next_sibling_impl(false) - } - - pub fn goto_next_named_sibling(&mut self) -> bool { - self.goto_next_sibling_impl(true) - } - - fn goto_prev_sibling_impl(&mut self, named: bool) -> bool { - let sibling = if named { - self.cursor.prev_named_sibling() - } else { - self.cursor.prev_sibling() - }; - - if let Some(sibling) = sibling { - self.cursor = sibling; - true - } else { - false - } - } - - pub fn goto_prev_sibling(&mut self) -> bool { - self.goto_prev_sibling_impl(false) - } - - pub fn goto_prev_named_sibling(&mut self) -> bool { - self.goto_prev_sibling_impl(true) - } - - /// Finds the injection layer that contains the given start-end range. - fn layer_id_containing_byte_range(&self, start: usize, end: usize) -> LayerId { - let start_idx = self - .injection_ranges - .partition_point(|range| range.end < end); - - self.injection_ranges[start_idx..] - .iter() - .take_while(|range| range.start < end || range.depth > 1) - .find_map(|range| (range.start <= start).then_some(range.layer_id)) - .unwrap_or(self.root) - } - - pub fn reset_to_byte_range(&mut self, start: usize, end: usize) { - self.current = self.layer_id_containing_byte_range(start, end); - let root = self.layers[self.current].tree().root_node(); - self.cursor = root.descendant_for_byte_range(start, end).unwrap_or(root); - } - - /// Returns an iterator over the children of the node the TreeCursor is on - /// at the time this is called. - pub fn children(&'a mut self) -> ChildIter<'a> { - let parent = self.node(); - - ChildIter { - cursor: self, - parent, - named: false, - } - } - - /// Returns an iterator over the named children of the node the TreeCursor is on - /// at the time this is called. - pub fn named_children(&'a mut self) -> ChildIter<'a> { - let parent = self.node(); - - ChildIter { - cursor: self, - parent, - named: true, - } - } -} - -pub struct ChildIter<'n> { - cursor: &'n mut TreeCursor<'n>, - parent: Node<'n>, - named: bool, -} - -impl<'n> Iterator for ChildIter<'n> { - type Item = Node<'n>; - - fn next(&mut self) -> Option<Self::Item> { - // first iteration, just visit the first child - if self.cursor.node() == self.parent { - self.cursor - .goto_first_child_impl(self.named) - .then(|| self.cursor.node()) - } else { - self.cursor - .goto_next_sibling_impl(self.named) - .then(|| self.cursor.node()) - } - } -} |