luaur_analysis/functions/
try_get_l_value.rs1use crate::records::field::Field;
2use crate::records::symbol::Symbol;
3use crate::type_aliases::l_value::LValue;
4use alloc::sync::Arc;
5use luaur_ast::records::ast_expr::AstExpr;
6use luaur_ast::records::ast_expr_constant_string::AstExprConstantString;
7use luaur_ast::records::ast_expr_global::AstExprGlobal;
8use luaur_ast::records::ast_expr_group::AstExprGroup;
9use luaur_ast::records::ast_expr_index_expr::AstExprIndexExpr;
10use luaur_ast::records::ast_expr_index_name::AstExprIndexName;
11use luaur_ast::records::ast_expr_local::AstExprLocal;
12use luaur_ast::rtti::ast_node_as;
13
14pub fn try_get_l_value(node: &AstExpr) -> Option<LValue> {
15 let mut expr = node as *const AstExpr;
16
17 unsafe {
18 loop {
19 let group =
20 ast_node_as::<AstExprGroup>(expr as *mut luaur_ast::records::ast_node::AstNode);
21 if !group.is_null() {
22 expr = (*group).expr;
23 continue;
24 }
25 break;
26 }
27
28 let local = ast_node_as::<AstExprLocal>(expr as *mut luaur_ast::records::ast_node::AstNode);
29 if !local.is_null() {
30 return Some(LValue::Symbol(Symbol::symbol_ast_local((*local).local)));
31 }
32
33 let global =
34 ast_node_as::<AstExprGlobal>(expr as *mut luaur_ast::records::ast_node::AstNode);
35 if !global.is_null() {
36 return Some(LValue::Symbol(Symbol::symbol_ast_name((*global).name)));
37 }
38
39 let indexname =
40 ast_node_as::<AstExprIndexName>(expr as *mut luaur_ast::records::ast_node::AstNode);
41 if !indexname.is_null() {
42 if let Some(lvalue) = try_get_l_value(&*(*indexname).expr) {
43 let key = if (*indexname).index.value.is_null() {
44 alloc::string::String::new()
45 } else {
46 core::ffi::CStr::from_ptr((*indexname).index.value)
47 .to_string_lossy()
48 .into_owned()
49 };
50 return Some(LValue::Field(Field {
51 parent: Some(Arc::new(lvalue)),
52 key,
53 }));
54 }
55 }
56
57 let indexexpr =
58 ast_node_as::<AstExprIndexExpr>(expr as *mut luaur_ast::records::ast_node::AstNode);
59 if !indexexpr.is_null() {
60 if let Some(lvalue) = try_get_l_value(&*(*indexexpr).expr) {
61 let string_node = ast_node_as::<AstExprConstantString>(
62 (*indexexpr).index as *mut luaur_ast::records::ast_node::AstNode,
63 );
64 if !string_node.is_null() {
65 let data = (*string_node).value.data;
66 let size = (*string_node).value.size;
67 let key = if data.is_null() {
68 alloc::string::String::new()
69 } else {
70 let slice = core::slice::from_raw_parts(data as *const u8, size as usize);
71 alloc::string::String::from_utf8_lossy(slice).into_owned()
72 };
73 return Some(LValue::Field(Field {
74 parent: Some(Arc::new(lvalue)),
75 key,
76 }));
77 }
78 }
79 }
80 }
81
82 None
83}