1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::{raw, Node, Point, UntypedNode};
#[cfg(feature = "yak-sitter")]
use yak_sitter::TraversalState;
/// A stateful object for walking a syntax tree efficiently. See [`raw::TreeCursor`]
#[derive(Clone)]
#[repr(transparent)]
pub struct TreeCursor<'tree>(pub raw::TreeCursor<'tree>);
impl<'tree> TreeCursor<'tree> {
/// Transmute an immutable reference, since they have the same representation.
pub fn wrap_ref<'a>(cursor: &'a raw::TreeCursor) -> &'a Self {
// SAFETY: Same repr
unsafe { &*(cursor as *const raw::TreeCursor as *const Self) }
}
/// Transmute a mutable reference, since they have the same representation.
pub fn wrap_mut<'a>(cursor: &'a mut raw::TreeCursor) -> &'a mut Self {
// SAFETY: Same repr
unsafe { &mut *(cursor as *mut raw::TreeCursor as *mut Self) }
}
/// Gets the cursor's current node
#[inline]
pub fn node(&self) -> UntypedNode<'tree> {
UntypedNode::new(self.0.node())
}
/// Gets the field name of the cursor's current node
#[inline]
pub fn field_name(&mut self) -> Option<&'static str> {
self.0.field_name()
}
/// Re-initialize the cursor to point to the given node
#[inline]
#[cfg(feature = "yak-sitter")]
pub fn goto(&mut self, node: impl Node<'tree>) {
self.0.reset(node.into_raw())
}
/// Re-initialize the cursor to point to the given node
#[inline]
#[cfg(not(feature = "yak-sitter"))]
pub fn reset(&mut self, node: impl Node<'tree>) {
self.0.reset(node.into_raw())
}
/// Move the cursor to the first child of the current node and return `true`, or return `false`
/// if the current node has no children
#[inline]
pub fn goto_first_child(&mut self) -> bool {
self.0.goto_first_child()
}
/// Move the cursor to the first child of the current node that extends beyond the given byte
/// offset, and return its index.
///
/// Returns `None` if the current node has no children past that offset.
#[inline]
pub fn goto_first_child_for_byte(&mut self, index: usize) -> Option<usize> {
self.0.goto_first_child_for_byte(index)
}
/// Move the cursor to the first child of the current node that extends beyond the given row
/// and column, and return its index.
///
/// Returns `None` if the current node has no children past that row and column.
#[inline]
pub fn goto_first_child_for_point(&mut self, point: Point) -> Option<usize> {
self.0.goto_first_child_for_point(point)
}
/// Move the cursor to the next sibling of the current node and return `true`, or return `false`
/// if the current node has no next sibling.
///
/// Unlike [`tree_sitter::TreeCursor.goto_next_sibling`], this will try (isn't guaranteed to
/// return `false`) if the cursor is rooted (e.g. reset) to its current node.
#[cfg(feature = "yak-sitter")]
#[inline]
pub fn goto_next_sibling(&mut self) -> bool {
self.0.goto_next_sibling()
}
/// Move the cursor to the next sibling of the current node and return `true`, or return `false`
/// if the current node has no next sibling.
///
/// Also returns `false` if the cursor was initialized or re-initialized to this node, even if
/// it has a sibling.
#[cfg(not(feature = "yak-sitter"))]
#[inline]
pub fn goto_next_sibling(&mut self) -> bool {
self.0.goto_next_sibling()
}
/// Move the cursor to the parent of the current node and return `true`, or return `false`
/// if the current node is a tree root.
///
/// Unlike [`tree_sitter::TreeCursor.goto_parent`], this will try (isn't guaranteed to return
/// `false`) if the cursor is rooted (e.g. reset) to its current node.
#[cfg(feature = "yak-sitter")]
#[inline]
pub fn goto_parent(&mut self) -> bool {
self.0.goto_parent()
}
/// Move the cursor to the parent of the current node and return `true`, or return `false`
/// if the current node is a tree root.
///
/// Also returns `false` if the cursor was initialized or re-initialized to this node, even if
/// it has a parent.
#[cfg(not(feature = "yak-sitter"))]
#[inline]
pub fn goto_parent(&mut self) -> bool {
self.0.goto_parent()
}
/// Move the cursor to the next node in pre-order traversal order, where nodes with children are
/// traversed on both the up and down.
///
/// This uses `last_state` to determine where to go next (i.e. up or right/down on a node with
/// children), and returns the next state which you would pass to the next `goto_preorder` call
/// and so on.
#[cfg(feature = "yak-sitter")]
#[inline]
pub fn goto_preorder(&mut self, last_state: TraversalState) -> TraversalState {
self.0.goto_preorder(last_state)
}
}