Skip to main content

luaur_analysis/records/
find_node.rs

1use luaur_ast::records::ast_expr::AstExpr;
2use luaur_ast::records::ast_node::AstNode;
3use luaur_ast::records::ast_stat_block::AstStatBlock;
4use luaur_ast::records::ast_stat_function::AstStatFunction;
5use luaur_ast::records::ast_visitor::AstVisitor;
6use luaur_ast::records::position::Position;
7use luaur_ast::visit;
8
9#[derive(Debug, Clone)]
10pub struct FindNode {
11    pub(crate) pos: Position,
12    pub(crate) document_end: Position,
13    pub(crate) best: *mut AstNode,
14}
15
16impl FindNode {
17    pub fn new(pos: Position, document_end: Position) -> Self {
18        Self {
19            pos,
20            document_end,
21            best: core::ptr::null_mut(),
22        }
23    }
24}
25
26impl AstVisitor for FindNode {
27    fn visit_node(&mut self, node: *mut core::ffi::c_void) -> bool {
28        let node = node as *mut AstNode;
29        unsafe {
30            if (*node).location.contains(self.pos) {
31                self.best = node;
32                return true;
33            }
34
35            if (*node).location.end == self.document_end && self.pos >= self.document_end {
36                self.best = node;
37                return true;
38            }
39        }
40        false
41    }
42
43    fn visit_stat_function(&mut self, node: *mut core::ffi::c_void) -> bool {
44        self.visit_node(node);
45        let node = node as *mut AstStatFunction;
46        unsafe {
47            let name_node = (*node).name as *mut AstNode;
48            let func_node = (*node).func as *mut AstNode;
49            if (*name_node).location.contains(self.pos) {
50                visit::ast_expr_visit((*node).name as *mut AstExpr, self);
51            } else if (*func_node).location.contains(self.pos) {
52                visit::ast_expr_visit((*node).func as *mut AstExpr, self);
53            }
54        }
55        false
56    }
57
58    fn visit_stat_block(&mut self, node: *mut core::ffi::c_void) -> bool {
59        self.visit_node(node);
60        let block = node as *mut AstStatBlock;
61        unsafe {
62            for stat in (*block).body.iter() {
63                let stat = *stat;
64                let stat_node = stat as *mut AstNode;
65                if (*stat_node).location.end < self.pos {
66                    continue;
67                }
68                if (*stat_node).location.begin > self.pos {
69                    break;
70                }
71                visit::ast_stat_visit(stat, self);
72            }
73        }
74        false
75    }
76}