luaur_analysis/records/
require_tracer.rs1use luaur_ast::records::ast_visitor::AstVisitor;
2
3use crate::records::file_resolver::FileResolver;
4use crate::records::module_info::ModuleInfo;
5use crate::records::require_trace_result::RequireTraceResult;
6use crate::type_aliases::module_name_file_resolver::ModuleName;
7
8use luaur_ast::records::ast_expr::AstExpr;
9use luaur_ast::records::ast_expr_call::AstExprCall;
10use luaur_ast::records::ast_expr_global::AstExprGlobal;
11use luaur_ast::records::ast_expr_local::AstExprLocal;
12use luaur_ast::records::ast_local::AstLocal;
13use luaur_ast::records::ast_node::AstNode;
14use luaur_ast::records::ast_stat_assign::AstStatAssign;
15use luaur_ast::records::ast_stat_local::AstStatLocal;
16
17use luaur_common::records::dense_hash_map::DenseHashMap;
18use luaur_common::records::dense_hash_table::DenseDefault;
19
20impl DenseDefault for ModuleInfo {
21 fn dense_default() -> Self {
22 Self {
23 name: alloc::string::String::new(),
24 optional: false,
25 }
26 }
27}
28
29#[derive(Debug, Clone)]
30pub struct RequireTracer {
31 pub(crate) result: *mut RequireTraceResult,
32 pub(crate) file_resolver: *mut FileResolver,
33 pub(crate) current_module_name: ModuleName,
34 pub(crate) locals: DenseHashMap<*mut AstLocal, *mut AstExpr>,
35 pub(crate) work: alloc::vec::Vec<*mut AstNode>,
36 pub(crate) require_calls: alloc::vec::Vec<*mut AstExprCall>,
37}
38
39impl AstVisitor for RequireTracer {
40 fn visit_node(&mut self, _node: *mut core::ffi::c_void) -> bool {
41 true
42 }
43
44 fn visit_expr_type_assertion(&mut self, _node: *mut core::ffi::c_void) -> bool {
45 false
46 }
47
48 fn visit_expr_call(&mut self, node: *mut core::ffi::c_void) -> bool {
49 unsafe {
50 let expr = node as *mut AstExprCall;
51 if expr.is_null() {
52 return true;
53 }
54
55 let global = (*(*expr).func).base.as_item_mut::<AstExprGlobal>();
56 if !global.is_null() {
57 let name_ptr = (*global).name.value;
58 if !name_ptr.is_null() {
59 let c_str = core::ffi::CStr::from_ptr(name_ptr).to_string_lossy();
60 if c_str == "require" && (*expr).args.size >= 1 {
61 self.require_calls.push(expr);
62 }
63 }
64 }
65 true
66 }
67 }
68
69 fn visit_stat_local(&mut self, node: *mut core::ffi::c_void) -> bool {
70 unsafe {
71 let stat = node as *mut AstStatLocal;
72 if stat.is_null() {
73 return true;
74 }
75
76 for i in 0..(*stat).vars.size.min((*stat).values.size) {
77 let local = *(*stat).vars.data.add(i);
78 let expr = *(*stat).values.data.add(i);
79 *self.locals.get_or_insert(local) = expr;
80 }
81 }
82 true
83 }
84
85 fn visit_stat_assign(&mut self, node: *mut core::ffi::c_void) -> bool {
86 unsafe {
87 let stat = node as *mut AstStatAssign;
88 if stat.is_null() {
89 return true;
90 }
91
92 for i in 0..(*stat).vars.size {
93 let v = *(*stat).vars.data.add(i);
94 let expr_local = (*v).base.as_item_mut::<AstExprLocal>();
95 if !expr_local.is_null() {
96 let local = (*expr_local).local;
97 *self.locals.get_or_insert(local) = core::ptr::null_mut();
98 }
99 }
100 }
101 true
102 }
103
104 fn visit_type(&mut self, _node: *mut core::ffi::c_void) -> bool {
105 true
106 }
107
108 fn visit_type_pack(&mut self, _node: *mut core::ffi::c_void) -> bool {
109 true
110 }
111}
112
113#[allow(dead_code, non_snake_case, unused_variables)]
118fn __contract_audit_witness() {
119 let r#local: () = ();
120 let expr: () = ();
121 let moduleContext: () = ();
122 let info: () = ();
123 let arg: () = ();
124 let infoCopy: () = ();
125}