Skip to main content

luaur_analysis/methods/
require_tracer_process.rs

1use crate::records::file_resolver::FileResolver;
2use crate::records::module_info::ModuleInfo;
3use crate::records::require_tracer::RequireTracer;
4use crate::records::type_check_limits::TypeCheckLimits;
5use luaur_ast::records::ast_expr::AstExpr;
6use luaur_ast::records::ast_expr_call::AstExprCall;
7use luaur_ast::records::ast_expr_group::AstExprGroup;
8use luaur_ast::records::ast_expr_local::AstExprLocal;
9use luaur_ast::records::ast_expr_type_assertion::AstExprTypeAssertion;
10use luaur_ast::records::ast_node::AstNode;
11use luaur_ast::records::ast_type_group::AstTypeGroup;
12use luaur_ast::records::ast_type_typeof::AstTypeTypeof;
13
14impl RequireTracer {
15    pub fn process(&mut self, limits: &TypeCheckLimits) {
16        let module_context = ModuleInfo {
17            name: self.current_module_name.clone(),
18            optional: false,
19        };
20
21        self.work.reserve(self.require_calls.len());
22        for &require in &self.require_calls {
23            unsafe {
24                if (*require).args.size > 0 {
25                    self.work.push(*(*require).args.data.add(0) as *mut AstNode);
26                }
27            }
28        }
29
30        let mut i = 0;
31        while i < self.work.len() {
32            let node = self.work[i];
33            if !node.is_null() {
34                let dep = unsafe { self.get_dependent(node) };
35                if !dep.is_null() {
36                    self.work.push(dep);
37                }
38            }
39            i += 1;
40        }
41
42        unsafe {
43            let mut i = self.work.len();
44            while i > 0 {
45                let expr = self.work[i - 1];
46                i -= 1;
47
48                if (*self.result).exprs.find(&expr).is_some() {
49                    continue;
50                }
51
52                let mut info: Option<ModuleInfo> = None;
53                let dep = self.get_dependent(expr);
54
55                if !dep.is_null() {
56                    let context = (*self.result).exprs.find(&dep);
57                    if let Some(context) = context {
58                        if (*expr).is::<AstExprLocal>()
59                            || (*expr).is::<AstExprGroup>()
60                            || (*expr).is::<AstTypeGroup>()
61                            || (*expr).is::<AstTypeTypeof>()
62                            || (*expr).is::<AstExprTypeAssertion>()
63                        {
64                            info = Some(context.clone());
65                        } else if let Some(as_expr) = (*expr).as_expr().as_mut() {
66                            info = FileResolver::resolve_module(
67                                self.file_resolver,
68                                context,
69                                as_expr,
70                                limits,
71                            );
72                        }
73                    }
74                } else if let Some(as_expr) = (*expr).as_expr().as_mut() {
75                    info = FileResolver::resolve_module(
76                        self.file_resolver,
77                        &module_context,
78                        as_expr,
79                        limits,
80                    );
81                }
82
83                if let Some(info) = info {
84                    (*self.result).exprs.try_insert(expr, info);
85                }
86            }
87
88            (*self.result)
89                .require_list
90                .reserve(self.require_calls.len());
91            for &require in &self.require_calls {
92                let arg = *(*require).args.data.add(0) as *mut AstNode;
93                if let Some(info) = (*self.result).exprs.find(&arg) {
94                    (*self.result)
95                        .require_list
96                        .push((info.name.clone(), (*require).base.base.location));
97                    let info_copy = info.clone();
98                    (*self.result)
99                        .exprs
100                        .try_insert(require as *mut AstNode, info_copy);
101                } else {
102                    (*self.result)
103                        .exprs
104                        .try_insert(require as *mut AstNode, ModuleInfo::default());
105                }
106            }
107        }
108    }
109}