Skip to main content

luaur_analysis/methods/
autocomplete_node_finder_visit_ast_query_alt_f.rs

1use crate::records::autocomplete_node_finder::AutocompleteNodeFinder;
2use luaur_ast::records::ast_expr_function::AstExprFunction;
3use luaur_ast::records::ast_expr_index_name::AstExprIndexName;
4use luaur_ast::records::ast_node::AstNode;
5use luaur_ast::records::ast_stat_block::AstStatBlock;
6use luaur_ast::records::ast_type_error::AstTypeError;
7
8impl AutocompleteNodeFinder {
9    pub fn visit_ast_stat_block(&mut self, block: *mut AstStatBlock) -> bool {
10        // If ancestry is empty, we are inspecting the root of the AST.  Its extent is considered to be infinite.
11        if self.ancestry.is_empty() {
12            self.ancestry.push(block as *mut AstNode);
13            return true;
14        }
15
16        unsafe {
17            let last = *self.ancestry.last().unwrap();
18
19            // AstExprIndexName nodes are nested outside-in, so we want the outermost node in the case of nested nodes.
20            // ex foo.bar.baz is represented in the AST as IndexName{ IndexName {foo, bar}, baz}
21            if (*last).is::<AstExprIndexName>() {
22                return false;
23            }
24
25            // Type annotation error might intersect the block statement when the function header is being written,
26            // annotation takes priority
27            if (*last).is::<AstTypeError>() {
28                return false;
29            }
30
31            let location = (*block).base.base.location;
32
33            // If the cursor is at the end of an expression or type and simultaneously at the beginning of a block,
34            // the expression or type wins out.
35            // The exception to this is if we are in a block under an AstExprFunction.  In this case, we consider the position to
36            // be within the block.
37            if location.begin == self.pos {
38                if !(*last).as_expr_const().is_null() && !(*last).is::<AstExprFunction>() {
39                    return false;
40                }
41
42                if !(*last).as_type().is_null() {
43                    return false;
44                }
45            }
46
47            if location.begin <= self.pos && self.pos <= location.end {
48                self.ancestry.push(block as *mut AstNode);
49                return true;
50            }
51        }
52        false
53    }
54}