Skip to main content

luaur_analysis/records/
nearest_statement_finder.rs

1use luaur_ast::records::ast_stat::AstStat;
2use luaur_ast::records::ast_stat_block::AstStatBlock;
3use luaur_ast::records::ast_visitor::AstVisitor;
4use luaur_ast::records::location::Location;
5use luaur_ast::records::position::Position;
6
7#[derive(Debug, Clone)]
8pub struct NearestStatementFinder {
9    pub(crate) cursor: Position,
10    pub(crate) nearest: *mut AstStat,
11    pub(crate) parent: *mut AstStatBlock,
12}
13
14impl NearestStatementFinder {
15    pub fn new(cursor_position: Position) -> Self {
16        Self {
17            cursor: cursor_position,
18            nearest: core::ptr::null_mut(),
19            parent: core::ptr::null_mut(),
20        }
21    }
22}
23
24impl NearestStatementFinder {
25    pub fn nearest_statement_finder(cursor_position: &Position) -> Self {
26        Self::new(*cursor_position)
27    }
28}
29
30impl AstVisitor for NearestStatementFinder {
31    fn visit_stat_block(&mut self, node: *mut core::ffi::c_void) -> bool {
32        let block = node as *mut AstStatBlock;
33        unsafe {
34            let block_location = (*block).base.base.location;
35            if block_location.contains(self.cursor) || block_location.end == self.cursor {
36                self.parent = block;
37
38                // Find last statement whose begin <= cursor.
39                for v in (*block).body.iter() {
40                    let v = *v;
41                    let stmt_location = unsafe { (*v).base.location };
42                    if stmt_location.begin <= self.cursor {
43                        self.nearest = v;
44                    }
45                }
46
47                true
48            } else {
49                false
50            }
51        }
52    }
53}