Skip to main content

luaur_analysis/functions/
is_valid_break_continue_context.rs

1use luaur_ast::records::ast_expr_function::AstExprFunction;
2use luaur_ast::records::ast_node::AstNode;
3use luaur_ast::records::ast_stat_for::AstStatFor;
4use luaur_ast::records::ast_stat_for_in::AstStatForIn;
5use luaur_ast::records::ast_stat_function::AstStatFunction;
6use luaur_ast::records::ast_stat_local_function::AstStatLocalFunction;
7use luaur_ast::records::ast_stat_repeat::AstStatRepeat;
8use luaur_ast::records::ast_stat_type_function::AstStatTypeFunction;
9use luaur_ast::records::ast_stat_while::AstStatWhile;
10use luaur_ast::records::ast_type_function::AstTypeFunction;
11use luaur_ast::records::position::Position;
12use luaur_ast::rtti::ast_node_is;
13
14pub fn is_valid_break_continue_context(
15    ancestry: &alloc::vec::Vec<*mut AstNode>,
16    position: Position,
17) -> bool {
18    let mut iter = ancestry.len();
19    while iter > 0 {
20        iter -= 1;
21        let node = ancestry[iter];
22
23        if unsafe { ast_node_is::<AstStatFunction>(&*(node as *mut AstNode)) }
24            || unsafe { ast_node_is::<AstStatLocalFunction>(&*(node as *mut AstNode)) }
25            || unsafe { ast_node_is::<AstExprFunction>(&*(node as *mut AstNode)) }
26            || unsafe { ast_node_is::<AstStatTypeFunction>(&*(node as *mut AstNode)) }
27            || unsafe { ast_node_is::<AstTypeFunction>(&*(node as *mut AstNode)) }
28        {
29            return false;
30        }
31
32        if let Some(stat_while) = unsafe {
33            ast_node_is::<AstStatWhile>(&*(node as *mut AstNode)).then(|| node as *mut AstStatWhile)
34        } {
35            let body_location = unsafe { (*(*stat_while).body).base.base.location };
36            if body_location.contains(position) {
37                return true;
38            }
39        }
40
41        if let Some(stat_for) = unsafe {
42            ast_node_is::<AstStatFor>(&*(node as *mut AstNode)).then(|| node as *mut AstStatFor)
43        } {
44            let body_location = unsafe { (*(*stat_for).body).base.base.location };
45            if body_location.contains(position) {
46                return true;
47            }
48        }
49
50        if let Some(stat_for_in) = unsafe {
51            ast_node_is::<AstStatForIn>(&*(node as *mut AstNode)).then(|| node as *mut AstStatForIn)
52        } {
53            let body_location = unsafe { (*(*stat_for_in).body).base.base.location };
54            if body_location.contains(position) {
55                return true;
56            }
57        }
58
59        if let Some(stat_repeat) = unsafe {
60            ast_node_is::<AstStatRepeat>(&*(node as *mut AstNode))
61                .then(|| node as *mut AstStatRepeat)
62        } {
63            let body_location = unsafe { (*(*stat_repeat).body).base.base.location };
64            if body_location.contains(position) {
65                return true;
66            }
67        }
68    }
69
70    false
71}