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}