Skip to main content

luaur_ast/methods/
printer_visualize_function_body.rs

1use crate::records::ast_expr_function::AstExprFunction;
2use crate::records::ast_generic_type::AstGenericType;
3use crate::records::ast_generic_type_pack::AstGenericTypePack;
4use crate::records::ast_local::AstLocal;
5use crate::records::ast_stat_block::AstStatBlock;
6use crate::records::comma_separator_inserter::CommaSeparatorInserter;
7use crate::records::cst_expr_function::CstExprFunction;
8use crate::records::cst_generic_type_pack::CstGenericTypePack;
9use crate::records::printer::Printer;
10
11pub trait IntoAstExprFunctionMut {
12    unsafe fn into_ast_expr_function_mut(self) -> *mut AstExprFunction;
13}
14
15impl IntoAstExprFunctionMut for *mut AstExprFunction {
16    unsafe fn into_ast_expr_function_mut(self) -> *mut AstExprFunction {
17        self
18    }
19}
20
21impl IntoAstExprFunctionMut for &mut AstExprFunction {
22    unsafe fn into_ast_expr_function_mut(self) -> *mut AstExprFunction {
23        self
24    }
25}
26
27impl<'a> Printer<'a> {
28    pub fn visualize_function_body<F: IntoAstExprFunctionMut>(&mut self, func: F) {
29        let func = unsafe { &mut *func.into_ast_expr_function_mut() };
30        let cst_node =
31            self.lookup_cst_node_impl::<CstExprFunction>(func as *mut AstExprFunction as *mut _);
32
33        if func.generics.size > 0 || func.generic_packs.size > 0 {
34            let comma_position = if cst_node.is_null() {
35                core::ptr::null()
36            } else {
37                unsafe { (*cst_node).generics_comma_positions.data }
38            };
39
40            let mut comma = CommaSeparatorInserter::new(self.writer, core::ptr::null());
41            comma.comma_position = comma_position;
42
43            if !cst_node.is_null() {
44                let open_pos = unsafe { &(*cst_node).open_generics_position };
45                self.maybe_advance_and_write(open_pos, "<", false);
46            } else {
47                self.writer.symbol("<");
48            }
49
50            for i in 0..func.generics.size {
51                comma.call(self.writer);
52
53                let generic_ty = unsafe { *func.generics.data.add(i) };
54                unsafe {
55                    self.writer.advance(&(*generic_ty).base.location.begin);
56                    let name_val = (*generic_ty).name.value;
57                    let name_str = core::ffi::CStr::from_ptr(name_val).to_string_lossy();
58                    self.writer.identifier(&name_str);
59                }
60            }
61
62            for i in 0..func.generic_packs.size {
63                comma.call(self.writer);
64
65                let pack = unsafe { *func.generic_packs.data.add(i) };
66                unsafe {
67                    self.writer.advance(&(*pack).base.location.begin);
68                    let name_val = (*pack).name.value;
69                    let name_str = core::ffi::CStr::from_ptr(name_val).to_string_lossy();
70                    self.writer.identifier(&name_str);
71
72                    let generic_type_pack_cst_node =
73                        self.lookup_cst_node_impl::<CstGenericTypePack>(pack as *mut _);
74                    if !generic_type_pack_cst_node.is_null() {
75                        let ellipsis_pos = &(*generic_type_pack_cst_node).ellipsis_position;
76                        self.advance(ellipsis_pos);
77                    }
78
79                    self.writer.symbol("...");
80                }
81            }
82
83            if !cst_node.is_null() {
84                let close_pos = unsafe { &(*cst_node).close_generics_position };
85                self.maybe_advance_and_write(close_pos, ">", false);
86            } else {
87                self.writer.symbol(">");
88            }
89        }
90
91        if let Some(arg_location) = func.arg_location.as_ref() {
92            self.advance(&arg_location.begin);
93        }
94        self.writer.symbol("(");
95
96        let args_comma_pos = if cst_node.is_null() {
97            core::ptr::null()
98        } else {
99            unsafe { (*cst_node).args_comma_positions.data }
100        };
101
102        let mut comma = CommaSeparatorInserter::new(self.writer, core::ptr::null());
103        comma.comma_position = args_comma_pos;
104
105        for i in 0..func.args.size {
106            let local = unsafe { *func.args.data.add(i) };
107            comma.call(self.writer);
108
109            unsafe {
110                self.advance(&(*local).location.begin);
111                let name_val = (*local).name.value;
112                let name_str = core::ffi::CStr::from_ptr(name_val).to_string_lossy();
113                self.writer.identifier(&name_str);
114
115                if self.write_types && !(*local).annotation.is_null() {
116                    if !cst_node.is_null() {
117                        let colon_pos =
118                            unsafe { (*cst_node).args_annotation_colon_positions.data.add(i) };
119                        self.maybe_advance_and_write(&*colon_pos, ":", false);
120                    } else {
121                        self.writer.symbol(":");
122                    }
123
124                    self.visualize_type_annotation(&mut *(*local).annotation);
125                }
126            }
127        }
128
129        if func.vararg {
130            comma.call(self.writer);
131
132            self.advance(&func.vararg_location.begin);
133            self.writer.symbol("...");
134
135            if self.write_types && !func.vararg_annotation.is_null() {
136                if !cst_node.is_null() {
137                    unsafe {
138                        self.maybe_advance_and_write(
139                            &(*cst_node).vararg_annotation_colon_position,
140                            ":",
141                            false,
142                        );
143                    }
144                } else {
145                    self.writer.symbol(":");
146                }
147
148                unsafe {
149                    self.visualize_type_pack_annotation(
150                        &mut *func.vararg_annotation,
151                        true,
152                        false,
153                        false,
154                    );
155                }
156            }
157        }
158
159        if let Some(arg_location) = func.arg_location.as_ref() {
160            self.advance_before(arg_location.end, 1);
161        }
162        self.writer.symbol(")");
163
164        if self.write_types && !func.return_annotation.is_null() {
165            if !cst_node.is_null() {
166                unsafe {
167                    self.maybe_advance_and_write(
168                        &(*cst_node).return_specifier_position,
169                        ":",
170                        false,
171                    );
172                }
173            } else {
174                self.writer.symbol(":");
175            }
176
177            if cst_node.is_null() {
178                self.writer.space();
179            }
180
181            unsafe {
182                self.visualize_type_pack_annotation(
183                    &mut *func.return_annotation,
184                    false,
185                    false,
186                    true,
187                );
188            }
189        }
190
191        unsafe {
192            self.visualize_block_ast_stat_block(&mut *func.body);
193            self.advance(&(*func.body).base.base.location.end);
194        }
195        self.writer.keyword("end");
196    }
197}