Skip to main content

luaur_analysis/functions/
snapshot_scope.rs

1use crate::functions::to_string_detailed_to_string::to_string_detailed_type_id_to_string_options;
2use crate::functions::to_string_to_string_alt_m::to_string_type_id_to_string_options;
3use crate::functions::to_string_to_string_alt_n::to_string_type_pack_id_to_string_options;
4use crate::records::binding_snapshot::BindingSnapshot;
5use crate::records::scope::Scope;
6use crate::records::scope_snapshot::ScopeSnapshot;
7use crate::records::to_string_options::ToStringOptions;
8use crate::records::to_string_result::ToStringResult;
9use crate::records::type_binding_snapshot::TypeBindingSnapshot;
10use alloc::string::{String, ToString};
11use alloc::vec::Vec;
12use std::collections::HashMap;
13
14/// C++ `static ScopeSnapshot snapshotScope(const Scope* scope, ToStringOptions& opts)`.
15pub fn snapshot_scope(scope: &Scope, opts: &mut ToStringOptions) -> ScopeSnapshot {
16    let mut bindings: HashMap<String, BindingSnapshot> = HashMap::new();
17    let mut type_bindings: HashMap<String, TypeBindingSnapshot> = HashMap::new();
18    let mut type_pack_bindings: HashMap<String, TypeBindingSnapshot> = HashMap::new();
19    let mut children: Vec<ScopeSnapshot> = Vec::new();
20
21    for (symbol, binding) in &scope.bindings {
22        let id = binding.type_id as usize;
23        let id_str = id.to_string();
24        let result: ToStringResult =
25            to_string_detailed_type_id_to_string_options(binding.type_id, opts);
26        let type_string = result.name.clone();
27
28        // C++ `Symbol::c_str()`: prefer the local's name, else the global AstName.
29        let key = unsafe {
30            let cstr = if !symbol.local.is_null() {
31                (*symbol.local).name.value
32            } else {
33                symbol.global.value
34            };
35            core::ffi::CStr::from_ptr(cstr)
36                .to_string_lossy()
37                .to_string()
38        };
39        bindings.insert(
40            key,
41            BindingSnapshot {
42                type_id: id_str,
43                type_string,
44                location: binding.location,
45            },
46        );
47    }
48
49    for (name, tf) in &scope.exported_type_bindings {
50        let id = tf.r#type as usize;
51        let id_str = id.to_string();
52        let type_string = to_string_type_id_to_string_options(tf.r#type, opts);
53
54        type_bindings.insert(
55            name.clone(),
56            TypeBindingSnapshot {
57                type_id: id_str,
58                type_string,
59            },
60        );
61    }
62
63    for (name, tf) in &scope.private_type_bindings {
64        let id = tf.r#type as usize;
65        let id_str = id.to_string();
66        let type_string = to_string_type_id_to_string_options(tf.r#type, opts);
67
68        type_bindings.insert(
69            name.clone(),
70            TypeBindingSnapshot {
71                type_id: id_str,
72                type_string,
73            },
74        );
75    }
76
77    for (name, tp) in &scope.private_type_pack_bindings {
78        let id = *tp as usize;
79        let id_str = id.to_string();
80        let type_string = to_string_type_pack_id_to_string_options(*tp, opts);
81
82        type_pack_bindings.insert(
83            name.clone(),
84            TypeBindingSnapshot {
85                type_id: id_str,
86                type_string,
87            },
88        );
89    }
90
91    for child in &scope.children {
92        let child_scope = unsafe { &**child };
93        children.push(snapshot_scope(child_scope, opts));
94    }
95
96    ScopeSnapshot {
97        bindings,
98        type_bindings,
99        type_pack_bindings,
100        children,
101    }
102}