@@ -37,49 +37,60 @@ impl<'a> Node<'a> {
3737 self . 0 . has_error ( )
3838 }
3939
40- pub ( crate ) fn id ( & self ) -> usize {
40+ /// Returns a numeric id for this node that is unique within its tree.
41+ pub fn id ( & self ) -> usize {
4142 self . 0 . id ( )
4243 }
4344
44- pub ( crate ) fn kind ( & self ) -> & ' static str {
45+ /// Returns the node's type as a string.
46+ pub fn kind ( & self ) -> & ' static str {
4547 self . 0 . kind ( )
4648 }
4749
48- pub ( crate ) fn kind_id ( & self ) -> u16 {
50+ /// Returns the node's type as a numeric id.
51+ pub fn kind_id ( & self ) -> u16 {
4952 self . 0 . kind_id ( )
5053 }
5154
52- pub ( crate ) fn utf8_text ( & self , data : & ' a [ u8 ] ) -> Option < & ' a str > {
55+ /// Returns the node's text as a UTF-8 string, if valid.
56+ pub fn utf8_text ( & self , data : & ' a [ u8 ] ) -> Option < & ' a str > {
5357 self . 0 . utf8_text ( data) . ok ( )
5458 }
5559
56- pub ( crate ) fn start_byte ( & self ) -> usize {
60+ /// Returns the byte offset where this node starts.
61+ pub fn start_byte ( & self ) -> usize {
5762 self . 0 . start_byte ( )
5863 }
5964
60- pub ( crate ) fn end_byte ( & self ) -> usize {
65+ /// Returns the byte offset where this node ends.
66+ pub fn end_byte ( & self ) -> usize {
6167 self . 0 . end_byte ( )
6268 }
6369
64- pub ( crate ) fn start_position ( & self ) -> ( usize , usize ) {
70+ /// Returns the (row, column) position where this node starts.
71+ pub fn start_position ( & self ) -> ( usize , usize ) {
6572 let temp = self . 0 . start_position ( ) ;
6673 ( temp. row , temp. column )
6774 }
6875
69- pub ( crate ) fn end_position ( & self ) -> ( usize , usize ) {
76+ /// Returns the (row, column) position where this node ends.
77+ pub fn end_position ( & self ) -> ( usize , usize ) {
7078 let temp = self . 0 . end_position ( ) ;
7179 ( temp. row , temp. column )
7280 }
7381
74- pub ( crate ) fn start_row ( & self ) -> usize {
82+ /// Returns the row number where this node starts.
83+ pub fn start_row ( & self ) -> usize {
7584 self . 0 . start_position ( ) . row
7685 }
7786
78- pub ( crate ) fn end_row ( & self ) -> usize {
87+ /// Returns the row number where this node ends.
88+ pub fn end_row ( & self ) -> usize {
7989 self . 0 . end_position ( ) . row
8090 }
8191
82- pub ( crate ) fn parent ( & self ) -> Option < Node < ' a > > {
92+ /// Returns this node's parent, if any.
93+ pub fn parent ( & self ) -> Option < Node < ' a > > {
8394 self . 0 . parent ( ) . map ( Node )
8495 }
8596
@@ -183,6 +194,21 @@ impl<'a> Node<'a> {
183194 }
184195 res
185196 }
197+
198+ /// Checks if this node has any ancestor that meets the given predicate.
199+ ///
200+ /// Traverses up the tree from this node's parent to the root,
201+ /// returning true if any ancestor satisfies the predicate.
202+ pub fn has_ancestor < F : Fn ( & Node ) -> bool > ( & self , pred : F ) -> bool {
203+ let mut node = * self ;
204+ while let Some ( parent) = node. parent ( ) {
205+ if pred ( & parent) {
206+ return true ;
207+ }
208+ node = parent;
209+ }
210+ false
211+ }
186212}
187213
188214/// An `AST` cursor.
@@ -236,6 +262,35 @@ impl<'a> Search<'a> for Node<'a> {
236262 None
237263 }
238264
265+ fn all_occurrences ( & self , pred : fn ( u16 ) -> bool ) -> Vec < Node < ' a > > {
266+ let mut cursor = self . cursor ( ) ;
267+ let mut stack = Vec :: new ( ) ;
268+ let mut children = Vec :: new ( ) ;
269+ let mut results = Vec :: new ( ) ;
270+
271+ stack. push ( * self ) ;
272+
273+ while let Some ( node) = stack. pop ( ) {
274+ if pred ( node. kind_id ( ) ) {
275+ results. push ( node) ;
276+ }
277+ cursor. reset ( & node) ;
278+ if cursor. goto_first_child ( ) {
279+ loop {
280+ children. push ( cursor. node ( ) ) ;
281+ if !cursor. goto_next_sibling ( ) {
282+ break ;
283+ }
284+ }
285+ for child in children. drain ( ..) . rev ( ) {
286+ stack. push ( child) ;
287+ }
288+ }
289+ }
290+
291+ results
292+ }
293+
239294 fn act_on_node ( & self , action : & mut dyn FnMut ( & Node < ' a > ) ) {
240295 let mut cursor = self . cursor ( ) ;
241296 let mut stack = Vec :: new ( ) ;
0 commit comments