Skip to main content

darklua_core/nodes/
function_body.rs

1use crate::nodes::Attributes;
2
3use super::{
4    Block, FunctionExpression, FunctionName, FunctionReturnType, FunctionStatement,
5    FunctionVariadicType, GenericParameters, Identifier, LocalFunctionStatement,
6    LocalFunctionTokens, Token, TypeFunctionStatement, TypeFunctionStatementTokens,
7    TypedIdentifier,
8};
9
10pub(crate) struct FunctionBuilder {
11    block: Block,
12    parameters: Vec<TypedIdentifier>,
13    is_variadic: bool,
14    variadic_type: Option<FunctionVariadicType>,
15    return_type: Option<FunctionReturnType>,
16
17    function: Option<Token>,
18    opening_parenthese: Option<Token>,
19    closing_parenthese: Option<Token>,
20    end: Option<Token>,
21    parameter_commas: Vec<Token>,
22
23    variable_arguments: Option<Token>,
24    variable_arguments_colon: Option<Token>,
25    return_type_colon: Option<Token>,
26    generic_parameters: Option<GenericParameters>,
27
28    attributes: Attributes,
29}
30
31impl FunctionBuilder {
32    pub fn from_block(block: impl Into<Block>) -> Self {
33        Self {
34            block: block.into(),
35            parameters: Vec::new(),
36            is_variadic: false,
37            variadic_type: None,
38            return_type: None,
39
40            function: None,
41            opening_parenthese: None,
42            closing_parenthese: None,
43            end: None,
44            parameter_commas: Vec::new(),
45
46            variable_arguments: None,
47            variable_arguments_colon: None,
48            return_type_colon: None,
49            generic_parameters: None,
50
51            attributes: Attributes::new(),
52        }
53    }
54
55    pub(crate) fn into_function_expression(self) -> FunctionExpression {
56        let mut expression = FunctionExpression::new(self.block, self.parameters, self.is_variadic)
57            .with_attributes(self.attributes);
58
59        if let Some(variadic_type) = self.variadic_type {
60            expression.set_variadic_type(variadic_type);
61        }
62
63        if let Some(return_type) = self.return_type {
64            expression.set_return_type(return_type);
65        }
66
67        if let Some(generic_parameters) = self.generic_parameters {
68            expression.set_generic_parameters(generic_parameters);
69        }
70
71        if let (Some(function), Some(opening_parenthese), Some(closing_parenthese), Some(end)) = (
72            self.function,
73            self.opening_parenthese,
74            self.closing_parenthese,
75            self.end,
76        ) {
77            expression.set_tokens(FunctionBodyTokens {
78                function,
79                opening_parenthese,
80                closing_parenthese,
81                end,
82                parameter_commas: self.parameter_commas,
83                variable_arguments: self.variable_arguments,
84                variable_arguments_colon: self.variable_arguments_colon,
85                return_type_colon: self.return_type_colon,
86            });
87        }
88
89        expression
90    }
91
92    pub(crate) fn into_function_statement(self, name: FunctionName) -> FunctionStatement {
93        let mut statement =
94            FunctionStatement::new(name, self.block, self.parameters, self.is_variadic)
95                .with_attributes(self.attributes);
96
97        if let Some(variadic_type) = self.variadic_type {
98            statement.set_variadic_type(variadic_type);
99        }
100
101        if let Some(return_type) = self.return_type {
102            statement.set_return_type(return_type);
103        }
104
105        if let Some(generic_parameters) = self.generic_parameters {
106            statement.set_generic_parameters(generic_parameters);
107        }
108
109        if let (Some(function), Some(opening_parenthese), Some(closing_parenthese), Some(end)) = (
110            self.function,
111            self.opening_parenthese,
112            self.closing_parenthese,
113            self.end,
114        ) {
115            statement.set_tokens(FunctionBodyTokens {
116                function,
117                opening_parenthese,
118                closing_parenthese,
119                end,
120                parameter_commas: self.parameter_commas,
121                variable_arguments: self.variable_arguments,
122                variable_arguments_colon: self.variable_arguments_colon,
123                return_type_colon: self.return_type_colon,
124            });
125        }
126
127        statement
128    }
129
130    pub(crate) fn into_local_function_statement(
131        self,
132        name: Identifier,
133        local_token: Option<Token>,
134    ) -> LocalFunctionStatement {
135        let mut statement =
136            LocalFunctionStatement::new(name, self.block, self.parameters, self.is_variadic)
137                .with_attributes(self.attributes);
138
139        if let Some(variadic_type) = self.variadic_type {
140            statement.set_variadic_type(variadic_type);
141        }
142
143        if let Some(return_type) = self.return_type {
144            statement.set_return_type(return_type);
145        }
146
147        if let Some(generic_parameters) = self.generic_parameters {
148            statement.set_generic_parameters(generic_parameters);
149        }
150
151        if let (
152            Some(local),
153            Some(function),
154            Some(opening_parenthese),
155            Some(closing_parenthese),
156            Some(end),
157        ) = (
158            local_token,
159            self.function,
160            self.opening_parenthese,
161            self.closing_parenthese,
162            self.end,
163        ) {
164            statement.set_tokens(LocalFunctionTokens {
165                local,
166                function_body: FunctionBodyTokens {
167                    function,
168                    opening_parenthese,
169                    closing_parenthese,
170                    end,
171                    parameter_commas: self.parameter_commas,
172                    variable_arguments: self.variable_arguments,
173                    variable_arguments_colon: self.variable_arguments_colon,
174                    return_type_colon: self.return_type_colon,
175                },
176            });
177        }
178
179        statement
180    }
181
182    pub(crate) fn into_type_function_statement(
183        self,
184        name: Identifier,
185        type_token: Option<Token>,
186        export_token: Option<Token>,
187    ) -> TypeFunctionStatement {
188        let mut statement =
189            TypeFunctionStatement::new(name, self.block, self.parameters, self.is_variadic);
190
191        if let Some(variadic_type) = self.variadic_type {
192            statement.set_variadic_type(variadic_type);
193        }
194
195        if let Some(return_type) = self.return_type {
196            statement.set_return_type(return_type);
197        }
198
199        if let Some(generic_parameters) = self.generic_parameters {
200            statement.set_generic_parameters(generic_parameters);
201        }
202
203        if let (
204            Some(type_token),
205            Some(function),
206            Some(opening_parenthese),
207            Some(closing_parenthese),
208            Some(end),
209        ) = (
210            type_token,
211            self.function,
212            self.opening_parenthese,
213            self.closing_parenthese,
214            self.end,
215        ) {
216            statement.set_tokens(TypeFunctionStatementTokens {
217                r#type: type_token,
218                export: export_token,
219                function_body: FunctionBodyTokens {
220                    function,
221                    opening_parenthese,
222                    closing_parenthese,
223                    end,
224                    parameter_commas: self.parameter_commas,
225                    variable_arguments: self.variable_arguments,
226                    variable_arguments_colon: self.variable_arguments_colon,
227                    return_type_colon: self.return_type_colon,
228                },
229            });
230        }
231
232        statement
233    }
234
235    pub(crate) fn is_variadic(&self) -> bool {
236        self.is_variadic
237    }
238
239    pub(crate) fn set_return_type_colon(&mut self, token: Token) {
240        self.return_type_colon = Some(token);
241    }
242
243    pub(crate) fn set_return_type(&mut self, r#type: FunctionReturnType) {
244        self.return_type = Some(r#type);
245    }
246
247    pub(crate) fn set_variable_arguments_token(&mut self, token: Token) {
248        self.variable_arguments = Some(token);
249    }
250
251    pub(crate) fn set_variadic(&mut self) {
252        self.is_variadic = true;
253    }
254
255    pub(crate) fn set_variadic_type(&mut self, r#type: FunctionVariadicType) {
256        self.is_variadic = true;
257        self.variadic_type = Some(r#type);
258    }
259
260    pub(crate) fn set_variable_arguments_colon(&mut self, token: Token) {
261        self.variable_arguments_colon = Some(token);
262    }
263
264    pub(crate) fn push_parameter(&mut self, typed_identifier: TypedIdentifier) {
265        self.parameters.push(typed_identifier);
266    }
267
268    pub(crate) fn set_parentheses_tokens(&mut self, open: Token, close: Token) {
269        self.opening_parenthese = Some(open);
270        self.closing_parenthese = Some(close);
271    }
272
273    pub(crate) fn set_parameter_commas(&mut self, commas: Vec<Token>) {
274        self.parameter_commas = commas;
275    }
276
277    pub(crate) fn set_function_token(&mut self, token: Token) {
278        self.function = Some(token);
279    }
280
281    pub(crate) fn set_end_token(&mut self, token: Token) {
282        self.end = Some(token);
283    }
284
285    pub(crate) fn set_generic_parameters(&mut self, generic_parameters: GenericParameters) {
286        self.generic_parameters = Some(generic_parameters);
287    }
288
289    pub(crate) fn set_attributes(&mut self, attributes: Attributes) {
290        self.attributes = attributes;
291    }
292}
293
294/// Represents the token information associated with a function body.
295#[derive(Clone, Debug, PartialEq, Eq)]
296pub struct FunctionBodyTokens {
297    /// The 'function' keyword token.
298    pub function: Token,
299    /// The opening parenthesis token for parameter list.
300    pub opening_parenthese: Token,
301    /// The closing parenthesis token for parameter list.
302    pub closing_parenthese: Token,
303    /// The 'end' keyword token that terminates the function definition.
304    pub end: Token,
305    /// Tokens for commas separating parameters.
306    pub parameter_commas: Vec<Token>,
307    /// The '...' token for variadic functions, if present.
308    pub variable_arguments: Option<Token>,
309    /// The colon token before the variadic type annotation, if present.
310    pub variable_arguments_colon: Option<Token>,
311    /// The colon token before the return type annotation, if present.
312    pub return_type_colon: Option<Token>,
313}
314
315impl FunctionBodyTokens {
316    super::impl_token_fns!(
317        target = [function, opening_parenthese, closing_parenthese, end]
318        iter = [
319            variable_arguments,
320            variable_arguments_colon,
321            return_type_colon,
322            parameter_commas,
323        ]
324    );
325}