Skip to main content

luaur_analysis/functions/
to_string_named_function_to_string_alt_b.rs

1//! Node: `cxx:Function:Luau.Analysis:Analysis/src/ToString.cpp:1742:to_string_named_function`
2//! Source: `Analysis/src/ToString.cpp:1742-1824` (hand-ported)
3
4use crate::functions::begin_type_pack::begin;
5use crate::functions::end_type_pack::end;
6use crate::functions::finite::finite;
7use crate::functions::follow_type_pack::follow_type_pack_id;
8use crate::functions::get_type_pack::get;
9use crate::functions::size_type_pack::size;
10use crate::records::function_type::FunctionType;
11use crate::records::stringifier_state::StringifierState;
12use crate::records::to_string_options::ToStringOptions;
13use crate::records::to_string_result::ToStringResult;
14use crate::records::type_pack::TypePack;
15use crate::records::type_stringifier::TypeStringifier;
16use crate::records::variadic_type_pack::VariadicTypePack;
17use alloc::format;
18use alloc::string::String;
19
20/// C++ `std::string toStringNamedFunction(const std::string& funcName, const FunctionType& ftv, ToStringOptions& opts)`.
21pub fn to_string_named_function_string_function_type_to_string_options(
22    func_name: &str,
23    ftv: &FunctionType,
24    opts: &mut ToStringOptions,
25) -> String {
26    unsafe {
27        let mut result = ToStringResult::default();
28        let mut state = StringifierState::stringifier_state_stringifier_state(
29            opts as *mut ToStringOptions,
30            &mut result as *mut ToStringResult,
31        );
32        let mut tvs = TypeStringifier {
33            state: &mut state as *mut StringifierState,
34        };
35
36        state.emit(func_name);
37
38        if !opts.hide_named_function_type_parameters {
39            tvs.stringify_vector_type_id_vector_type_pack_id(&ftv.generics, &ftv.generic_packs);
40        }
41
42        state.emit("(");
43
44        let mut arg_pack_iter = begin(ftv.arg_types);
45        let end_iter = end(ftv.arg_types);
46
47        let mut first = true;
48        let mut idx: usize = 0;
49        while arg_pack_iter.operator_ne(&end_iter) {
50            // ftv takes a self parameter as the first argument, skip it if specified in option
51            if idx == 0 && ftv.has_self && opts.hide_function_self_argument {
52                arg_pack_iter.operator_inc();
53                idx += 1;
54                continue;
55            }
56
57            if !first {
58                state.emit(", ");
59            }
60            first = false;
61
62            // We don't respect opts.functionTypeArguments
63            if idx < opts.named_function_override_arg_names.len() {
64                state.emit(format!("{}: ", opts.named_function_override_arg_names[idx]).as_str());
65            } else if idx < ftv.arg_names.len() && ftv.arg_names[idx].is_some() {
66                state.emit(format!("{}: ", ftv.arg_names[idx].as_ref().unwrap().name).as_str());
67            } else {
68                state.emit("_: ");
69            }
70            tvs.stringify_type_id(*arg_pack_iter.operator_deref());
71
72            arg_pack_iter.operator_inc();
73            idx += 1;
74        }
75
76        if let Some(tail) = arg_pack_iter.tail() {
77            let vtp = get::<VariadicTypePack>(tail);
78            if vtp.is_null() || !(*vtp).hidden {
79                if !first {
80                    state.emit(", ");
81                }
82
83                state.emit("...: ");
84
85                if !vtp.is_null() {
86                    tvs.stringify_type_id((*vtp).ty);
87                } else {
88                    tvs.stringify_type_pack_id(tail);
89                }
90            }
91        }
92
93        state.emit("): ");
94
95        let ret_size = size(ftv.ret_types, core::ptr::null_mut());
96        let has_tail = !finite(ftv.ret_types, core::ptr::null_mut());
97        let wrap = !get::<TypePack>(follow_type_pack_id(ftv.ret_types)).is_null()
98            && (if has_tail {
99                ret_size != 0
100            } else {
101                ret_size > 1
102            });
103
104        if wrap {
105            state.emit("(");
106        }
107
108        tvs.stringify_type_pack_id(ftv.ret_types);
109
110        if wrap {
111            state.emit(")");
112        }
113
114        result.name
115    }
116}