luaur_analysis/records/
find_node.rs1use 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}