Skip to main content

codelore_rca/
node.rs

1use tree_sitter::Node as OtherNode;
2use tree_sitter::Tree as OtherTree;
3use tree_sitter::{Parser, TreeCursor};
4
5use crate::checker::Checker;
6use crate::traits::{LanguageInfo, Search};
7
8#[derive(Clone, Debug)]
9pub(crate) struct Tree(OtherTree);
10
11impl Tree {
12    pub(crate) fn new<T: LanguageInfo>(code: &[u8]) -> Self {
13        let mut parser = Parser::new();
14        parser
15            .set_language(&T::get_lang().get_ts_language())
16            .unwrap();
17
18        Self(parser.parse(code, None).unwrap())
19    }
20
21    pub(crate) fn get_root(&self) -> Node<'_> {
22        Node(self.0.root_node())
23    }
24}
25
26/// An `AST` node.
27///
28/// The inner `tree_sitter::Node` is exposed for advanced use cases
29/// where direct access to the underlying tree-sitter API is needed.
30#[derive(Clone, Copy, Debug)]
31pub struct Node<'a>(pub OtherNode<'a>);
32
33impl<'a> Node<'a> {
34    /// Checks if a node represents a syntax error or contains any syntax errors
35    /// anywhere within it.
36    pub fn has_error(&self) -> bool {
37        self.0.has_error()
38    }
39
40    pub(crate) fn id(&self) -> usize {
41        self.0.id()
42    }
43
44    pub(crate) fn kind(&self) -> &'static str {
45        self.0.kind()
46    }
47
48    pub(crate) fn kind_id(&self) -> u16 {
49        self.0.kind_id()
50    }
51
52    pub(crate) fn utf8_text(&self, data: &'a [u8]) -> Option<&'a str> {
53        self.0.utf8_text(data).ok()
54    }
55
56    pub(crate) fn start_byte(&self) -> usize {
57        self.0.start_byte()
58    }
59
60    pub(crate) fn end_byte(&self) -> usize {
61        self.0.end_byte()
62    }
63
64    pub(crate) fn start_position(&self) -> (usize, usize) {
65        let temp = self.0.start_position();
66        (temp.row, temp.column)
67    }
68
69    pub(crate) fn end_position(&self) -> (usize, usize) {
70        let temp = self.0.end_position();
71        (temp.row, temp.column)
72    }
73
74    pub(crate) fn start_row(&self) -> usize {
75        self.0.start_position().row
76    }
77
78    pub(crate) fn end_row(&self) -> usize {
79        self.0.end_position().row
80    }
81
82    pub(crate) fn parent(&self) -> Option<Node<'a>> {
83        self.0.parent().map(Node)
84    }
85
86    #[inline(always)]
87    pub(crate) fn has_sibling(&self, id: u16) -> bool {
88        self.0.parent().is_some_and(|parent| {
89            self.0
90                .children(&mut parent.walk())
91                .any(|child| child.kind_id() == id)
92        })
93    }
94
95    #[allow(dead_code)]
96    pub(crate) fn previous_sibling(&self) -> Option<Node<'a>> {
97        self.0.prev_sibling().map(Node)
98    }
99
100    pub(crate) fn next_sibling(&self) -> Option<Node<'a>> {
101        self.0.next_sibling().map(Node)
102    }
103
104    #[inline(always)]
105    pub(crate) fn is_child(&self, id: u16) -> bool {
106        self.0
107            .children(&mut self.0.walk())
108            .any(|child| child.kind_id() == id)
109    }
110
111    pub(crate) fn child_count(&self) -> usize {
112        self.0.child_count()
113    }
114
115    pub(crate) fn child_by_field_name(&self, name: &str) -> Option<Node<'_>> {
116        self.0.child_by_field_name(name).map(Node)
117    }
118
119    pub(crate) fn child(&self, pos: usize) -> Option<Node<'a>> {
120        self.0.child(pos).map(Node)
121    }
122
123    pub(crate) fn children(&self) -> impl ExactSizeIterator<Item = Node<'a>> + use<'a> {
124        let mut cursor = self.cursor();
125        cursor.goto_first_child();
126        (0..self.child_count()).map(move |_| {
127            let result = cursor.node();
128            cursor.goto_next_sibling();
129            result
130        })
131    }
132
133    pub(crate) fn cursor(&self) -> Cursor<'a> {
134        Cursor(self.0.walk())
135    }
136
137    #[allow(dead_code)]
138    pub(crate) fn get_parent(&self, level: usize) -> Option<Node<'a>> {
139        let mut level = level;
140        let mut node = *self;
141        while level != 0 {
142            node = node.parent()?;
143            level -= 1;
144        }
145
146        Some(node)
147    }
148
149    pub(crate) fn count_specific_ancestors<T: crate::ParserTrait>(
150        &self,
151        check: fn(&Node) -> bool,
152        stop: fn(&Node) -> bool,
153    ) -> usize {
154        let mut count = 0;
155        let mut node = *self;
156        while let Some(parent) = node.parent() {
157            if stop(&parent) {
158                break;
159            }
160            if check(&parent) && !T::Checker::is_else_if(&parent) {
161                count += 1;
162            }
163            node = parent;
164        }
165        count
166    }
167
168    pub(crate) fn has_ancestors(&self, typ: fn(&Node) -> bool, typs: fn(&Node) -> bool) -> bool {
169        let mut res = false;
170        let mut node = *self;
171        if let Some(parent) = node.parent()
172            && typ(&parent)
173        {
174            node = parent;
175        }
176        if let Some(parent) = node.parent()
177            && typs(&parent)
178        {
179            res = true;
180        }
181        res
182    }
183}
184
185/// An `AST` cursor.
186#[derive(Clone)]
187pub struct Cursor<'a>(TreeCursor<'a>);
188
189impl<'a> Cursor<'a> {
190    pub(crate) fn reset(&mut self, node: &Node<'a>) {
191        self.0.reset(node.0);
192    }
193
194    pub(crate) fn goto_next_sibling(&mut self) -> bool {
195        self.0.goto_next_sibling()
196    }
197
198    pub(crate) fn goto_first_child(&mut self) -> bool {
199        self.0.goto_first_child()
200    }
201
202    pub(crate) fn node(&self) -> Node<'a> {
203        Node(self.0.node())
204    }
205}
206
207impl<'a> Search<'a> for Node<'a> {
208    fn first_occurrence(&self, pred: fn(u16) -> bool) -> Option<Node<'a>> {
209        let mut cursor = self.cursor();
210        let mut stack = Vec::new();
211        let mut children = Vec::new();
212
213        stack.push(*self);
214
215        while let Some(node) = stack.pop() {
216            if pred(node.kind_id()) {
217                return Some(node);
218            }
219            cursor.reset(&node);
220            if cursor.goto_first_child() {
221                loop {
222                    children.push(cursor.node());
223                    if !cursor.goto_next_sibling() {
224                        break;
225                    }
226                }
227                for child in children.drain(..).rev() {
228                    stack.push(child);
229                }
230            }
231        }
232
233        None
234    }
235
236    fn act_on_node(&self, action: &mut dyn FnMut(&Node<'a>)) {
237        let mut cursor = self.cursor();
238        let mut stack = Vec::new();
239        let mut children = Vec::new();
240
241        stack.push(*self);
242
243        while let Some(node) = stack.pop() {
244            action(&node);
245            cursor.reset(&node);
246            if cursor.goto_first_child() {
247                loop {
248                    children.push(cursor.node());
249                    if !cursor.goto_next_sibling() {
250                        break;
251                    }
252                }
253                for child in children.drain(..).rev() {
254                    stack.push(child);
255                }
256            }
257        }
258    }
259
260    fn first_child(&self, pred: fn(u16) -> bool) -> Option<Node<'a>> {
261        self.children().find(|&child| pred(child.kind_id()))
262    }
263
264    fn act_on_child(&self, action: &mut dyn FnMut(&Node<'a>)) {
265        for child in self.children() {
266            action(&child);
267        }
268    }
269}