mirror of
https://github.com/helix-editor/tree-house.git
synced 2025-10-06 00:12:46 +02:00
add recursive walker (#16)
This commit is contained in:
@@ -95,6 +95,14 @@ impl<'tree> Node<'tree> {
|
||||
unsafe { ts_node_is_named(self.as_raw()) }
|
||||
}
|
||||
|
||||
/// Returns true if and only if this node is contained "inside" the given
|
||||
/// input range, i.e. either start_new > start_old and end_new <= end_old OR
|
||||
/// start_new >= start_old and end_new < end_old
|
||||
pub fn is_contained_within(&self, range: Range<u32>) -> bool {
|
||||
(self.start_byte() > range.start && self.end_byte() <= range.end)
|
||||
|| (self.start_byte() >= range.start && self.end_byte() < range.end)
|
||||
}
|
||||
|
||||
/// Check if this node is *missing*.
|
||||
///
|
||||
/// Missing nodes are inserted by the parser in order to recover from
|
||||
|
@@ -1,5 +1,6 @@
|
||||
use ::std::os::raw;
|
||||
use std::cell::Cell;
|
||||
use std::collections::VecDeque;
|
||||
use std::ffi::{c_char, CStr};
|
||||
use std::marker::PhantomData;
|
||||
use std::{fmt, mem};
|
||||
@@ -76,6 +77,10 @@ impl<'tree> TreeCursor<'tree> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self, node: &Node<'tree>) {
|
||||
unsafe { ts_tree_cursor_reset(&mut self.inner, node.as_raw()) }
|
||||
}
|
||||
|
||||
pub fn node(&self) -> Node<'tree> {
|
||||
unsafe { Node::from_raw(ts_tree_cursor_current_node(&self.inner)).unwrap_unchecked() }
|
||||
}
|
||||
@@ -109,6 +114,54 @@ impl Clone for TreeCursor<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tree> IntoIterator for &'tree mut TreeCursor<'tree> {
|
||||
type Item = Node<'tree>;
|
||||
type IntoIter = TreeRecursiveWalker<'tree>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
let mut queue = VecDeque::new();
|
||||
let root = self.node();
|
||||
queue.push_back(root.clone());
|
||||
|
||||
TreeRecursiveWalker {
|
||||
cursor: self,
|
||||
queue,
|
||||
root,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TreeRecursiveWalker<'tree> {
|
||||
cursor: &'tree mut TreeCursor<'tree>,
|
||||
queue: VecDeque<Node<'tree>>,
|
||||
root: Node<'tree>,
|
||||
}
|
||||
|
||||
impl<'tree> Iterator for TreeRecursiveWalker<'tree> {
|
||||
type Item = Node<'tree>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let current = self.cursor.node();
|
||||
|
||||
if current != self.root && self.cursor.goto_next_sibling() {
|
||||
self.queue.push_back(current);
|
||||
return Some(self.cursor.node());
|
||||
}
|
||||
|
||||
while let Some(queued) = self.queue.pop_front() {
|
||||
self.cursor.reset(&queued);
|
||||
|
||||
if !self.cursor.goto_first_child() {
|
||||
continue;
|
||||
}
|
||||
|
||||
return Some(self.cursor.node());
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
/// Create a new tree cursor starting from the given node.
|
||||
///
|
||||
|
@@ -1,3 +1,5 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use crate::tree_sitter::Node;
|
||||
use crate::{Layer, Syntax};
|
||||
|
||||
@@ -129,3 +131,51 @@ impl<'tree> Iterator for ChildIter<'_, 'tree> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cursor, 'tree> IntoIterator for &'cursor mut TreeCursor<'tree> {
|
||||
type Item = Node<'tree>;
|
||||
type IntoIter = TreeRecursiveWalker<'cursor, 'tree>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
let mut queue = VecDeque::new();
|
||||
let root = self.node();
|
||||
queue.push_back(root.clone());
|
||||
|
||||
TreeRecursiveWalker {
|
||||
cursor: self,
|
||||
queue,
|
||||
root,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TreeRecursiveWalker<'cursor, 'tree> {
|
||||
cursor: &'cursor mut TreeCursor<'tree>,
|
||||
queue: VecDeque<Node<'tree>>,
|
||||
root: Node<'tree>,
|
||||
}
|
||||
|
||||
impl<'tree> Iterator for TreeRecursiveWalker<'_, 'tree> {
|
||||
type Item = Node<'tree>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let current = self.cursor.node();
|
||||
|
||||
if current != self.root && self.cursor.goto_next_sibling() {
|
||||
self.queue.push_back(current);
|
||||
return Some(self.cursor.node());
|
||||
}
|
||||
|
||||
while let Some(queued) = self.queue.pop_front() {
|
||||
self.cursor.cursor.reset(&queued);
|
||||
|
||||
if !self.cursor.goto_first_child() {
|
||||
continue;
|
||||
}
|
||||
|
||||
return Some(self.cursor.node());
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user