Skip to main content

rust_code_analysis_code_split/
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    pub(crate) fn previous_sibling(&self) -> Option<Node<'a>> {
96        self.0.prev_sibling().map(Node)
97    }
98
99    pub(crate) fn next_sibling(&self) -> Option<Node<'a>> {
100        self.0.next_sibling().map(Node)
101    }
102
103    #[inline(always)]
104    pub(crate) fn is_child(&self, id: u16) -> bool {
105        self.0
106            .children(&mut self.0.walk())
107            .any(|child| child.kind_id() == id)
108    }
109
110    pub(crate) fn child_count(&self) -> usize {
111        self.0.child_count()
112    }
113
114    pub(crate) fn child_by_field_name(&self, name: &str) -> Option<Node<'_>> {
115        self.0.child_by_field_name(name).map(Node)
116    }
117
118    pub(crate) fn child(&self, pos: usize) -> Option<Node<'a>> {
119        self.0.child(pos as u32).map(Node)
120    }
121
122    pub(crate) fn children(&self) -> impl ExactSizeIterator<Item = Node<'a>> + use<'a> {
123        let mut cursor = self.cursor();
124        cursor.goto_first_child();
125        (0..self.child_count()).map(move |_| {
126            let result = cursor.node();
127            cursor.goto_next_sibling();
128            result
129        })
130    }
131
132    pub(crate) fn cursor(&self) -> Cursor<'a> {
133        Cursor(self.0.walk())
134    }
135
136    #[allow(dead_code)]
137    pub(crate) fn get_parent(&self, level: usize) -> Option<Node<'a>> {
138        let mut level = level;
139        let mut node = *self;
140        while level != 0 {
141            if let Some(parent) = node.parent() {
142                node = parent;
143            } else {
144                return None;
145            }
146            level -= 1;
147        }
148
149        Some(node)
150    }
151
152    pub(crate) fn count_specific_ancestors<T: crate::ParserTrait>(
153        &self,
154        check: fn(&Node) -> bool,
155        stop: fn(&Node) -> bool,
156    ) -> usize {
157        let mut count = 0;
158        let mut node = *self;
159        while let Some(parent) = node.parent() {
160            if stop(&parent) {
161                break;
162            }
163            if check(&parent) && !T::Checker::is_else_if(&parent) {
164                count += 1;
165            }
166            node = parent;
167        }
168        count
169    }
170
171    pub(crate) fn has_ancestors(&self, typ: fn(&Node) -> bool, typs: fn(&Node) -> bool) -> bool {
172        let mut res = false;
173        let mut node = *self;
174        if let Some(parent) = node.parent()
175            && typ(&parent)
176        {
177            node = parent;
178        }
179        if let Some(parent) = node.parent()
180            && typs(&parent)
181        {
182            res = true;
183        }
184        res
185    }
186}
187
188/// An `AST` cursor.
189#[derive(Clone)]
190pub struct Cursor<'a>(TreeCursor<'a>);
191
192impl<'a> Cursor<'a> {
193    pub(crate) fn reset(&mut self, node: &Node<'a>) {
194        self.0.reset(node.0);
195    }
196
197    pub(crate) fn goto_next_sibling(&mut self) -> bool {
198        self.0.goto_next_sibling()
199    }
200
201    pub(crate) fn goto_first_child(&mut self) -> bool {
202        self.0.goto_first_child()
203    }
204
205    pub(crate) fn node(&self) -> Node<'a> {
206        Node(self.0.node())
207    }
208}
209
210impl<'a> Search<'a> for Node<'a> {
211    fn first_occurrence(&self, pred: fn(u16) -> bool) -> Option<Node<'a>> {
212        let mut cursor = self.cursor();
213        let mut stack = Vec::new();
214        let mut children = Vec::new();
215
216        stack.push(*self);
217
218        while let Some(node) = stack.pop() {
219            if pred(node.kind_id()) {
220                return Some(node);
221            }
222            cursor.reset(&node);
223            if cursor.goto_first_child() {
224                loop {
225                    children.push(cursor.node());
226                    if !cursor.goto_next_sibling() {
227                        break;
228                    }
229                }
230                for child in children.drain(..).rev() {
231                    stack.push(child);
232                }
233            }
234        }
235
236        None
237    }
238
239    fn act_on_node(&self, action: &mut dyn FnMut(&Node<'a>)) {
240        let mut cursor = self.cursor();
241        let mut stack = Vec::new();
242        let mut children = Vec::new();
243
244        stack.push(*self);
245
246        while let Some(node) = stack.pop() {
247            action(&node);
248            cursor.reset(&node);
249            if cursor.goto_first_child() {
250                loop {
251                    children.push(cursor.node());
252                    if !cursor.goto_next_sibling() {
253                        break;
254                    }
255                }
256                for child in children.drain(..).rev() {
257                    stack.push(child);
258                }
259            }
260        }
261    }
262
263    fn first_child(&self, pred: fn(u16) -> bool) -> Option<Node<'a>> {
264        self.children().find(|&child| pred(child.kind_id()))
265    }
266
267    fn act_on_child(&self, action: &mut dyn FnMut(&Node<'a>)) {
268        for child in self.children() {
269            action(&child);
270        }
271    }
272}