Skip to main content

darklua_core/generator/
token_based.rs

1use std::iter;
2
3use crate::{
4    generator::{utils, LuaGenerator},
5    nodes::*,
6};
7
8/// This implementation of [LuaGenerator](trait.LuaGenerator.html) outputs the
9/// AST nodes from the tokens associated with each of them.
10#[derive(Debug, Clone)]
11pub struct TokenBasedLuaGenerator<'a> {
12    original_code: &'a str,
13    output: String,
14    currently_commenting: bool,
15    current_line: usize,
16}
17
18impl<'a> TokenBasedLuaGenerator<'a> {
19    pub fn new(original_code: &'a str) -> Self {
20        Self {
21            original_code,
22            output: String::new(),
23            currently_commenting: false,
24            current_line: 1,
25        }
26    }
27
28    fn push_str(&mut self, string: &str) {
29        self.current_line += utils::count_new_lines(string.as_bytes());
30        self.output.push_str(string);
31    }
32
33    fn write_trivia(&mut self, trivia: &Trivia) {
34        let content = trivia.read(self.original_code);
35
36        let is_comment = matches!(trivia.kind(), TriviaKind::Comment);
37        let is_line_comment = is_comment && is_single_line_comment(content);
38        let is_multiline_comment = is_comment && !is_line_comment;
39
40        if is_multiline_comment && self.currently_commenting {
41            self.uncomment();
42        }
43
44        self.push_str(content);
45
46        match trivia.kind() {
47            TriviaKind::Comment => {
48                if is_line_comment {
49                    self.currently_commenting = true;
50                }
51            }
52            TriviaKind::Whitespace => {
53                if self.currently_commenting && content.contains('\n') {
54                    self.currently_commenting = false
55                }
56            }
57        }
58    }
59
60    #[inline]
61    fn write_token(&mut self, token: &Token) {
62        self.write_token_options(token, true)
63    }
64
65    fn write_token_options(&mut self, token: &Token, space_check: bool) {
66        for trivia in token.iter_leading_trivia() {
67            self.write_trivia(trivia);
68        }
69
70        let content = token.read(self.original_code);
71
72        if !content.is_empty() {
73            if self.currently_commenting {
74                self.uncomment();
75            }
76
77            if let Some(line_number) = token.get_line_number() {
78                while line_number > self.current_line {
79                    self.output.push('\n');
80                    self.current_line += 1;
81                }
82            }
83
84            if space_check {
85                if let Some(next_character) = content.chars().next() {
86                    if self.needs_space(next_character) {
87                        self.output.push(' ');
88                    }
89                }
90            }
91
92            self.push_str(content);
93        }
94
95        for trivia in token.iter_trailing_trivia() {
96            self.write_trivia(trivia);
97        }
98    }
99
100    fn write_block_with_tokens(&mut self, block: &Block, tokens: &BlockTokens) {
101        let mut iterator = block.iter_statements().enumerate().peekable();
102
103        while let Some((index, statement)) = iterator.next() {
104            self.write_statement(statement);
105
106            if let Some(semicolon) = tokens.semicolons.get(index).unwrap_or(&None) {
107                self.write_token(semicolon);
108            } else if let Some((_, next_statement)) = iterator.peek() {
109                if utils::starts_with_parenthese(next_statement)
110                    && utils::ends_with_prefix(statement)
111                {
112                    self.write_symbol(";");
113                }
114            };
115        }
116
117        if let Some(statement) = block.get_last_statement() {
118            self.write_last_statement(statement);
119        }
120
121        if let Some(token) = &tokens.final_token {
122            self.write_token(token);
123        }
124    }
125
126    fn write_return_with_tokens(&mut self, statement: &ReturnStatement, tokens: &ReturnTokens) {
127        self.write_token(&tokens.r#return);
128
129        let last_index = statement.len().saturating_sub(1);
130        statement
131            .iter_expressions()
132            .enumerate()
133            .for_each(|(i, expression)| {
134                self.write_expression(expression);
135                if i < last_index {
136                    if let Some(comma) = tokens.commas.get(i) {
137                        self.write_token(comma);
138                    } else {
139                        self.write_symbol(",");
140                    }
141                }
142            });
143    }
144
145    fn write_assign_with_tokens(&mut self, assign: &AssignStatement, tokens: &AssignTokens) {
146        let last_variable_index = assign.variables_len().saturating_sub(1);
147        assign
148            .iter_variables()
149            .enumerate()
150            .for_each(|(i, variable)| {
151                self.write_variable(variable);
152                if i < last_variable_index {
153                    if let Some(comma) = tokens.variable_commas.get(i) {
154                        self.write_token(comma);
155                    } else {
156                        self.write_symbol(",");
157                    }
158                }
159            });
160
161        self.write_token(&tokens.equal);
162        let last_value_index = assign.values_len().saturating_sub(1);
163        assign.iter_values().enumerate().for_each(|(i, value)| {
164            self.write_expression(value);
165            if i < last_value_index {
166                if let Some(comma) = tokens.value_commas.get(i) {
167                    self.write_token(comma);
168                } else {
169                    self.write_symbol(",");
170                }
171            }
172        });
173    }
174
175    fn write_do_with_tokens(&mut self, do_statement: &DoStatement, tokens: &DoTokens) {
176        self.write_token(&tokens.r#do);
177        self.write_block(do_statement.get_block());
178        self.write_token(&tokens.end);
179    }
180
181    fn write_function_call_with_tokens(
182        &mut self,
183        call: &FunctionCall,
184        tokens: &FunctionCallTokens,
185    ) {
186        self.write_prefix(call.get_prefix());
187        if let Some(method) = call.get_method() {
188            if let Some(colon) = &tokens.colon {
189                self.write_token(colon);
190            } else {
191                self.write_symbol(":");
192            }
193            self.write_identifier(method);
194        }
195        self.write_arguments(call.get_arguments());
196    }
197
198    fn write_parenthese_with_tokens(
199        &mut self,
200        parenthese: &ParentheseExpression,
201        tokens: &ParentheseTokens,
202    ) {
203        self.write_token(&tokens.left_parenthese);
204        self.write_expression(parenthese.inner_expression());
205        self.write_token(&tokens.right_parenthese);
206    }
207
208    fn write_type_cast_with_tokens(&mut self, type_cast: &TypeCastExpression, token: &Token) {
209        let inner_expression = type_cast.get_expression();
210
211        if TypeCastExpression::needs_parentheses(inner_expression) {
212            self.write_symbol("(");
213            self.write_expression(inner_expression);
214            self.write_symbol(")");
215        } else {
216            self.write_expression(inner_expression);
217        }
218
219        self.write_token(token);
220        self.write_type(type_cast.get_type());
221    }
222
223    fn write_tuple_arguments_with_tokens(
224        &mut self,
225        arguments: &TupleArguments,
226        tokens: &TupleArgumentsTokens,
227    ) {
228        self.write_token(&tokens.opening_parenthese);
229
230        let last_value_index = arguments.len().saturating_sub(1);
231        arguments.iter_values().enumerate().for_each(|(i, value)| {
232            self.write_expression(value);
233            if i < last_value_index {
234                if let Some(comma) = tokens.commas.get(i) {
235                    self.write_token(comma);
236                } else {
237                    self.write_symbol(",");
238                }
239            }
240        });
241
242        self.write_token(&tokens.closing_parenthese);
243    }
244
245    fn write_table_with_tokens(&mut self, table: &TableExpression, tokens: &TableTokens) {
246        self.write_token(&tokens.opening_brace);
247
248        let last_index = table.len().saturating_sub(1);
249        table.iter_entries().enumerate().for_each(|(i, entry)| {
250            self.write_table_entry(entry);
251            if let Some(separator) = tokens.separators.get(i) {
252                self.write_token(separator);
253            } else if i < last_index {
254                self.write_symbol(",");
255            }
256        });
257
258        self.write_token(&tokens.closing_brace);
259    }
260
261    fn write_table_field_with_tokens(&mut self, entry: &TableFieldEntry, token: &Token) {
262        self.write_identifier(entry.get_field());
263        self.write_token(token);
264        self.write_expression(entry.get_value());
265    }
266
267    fn write_table_index_with_tokens(
268        &mut self,
269        entry: &TableIndexEntry,
270        tokens: &TableIndexEntryTokens,
271    ) {
272        self.write_token(&tokens.opening_bracket);
273        self.write_expression(entry.get_key());
274        self.write_token(&tokens.closing_bracket);
275        self.write_token(&tokens.equal);
276        self.write_expression(entry.get_value());
277    }
278
279    fn write_field_with_token(&mut self, field: &FieldExpression, token: &Token) {
280        self.write_prefix(field.get_prefix());
281        self.write_token_options(token, false);
282        self.write_identifier(field.get_field());
283    }
284
285    fn write_index_with_tokens(&mut self, index: &IndexExpression, tokens: &IndexExpressionTokens) {
286        self.write_prefix(index.get_prefix());
287        self.write_token(&tokens.opening_bracket);
288        self.write_expression(index.get_index());
289        self.write_token(&tokens.closing_bracket);
290    }
291
292    fn write_if_expression_with_token(
293        &mut self,
294        if_expression: &IfExpression,
295        tokens: &IfExpressionTokens,
296    ) {
297        self.write_token(&tokens.r#if);
298        self.write_expression(if_expression.get_condition());
299        self.write_token(&tokens.then);
300        self.write_expression(if_expression.get_result());
301
302        for branch in if_expression.iter_branches() {
303            if let Some(tokens) = branch.get_tokens() {
304                self.write_if_expression_branch_with_tokens(branch, tokens);
305            } else {
306                self.write_if_expression_branch_with_tokens(
307                    branch,
308                    &self.generate_if_expression_branch_tokens(branch),
309                );
310            }
311        }
312
313        self.write_token(&tokens.r#else);
314        self.write_expression(if_expression.get_else_result());
315    }
316
317    fn write_if_expression_branch_with_tokens(
318        &mut self,
319        branch: &ElseIfExpressionBranch,
320        tokens: &ElseIfExpressionBranchTokens,
321    ) {
322        self.write_token(&tokens.elseif);
323        self.write_expression(branch.get_condition());
324        self.write_token(&tokens.then);
325        self.write_expression(branch.get_result());
326    }
327
328    fn write_compound_assign_with_tokens(
329        &mut self,
330        assign: &CompoundAssignStatement,
331        tokens: &CompoundAssignTokens,
332    ) {
333        self.write_variable(assign.get_variable());
334        self.write_token(&tokens.operator);
335        self.write_expression(assign.get_value());
336    }
337
338    #[allow(clippy::too_many_arguments)]
339    fn write_function_attributes<'b>(
340        &mut self,
341        tokens: &FunctionBodyTokens,
342        generic_parameters: Option<&GenericParameters>,
343        parameter_count: usize,
344        parameters: impl Iterator<Item = &'b TypedIdentifier>,
345        is_variadic: bool,
346        variadic_type: Option<&FunctionVariadicType>,
347        return_type: Option<&FunctionReturnType>,
348        block: &Block,
349    ) {
350        if let Some(generics) = generic_parameters {
351            self.write_function_generics(generics);
352        }
353
354        self.write_token(&tokens.opening_parenthese);
355
356        let last_parameter_index = parameter_count.saturating_sub(1);
357        parameters.enumerate().for_each(|(i, param)| {
358            self.write_typed_identifier(param);
359            if i < last_parameter_index {
360                if let Some(comma) = tokens.parameter_commas.get(i) {
361                    self.write_token(comma);
362                } else {
363                    self.write_symbol(",");
364                }
365            }
366        });
367
368        if is_variadic {
369            if parameter_count > 0 {
370                if let Some(comma) = tokens.parameter_commas.get(last_parameter_index) {
371                    self.write_token(comma);
372                } else {
373                    self.write_symbol(",");
374                }
375            }
376
377            if let Some(token) = &tokens.variable_arguments {
378                self.write_token(token);
379            } else {
380                self.write_symbol("...");
381            }
382
383            if let Some(variadic_type) = variadic_type {
384                if let Some(colon) = &tokens.variable_arguments_colon {
385                    self.write_token(colon);
386                } else {
387                    self.write_symbol(":")
388                }
389                self.write_function_variadic_type(variadic_type);
390            }
391        }
392
393        self.write_token(&tokens.closing_parenthese);
394
395        if let Some(return_type) = return_type {
396            if let Some(colon) = &tokens.return_type_colon {
397                self.write_token(colon);
398            } else {
399                self.write_symbol(":")
400            }
401
402            self.write_function_return_type(return_type);
403        }
404
405        self.write_block(block);
406
407        self.write_token(&tokens.end);
408    }
409
410    fn write_attributes(&mut self, attributes: &Attributes) {
411        for attribute in attributes.iter_attributes() {
412            match attribute {
413                Attribute::Name(named) => {
414                    if let Some(token) = named.get_token() {
415                        self.write_named_attribute_with_token(named, token);
416                    } else {
417                        self.write_named_attribute_with_token(
418                            named,
419                            &self.generate_named_attribute_token(named),
420                        );
421                    }
422                }
423                Attribute::Group(group) => {
424                    if let Some(tokens) = group.get_tokens() {
425                        self.write_attribute_group_with_tokens(group, tokens);
426                    } else {
427                        self.write_attribute_group_with_tokens(
428                            group,
429                            &self.generate_attribute_group_tokens(group),
430                        );
431                    }
432                }
433            }
434        }
435    }
436
437    fn write_named_attribute_with_token(&mut self, named: &NamedAttribute, token: &Token) {
438        self.write_token(token);
439        self.write_identifier(named.get_identifier());
440    }
441
442    fn write_attribute_group_with_tokens(
443        &mut self,
444        group: &AttributeGroup,
445        tokens: &AttributeGroupTokens,
446    ) {
447        self.write_token(&tokens.opening_attribute_list);
448
449        let last_index = group.len().saturating_sub(1);
450
451        for (index, attribute) in group.iter_attributes().enumerate() {
452            self.write_identifier(attribute.name());
453
454            if let Some(arguments) = attribute.get_arguments() {
455                self.write_attribute_arguments(arguments);
456            }
457
458            if index < last_index {
459                if let Some(separator) = tokens.separators.get(index) {
460                    self.write_token(separator);
461                } else {
462                    self.write_symbol(",");
463                }
464            }
465        }
466
467        self.write_token(&tokens.closing_bracket);
468    }
469
470    fn write_literal_table_with_tokens(&mut self, table: &LiteralTable, tokens: &TableTokens) {
471        self.write_token(&tokens.opening_brace);
472
473        let last_index = table.len().saturating_sub(1);
474        for (i, entry) in table.iter_entries().enumerate() {
475            self.write_literal_table_entry(entry);
476            if let Some(separator) = tokens.separators.get(i) {
477                self.write_token(separator);
478            } else if i < last_index {
479                self.write_symbol(",");
480            }
481        }
482
483        self.write_token(&tokens.closing_brace);
484    }
485
486    fn write_literal_table_field_with_token(
487        &mut self,
488        field: &LiteralTableFieldEntry,
489        token: &Token,
490    ) {
491        self.write_identifier(field.get_field());
492        self.write_token(token);
493        self.write_literal_expression(field.get_value());
494    }
495
496    fn write_attribute_tuple_arguments_with_tokens(
497        &mut self,
498        tuple: &AttributeTupleArguments,
499        tokens: &TupleArgumentsTokens,
500    ) {
501        self.write_token(&tokens.opening_parenthese);
502
503        let last_index = tuple.len().saturating_sub(1);
504        for (i, value) in tuple.iter_values().enumerate() {
505            self.write_literal_expression(value);
506            if i < last_index {
507                if let Some(comma) = tokens.commas.get(i) {
508                    self.write_token(comma);
509                } else {
510                    self.write_symbol(",");
511                }
512            }
513        }
514
515        self.write_token(&tokens.closing_parenthese);
516    }
517
518    fn write_function_statement_with_tokens(
519        &mut self,
520        function: &FunctionStatement,
521        tokens: &FunctionBodyTokens,
522    ) {
523        self.write_attributes(function.attributes());
524        self.write_token(&tokens.function);
525
526        let name = function.get_name();
527        if let Some(tokens) = name.get_tokens() {
528            self.write_function_name_with_tokens(name, tokens);
529        } else {
530            self.write_function_name_with_tokens(name, &self.generate_function_name_tokens(name));
531        }
532
533        self.write_function_attributes(
534            tokens,
535            function.get_generic_parameters(),
536            function.parameters_count(),
537            function.iter_parameters(),
538            function.is_variadic(),
539            function.get_variadic_type(),
540            function.get_return_type(),
541            function.get_block(),
542        );
543    }
544
545    fn write_function_name_with_tokens(
546        &mut self,
547        name: &FunctionName,
548        tokens: &FunctionNameTokens,
549    ) {
550        self.write_identifier(name.get_name());
551
552        name.get_field_names()
553            .iter()
554            .enumerate()
555            .for_each(|(i, field)| {
556                if let Some(period) = tokens.periods.get(i) {
557                    self.write_token_options(period, false);
558                } else {
559                    self.write_symbol_without_space_check(".");
560                }
561                self.write_identifier(field);
562            });
563
564        if let Some(method) = name.get_method() {
565            if let Some(colon) = &tokens.colon {
566                self.write_token(colon);
567            } else {
568                self.write_symbol(":");
569            }
570            self.write_identifier(method);
571        }
572    }
573
574    fn write_generic_for_with_tokens(
575        &mut self,
576        generic_for: &GenericForStatement,
577        tokens: &GenericForTokens,
578    ) {
579        self.write_token(&tokens.r#for);
580
581        let last_identifier_index = generic_for.identifiers_len().saturating_sub(1);
582        generic_for
583            .iter_identifiers()
584            .enumerate()
585            .for_each(|(i, identifier)| {
586                self.write_typed_identifier(identifier);
587                if i < last_identifier_index {
588                    if let Some(comma) = tokens.identifier_commas.get(i) {
589                        self.write_token(comma);
590                    } else {
591                        self.write_symbol(",");
592                    }
593                }
594            });
595
596        self.write_token(&tokens.r#in);
597
598        let last_expression_index = generic_for.expressions_len().saturating_sub(1);
599        generic_for
600            .iter_expressions()
601            .enumerate()
602            .for_each(|(i, expression)| {
603                self.write_expression(expression);
604                if i < last_expression_index {
605                    if let Some(comma) = tokens.value_commas.get(i) {
606                        self.write_token(comma);
607                    } else {
608                        self.write_symbol(",");
609                    }
610                }
611            });
612
613        self.write_token(&tokens.r#do);
614        self.write_block(generic_for.get_block());
615        self.write_token(&tokens.end);
616    }
617
618    fn write_if_statement_with_tokens(
619        &mut self,
620        if_statement: &IfStatement,
621        tokens: &IfStatementTokens,
622    ) {
623        let mut branches = if_statement.iter_branches();
624        if let Some(branch) = branches.next() {
625            self.write_token(&tokens.r#if);
626            self.write_expression(branch.get_condition());
627            self.write_token(&tokens.then);
628            self.write_block(branch.get_block());
629
630            for branch in branches {
631                if let Some(tokens) = branch.get_tokens() {
632                    self.write_if_branch_with_tokens(branch, tokens);
633                } else {
634                    self.write_if_branch_with_tokens(
635                        branch,
636                        &self.generate_if_branch_tokens(branch),
637                    );
638                }
639            }
640
641            if let Some(else_block) = if_statement.get_else_block() {
642                if let Some(token) = &tokens.r#else {
643                    self.write_token(token);
644                } else {
645                    self.write_symbol("else");
646                }
647                self.write_block(else_block);
648            }
649
650            self.write_token(&tokens.end);
651        }
652    }
653
654    fn write_if_branch_with_tokens(&mut self, branch: &IfBranch, tokens: &IfBranchTokens) {
655        self.write_token(&tokens.elseif);
656        self.write_expression(branch.get_condition());
657        self.write_token(&tokens.then);
658        self.write_block(branch.get_block());
659    }
660
661    fn write_local_assign_with_tokens(
662        &mut self,
663        assign: &LocalAssignStatement,
664        tokens: &LocalAssignTokens,
665    ) {
666        self.write_token(&tokens.local);
667        let last_variable_index = assign.variables_len().saturating_sub(1);
668        assign
669            .iter_variables()
670            .enumerate()
671            .for_each(|(i, identifier)| {
672                self.write_typed_identifier(identifier);
673                if i < last_variable_index {
674                    if let Some(comma) = tokens.variable_commas.get(i) {
675                        self.write_token(comma);
676                    } else {
677                        self.write_symbol(",");
678                    }
679                }
680            });
681
682        if assign.has_values() {
683            if let Some(token) = &tokens.equal {
684                self.write_token(token);
685            } else {
686                self.write_symbol("=");
687            }
688            let last_value_index = assign.values_len().saturating_sub(1);
689            assign.iter_values().enumerate().for_each(|(i, value)| {
690                self.write_expression(value);
691                if i < last_value_index {
692                    if let Some(comma) = tokens.value_commas.get(i) {
693                        self.write_token(comma);
694                    } else {
695                        self.write_symbol(",");
696                    }
697                }
698            });
699        }
700    }
701
702    fn write_local_function_with_tokens(
703        &mut self,
704        function: &LocalFunctionStatement,
705        tokens: &LocalFunctionTokens,
706    ) {
707        self.write_attributes(function.attributes());
708        self.write_token(&tokens.local);
709        self.write_token(&tokens.function);
710        self.write_identifier(function.get_identifier());
711
712        self.write_function_attributes(
713            tokens,
714            function.get_generic_parameters(),
715            function.parameters_count(),
716            function.iter_parameters(),
717            function.is_variadic(),
718            function.get_variadic_type(),
719            function.get_return_type(),
720            function.get_block(),
721        );
722    }
723
724    fn write_numeric_for_with_tokens(
725        &mut self,
726        numeric_for: &NumericForStatement,
727        tokens: &NumericForTokens,
728    ) {
729        self.write_token(&tokens.r#for);
730        self.write_typed_identifier(numeric_for.get_identifier());
731        self.write_token(&tokens.equal);
732        self.write_expression(numeric_for.get_start());
733        self.write_token(&tokens.end_comma);
734        self.write_expression(numeric_for.get_end());
735
736        if let Some(step) = numeric_for.get_step() {
737            if let Some(comma) = &tokens.step_comma {
738                self.write_token(comma);
739            } else {
740                self.write_symbol(",");
741            }
742            self.write_expression(step);
743        }
744
745        self.write_token(&tokens.r#do);
746        self.write_block(numeric_for.get_block());
747        self.write_token(&tokens.end);
748    }
749
750    fn write_repeat_with_tokens(&mut self, repeat: &RepeatStatement, tokens: &RepeatTokens) {
751        self.write_token(&tokens.repeat);
752        self.write_block(repeat.get_block());
753        self.write_token(&tokens.until);
754        self.write_expression(repeat.get_condition());
755    }
756
757    fn write_while_with_tokens(&mut self, while_statement: &WhileStatement, tokens: &WhileTokens) {
758        self.write_token(&tokens.r#while);
759        self.write_expression(while_statement.get_condition());
760        self.write_token(&tokens.r#do);
761        self.write_block(while_statement.get_block());
762        self.write_token(&tokens.end);
763    }
764
765    fn write_type_declaration_with_tokens(
766        &mut self,
767        statement: &TypeDeclarationStatement,
768        tokens: &TypeDeclarationTokens,
769    ) {
770        if statement.is_exported() {
771            if let Some(export_token) = &tokens.export {
772                self.write_token(export_token);
773            } else {
774                self.write_symbol("export");
775            }
776        }
777        self.write_token(&tokens.r#type);
778
779        self.write_identifier(statement.get_name());
780
781        if let Some(generic_parameters) = statement
782            .get_generic_parameters()
783            .filter(|generic_parameters| !generic_parameters.is_empty())
784        {
785            if let Some(tokens) = generic_parameters.get_tokens() {
786                self.write_generic_parameters_with_default_with_tokens(generic_parameters, tokens);
787            } else {
788                self.write_generic_parameters_with_default_with_tokens(
789                    generic_parameters,
790                    &self.generate_generic_parameters_with_defaults_tokens(generic_parameters),
791                );
792            }
793        }
794
795        self.write_token(&tokens.equal);
796
797        self.write_type(statement.get_type());
798    }
799
800    fn write_type_function_with_tokens(
801        &mut self,
802        function: &TypeFunctionStatement,
803        tokens: &TypeFunctionStatementTokens,
804    ) {
805        if function.is_exported() {
806            if let Some(export_token) = &tokens.export {
807                self.write_token(export_token);
808            } else {
809                self.write_symbol("export");
810            }
811        }
812        self.write_token(&tokens.r#type);
813        self.write_token(&tokens.function_body.function);
814
815        self.write_identifier(function.get_identifier());
816
817        self.write_function_attributes(
818            tokens,
819            function.get_generic_parameters(),
820            function.parameters_count(),
821            function.iter_parameters(),
822            function.is_variadic(),
823            function.get_variadic_type(),
824            function.get_return_type(),
825            function.get_block(),
826        );
827    }
828
829    fn write_generic_parameters_with_default_with_tokens(
830        &mut self,
831        generic_parameters: &GenericParametersWithDefaults,
832        tokens: &GenericParametersTokens,
833    ) {
834        self.write_token(&tokens.opening_list);
835
836        let last_index = generic_parameters.len().saturating_sub(1);
837
838        for (i, parameter) in generic_parameters.iter().enumerate() {
839            match parameter {
840                GenericParameterRef::TypeVariable(identifier) => {
841                    self.write_identifier(identifier);
842                }
843                GenericParameterRef::TypeVariableWithDefault(identifier_with_default) => {
844                    self.write_identifier(identifier_with_default.get_type_variable());
845                    if let Some(token) = identifier_with_default.get_token() {
846                        self.write_token(token);
847                    } else {
848                        self.write_symbol("=");
849                    }
850                    self.write_type(identifier_with_default.get_default_type());
851                }
852                GenericParameterRef::GenericTypePack(generic_type_pack) => {
853                    self.write_generic_type_pack(generic_type_pack);
854                }
855                GenericParameterRef::GenericTypePackWithDefault(generic_pack_with_default) => {
856                    self.write_generic_type_pack(generic_pack_with_default.get_generic_type_pack());
857                    if let Some(token) = generic_pack_with_default.get_token() {
858                        self.write_token(token);
859                    } else {
860                        self.write_symbol("=");
861                    }
862                    self.write_generic_type_pack_default(
863                        generic_pack_with_default.get_default_type(),
864                    );
865                }
866            }
867
868            if i < last_index {
869                if let Some(comma) = tokens.commas.get(i) {
870                    self.write_token(comma);
871                } else {
872                    self.write_symbol(",");
873                }
874            }
875        }
876
877        self.write_token(&tokens.closing_list);
878    }
879
880    fn write_function_with_tokens(
881        &mut self,
882        function: &FunctionExpression,
883        tokens: &FunctionBodyTokens,
884    ) {
885        self.write_attributes(function.attributes());
886        self.write_token(&tokens.function);
887
888        self.write_function_attributes(
889            tokens,
890            function.get_generic_parameters(),
891            function.parameters_count(),
892            function.iter_parameters(),
893            function.is_variadic(),
894            function.get_variadic_type(),
895            function.get_return_type(),
896            function.get_block(),
897        );
898    }
899
900    fn write_type_parameters_with_tokens(
901        &mut self,
902        parameters: &TypeParameters,
903        tokens: &TypeParametersTokens,
904    ) {
905        self.write_token(&tokens.opening_list);
906        let last_index = parameters.len().saturating_sub(1);
907
908        for (i, parameter) in parameters.iter().enumerate() {
909            self.write_type_parameter(parameter);
910
911            if i < last_index {
912                if let Some(comma) = tokens.commas.get(i) {
913                    self.write_token(comma);
914                } else {
915                    self.write_symbol(",");
916                }
917            }
918        }
919
920        self.write_token(&tokens.closing_list);
921    }
922
923    fn write_type_field_with_token(&mut self, type_field: &TypeField, token: &Token) {
924        self.write_identifier(type_field.get_namespace());
925        self.write_token_options(token, false);
926        self.write_type_name(type_field.get_type_name());
927    }
928
929    fn write_array_type_with_tokens(&mut self, array_type: &ArrayType, tokens: &ArrayTypeTokens) {
930        self.write_token(&tokens.opening_brace);
931        self.write_type(array_type.get_element_type());
932        self.write_token(&tokens.closing_brace);
933    }
934
935    fn write_table_type_with_tokens(&mut self, table_type: &TableType, tokens: &TableTypeTokens) {
936        self.write_token(&tokens.opening_brace);
937
938        let last_index = table_type.len().saturating_sub(1);
939
940        for (i, property) in table_type.iter_entries().enumerate() {
941            match property {
942                TableEntryType::Property(property) => {
943                    self.write_table_property_modifier(
944                        property.get_modifier(),
945                        property
946                            .get_tokens()
947                            .and_then(|tokens| tokens.modifier.as_ref()),
948                    );
949
950                    self.write_identifier(property.get_identifier());
951
952                    if let Some(tokens) = property.get_tokens() {
953                        self.write_token(&tokens.colon);
954                    } else {
955                        self.write_symbol(":");
956                    }
957
958                    self.write_type(property.get_type());
959                }
960                TableEntryType::Literal(property) => {
961                    if let Some(tokens) = property.get_tokens() {
962                        self.write_table_literal_property_type_with_tokens(property, tokens);
963                    } else {
964                        self.write_table_literal_property_type_with_tokens(
965                            property,
966                            &self.generate_table_indexer_type_tokens(),
967                        );
968                    }
969                }
970                TableEntryType::Indexer(indexer) => {
971                    if let Some(tokens) = indexer.get_tokens() {
972                        self.write_table_indexer_type_with_tokens(indexer, tokens);
973                    } else {
974                        self.write_table_indexer_type_with_tokens(
975                            indexer,
976                            &self.generate_table_indexer_type_tokens(),
977                        );
978                    }
979                }
980            }
981
982            if let Some(comma) = tokens.separators.get(i) {
983                self.write_token(comma);
984            } else if i < last_index {
985                self.write_symbol(",");
986            }
987        }
988
989        self.write_token(&tokens.closing_brace);
990    }
991
992    fn write_table_property_modifier(
993        &mut self,
994        modifier: Option<&TablePropertyModifier>,
995        token: Option<&Token>,
996    ) {
997        if let Some(modifier) = modifier {
998            if let Some(token) = token {
999                self.write_token(token);
1000            } else {
1001                match modifier {
1002                    TablePropertyModifier::Read => self.write_symbol("read"),
1003                    TablePropertyModifier::Write => self.write_symbol("write"),
1004                }
1005            }
1006        }
1007    }
1008
1009    fn write_table_indexer_type_with_tokens(
1010        &mut self,
1011        indexer_type: &TableIndexerType,
1012        tokens: &TableIndexTypeTokens,
1013    ) {
1014        self.write_table_property_modifier(
1015            indexer_type.get_modifier(),
1016            indexer_type
1017                .get_tokens()
1018                .and_then(|tokens| tokens.modifier.as_ref()),
1019        );
1020
1021        self.write_token(&tokens.opening_bracket);
1022
1023        let key_type = indexer_type.get_key_type();
1024
1025        let need_parentheses = matches!(
1026            key_type,
1027            Type::Optional(_) | Type::Intersection(_) | Type::Union(_)
1028        );
1029
1030        if need_parentheses {
1031            self.write_symbol("(");
1032            self.write_type(key_type);
1033            self.write_symbol(")");
1034        } else {
1035            self.write_type(key_type);
1036        }
1037
1038        self.write_token(&tokens.closing_bracket);
1039        self.write_token(&tokens.colon);
1040        self.write_type(indexer_type.get_value_type());
1041    }
1042
1043    fn write_table_literal_property_type_with_tokens(
1044        &mut self,
1045        property: &TableLiteralPropertyType,
1046        tokens: &TableIndexTypeTokens,
1047    ) {
1048        self.write_table_property_modifier(
1049            property.get_modifier(),
1050            property
1051                .get_tokens()
1052                .and_then(|tokens| tokens.modifier.as_ref()),
1053        );
1054
1055        self.write_token(&tokens.opening_bracket);
1056        self.write_string_type(property.get_string());
1057        self.write_token(&tokens.closing_bracket);
1058        self.write_token(&tokens.colon);
1059        self.write_type(property.get_type());
1060    }
1061
1062    fn write_expression_type_with_tokens(
1063        &mut self,
1064        expression_type: &ExpressionType,
1065        tokens: &ExpressionTypeTokens,
1066    ) {
1067        self.write_token(&tokens.r#typeof);
1068        self.write_token(&tokens.opening_parenthese);
1069        self.write_expression(expression_type.get_expression());
1070        self.write_token(&tokens.closing_parenthese);
1071    }
1072
1073    fn write_parenthese_type_with_tokens(
1074        &mut self,
1075        parenthese_type: &ParentheseType,
1076        tokens: &ParentheseTypeTokens,
1077    ) {
1078        self.write_token(&tokens.left_parenthese);
1079        self.write_type(parenthese_type.get_inner_type());
1080        self.write_token(&tokens.right_parenthese);
1081    }
1082
1083    fn write_function_type_with_tokens(
1084        &mut self,
1085        function_type: &FunctionType,
1086        tokens: &FunctionTypeTokens,
1087    ) {
1088        if let Some(generic_parameters) = function_type.get_generic_parameters() {
1089            self.write_function_generics(generic_parameters);
1090        }
1091
1092        self.write_token(&tokens.opening_parenthese);
1093
1094        let argument_len = function_type.argument_len();
1095        let last_index = argument_len.saturating_sub(1);
1096
1097        for (i, argument) in function_type.iter_arguments().enumerate() {
1098            if let Some(name) = argument.get_name() {
1099                self.write_identifier(name);
1100
1101                if let Some(token) = argument.get_token() {
1102                    self.write_token(token);
1103                } else {
1104                    self.write_symbol(":");
1105                }
1106            }
1107
1108            self.write_type(argument.get_type());
1109
1110            if i < last_index {
1111                if let Some(comma) = tokens.commas.get(i) {
1112                    self.write_token(comma);
1113                } else {
1114                    self.write_symbol(",");
1115                }
1116            }
1117        }
1118
1119        if let Some(variadic_argument_type) = function_type.get_variadic_argument_type() {
1120            if argument_len > 0 {
1121                if let Some(comma) = tokens.commas.get(argument_len) {
1122                    self.write_token(comma);
1123                } else {
1124                    self.write_symbol(",");
1125                }
1126            }
1127            self.write_variadic_argument_type(variadic_argument_type);
1128        }
1129
1130        self.write_token(&tokens.closing_parenthese);
1131        self.write_token(&tokens.arrow);
1132        self.write_function_return_type(function_type.get_return_type());
1133    }
1134
1135    fn write_function_generics(&mut self, generic_parameters: &GenericParameters) {
1136        if generic_parameters.is_empty() {
1137            return;
1138        }
1139        if let Some(generic_tokens) = generic_parameters.get_tokens() {
1140            self.write_generic_parameters_with_tokens(generic_parameters, generic_tokens);
1141        } else {
1142            self.write_generic_parameters_with_tokens(
1143                generic_parameters,
1144                &self.generate_generic_parameters_tokens(generic_parameters),
1145            );
1146        }
1147    }
1148
1149    fn write_generic_parameters_with_tokens(
1150        &mut self,
1151        generic_parameters: &GenericParameters,
1152        tokens: &GenericParametersTokens,
1153    ) {
1154        self.write_token(&tokens.opening_list);
1155
1156        let last_index = generic_parameters.len().saturating_sub(1);
1157
1158        for (i, type_variable) in generic_parameters.iter_type_variable().enumerate() {
1159            self.write_identifier(type_variable);
1160
1161            if i < last_index {
1162                if let Some(comma) = tokens.commas.get(i) {
1163                    self.write_token(comma);
1164                } else {
1165                    self.write_symbol(",");
1166                }
1167            }
1168        }
1169
1170        let type_variables_len = generic_parameters.type_variables_len();
1171
1172        for (i, generic_type_pack) in generic_parameters.iter_generic_type_pack().enumerate() {
1173            self.write_generic_type_pack(generic_type_pack);
1174
1175            if (i + type_variables_len) < last_index {
1176                if let Some(comma) = tokens.commas.get(i) {
1177                    self.write_token(comma);
1178                } else {
1179                    self.write_symbol(",");
1180                }
1181            }
1182        }
1183
1184        self.write_token(&tokens.closing_list);
1185    }
1186
1187    fn write_type_pack_with_tokens(&mut self, type_pack: &TypePack, tokens: &TypePackTokens) {
1188        self.write_token(&tokens.left_parenthese);
1189
1190        let last_index = type_pack
1191            .len()
1192            .saturating_sub(if type_pack.has_variadic_type() { 0 } else { 1 });
1193
1194        for (i, r#type) in type_pack.iter().enumerate() {
1195            self.write_type(r#type);
1196
1197            if i < last_index {
1198                if let Some(comma) = tokens.commas.get(i) {
1199                    self.write_token(comma);
1200                } else {
1201                    self.write_symbol(",");
1202                }
1203            }
1204        }
1205
1206        if let Some(variadic_argument_type) = type_pack.get_variadic_type() {
1207            self.write_variadic_argument_type(variadic_argument_type);
1208        }
1209
1210        self.write_token(&tokens.right_parenthese);
1211    }
1212
1213    fn write_optional_type_with_token(&mut self, optional: &OptionalType, token: &Token) {
1214        let inner_type = optional.get_inner_type();
1215        if OptionalType::needs_parentheses(inner_type) {
1216            self.write_symbol("(");
1217            self.write_type(inner_type);
1218            self.write_symbol(")");
1219        } else {
1220            self.write_type(inner_type);
1221        }
1222        self.write_token(token);
1223    }
1224
1225    fn write_intersection_type_with_token(
1226        &mut self,
1227        intersection: &IntersectionType,
1228        tokens: &IntersectionTypeTokens,
1229    ) {
1230        let length = intersection.len();
1231        let last_index = length.saturating_sub(1);
1232
1233        for (i, r#type) in intersection.iter_types().enumerate() {
1234            if i == 0 {
1235                if let Some(leading) = &tokens.leading_token {
1236                    self.write_token(leading);
1237                }
1238            } else if let Some(token) = tokens.separators.get(i.saturating_sub(1)) {
1239                self.write_token(token);
1240            } else {
1241                self.write_symbol("&");
1242            }
1243
1244            let need_parentheses = if i == last_index {
1245                IntersectionType::last_needs_parentheses(r#type)
1246            } else {
1247                IntersectionType::intermediate_needs_parentheses(r#type)
1248            };
1249
1250            if need_parentheses {
1251                self.write_symbol("(");
1252                self.write_type(r#type);
1253                self.write_symbol(")");
1254            } else {
1255                self.write_type(r#type);
1256            }
1257        }
1258    }
1259
1260    fn write_union_type_with_token(&mut self, union: &UnionType, tokens: &UnionTypeTokens) {
1261        let length = union.len();
1262        let last_index = length.saturating_sub(1);
1263
1264        for (i, r#type) in union.iter_types().enumerate() {
1265            if i == 0 {
1266                if let Some(leading) = &tokens.leading_token {
1267                    self.write_token(leading);
1268                }
1269            } else if let Some(token) = tokens.separators.get(i.saturating_sub(1)) {
1270                self.write_token(token);
1271            } else {
1272                self.write_symbol("|");
1273            }
1274
1275            let need_parentheses = if i == last_index {
1276                UnionType::last_needs_parentheses(r#type)
1277            } else {
1278                UnionType::intermediate_needs_parentheses(r#type)
1279            };
1280
1281            if need_parentheses {
1282                self.write_symbol("(");
1283                self.write_type(r#type);
1284                self.write_symbol(")");
1285            } else {
1286                self.write_type(r#type);
1287            }
1288        }
1289    }
1290
1291    fn write_interpolated_string_with_tokens(
1292        &mut self,
1293        interpolated_string: &InterpolatedStringExpression,
1294        tokens: &InterpolatedStringTokens,
1295    ) {
1296        self.write_token(&tokens.opening_tick);
1297
1298        for segment in interpolated_string.iter_segments() {
1299            match segment {
1300                InterpolationSegment::String(string_segment) => {
1301                    if let Some(token) = string_segment.get_token() {
1302                        self.write_token(token);
1303                    } else {
1304                        self.write_symbol(&utils::write_interpolated_string_segment(string_segment))
1305                    }
1306                }
1307                InterpolationSegment::Value(value) => {
1308                    if let Some(tokens) = value.get_tokens() {
1309                        self.write_string_value_segment_with_tokens(value, tokens);
1310                    } else {
1311                        self.write_string_value_segment_with_tokens(
1312                            value,
1313                            &self.generate_string_value_segment_tokens(value),
1314                        );
1315                    }
1316                }
1317            }
1318        }
1319
1320        self.write_token(&tokens.closing_tick);
1321    }
1322
1323    fn write_string_value_segment_with_tokens(
1324        &mut self,
1325        value: &ValueSegment,
1326        tokens: &ValueSegmentTokens,
1327    ) {
1328        self.write_token(&tokens.opening_brace);
1329        let expression = value.get_expression();
1330        if self.output.ends_with('{') {
1331            if let Some(table) = utils::starts_with_table(expression) {
1332                if table
1333                    .get_tokens()
1334                    .and_then(|tokens| {
1335                        tokens
1336                            .opening_brace
1337                            .iter_leading_trivia()
1338                            .next()
1339                            .filter(|trivia| !trivia.read(self.original_code).is_empty())
1340                    })
1341                    .is_none()
1342                {
1343                    self.output.push(' ');
1344                }
1345            }
1346        }
1347        self.write_expression(expression);
1348        self.write_token(&tokens.closing_brace);
1349    }
1350
1351    fn generate_block_tokens(&self, _block: &Block) -> BlockTokens {
1352        BlockTokens {
1353            semicolons: Vec::new(),
1354            last_semicolon: None,
1355            final_token: None,
1356        }
1357    }
1358
1359    fn generate_assign_tokens(&self, assign: &AssignStatement) -> AssignTokens {
1360        AssignTokens {
1361            equal: Token::from_content("="),
1362            variable_commas: intersect_with_token(comma_token(), assign.variables_len()),
1363            value_commas: intersect_with_token(comma_token(), assign.values_len()),
1364        }
1365    }
1366
1367    fn generate_do_tokens(&self, _do_statement: &DoStatement) -> DoTokens {
1368        DoTokens {
1369            r#do: Token::from_content("do"),
1370            end: Token::from_content("end"),
1371        }
1372    }
1373
1374    fn generate_compound_assign_tokens(
1375        &self,
1376        assign: &CompoundAssignStatement,
1377    ) -> CompoundAssignTokens {
1378        CompoundAssignTokens {
1379            operator: Token::from_content(assign.get_operator().to_str()),
1380        }
1381    }
1382
1383    fn generate_generic_for_tokens(&self, generic_for: &GenericForStatement) -> GenericForTokens {
1384        GenericForTokens {
1385            r#for: Token::from_content("for"),
1386            r#in: Token::from_content("in"),
1387            r#do: Token::from_content("do"),
1388            end: Token::from_content("end"),
1389            identifier_commas: intersect_with_token(comma_token(), generic_for.identifiers_len()),
1390            value_commas: intersect_with_token(comma_token(), generic_for.expressions_len()),
1391        }
1392    }
1393
1394    fn generate_if_statement_tokens(&self, if_statement: &IfStatement) -> IfStatementTokens {
1395        IfStatementTokens {
1396            r#if: Token::from_content("if"),
1397            then: Token::from_content("then"),
1398            end: Token::from_content("end"),
1399            r#else: if_statement
1400                .get_else_block()
1401                .map(|_| Token::from_content("else")),
1402        }
1403    }
1404
1405    fn generate_if_branch_tokens(&self, _branch: &IfBranch) -> IfBranchTokens {
1406        IfBranchTokens {
1407            elseif: Token::from_content("elseif"),
1408            then: Token::from_content("then"),
1409        }
1410    }
1411
1412    fn generate_function_statement_tokens(
1413        &self,
1414        function: &FunctionStatement,
1415    ) -> FunctionBodyTokens {
1416        FunctionBodyTokens {
1417            function: Token::from_content("function"),
1418            opening_parenthese: Token::from_content("("),
1419            closing_parenthese: Token::from_content(")"),
1420            end: Token::from_content("end"),
1421            parameter_commas: intersect_with_token(
1422                comma_token(),
1423                function.parameters_count() + usize::from(function.is_variadic()),
1424            ),
1425            variable_arguments: if function.is_variadic() {
1426                Some(Token::from_content("..."))
1427            } else {
1428                None
1429            },
1430            variable_arguments_colon: if function.has_variadic_type() {
1431                Some(Token::from_content(":"))
1432            } else {
1433                None
1434            },
1435            return_type_colon: if function.has_return_type() {
1436                Some(Token::from_content(":"))
1437            } else {
1438                None
1439            },
1440        }
1441    }
1442
1443    fn generate_function_name_tokens(&self, name: &FunctionName) -> FunctionNameTokens {
1444        FunctionNameTokens {
1445            periods: iter::repeat_with(|| Token::from_content("."))
1446                .take(name.get_field_names().len())
1447                .collect(),
1448            colon: name.get_method().map(|_| Token::from_content(":")),
1449        }
1450    }
1451
1452    fn generate_return_tokens(&self, return_statement: &ReturnStatement) -> ReturnTokens {
1453        ReturnTokens {
1454            r#return: Token::from_content("return")
1455                .with_trailing_trivia(TriviaKind::Whitespace.with_content(" ")),
1456            commas: intersect_with_token(comma_token(), return_statement.len()),
1457        }
1458    }
1459
1460    fn generate_local_assign_tokens(&self, assign: &LocalAssignStatement) -> LocalAssignTokens {
1461        LocalAssignTokens {
1462            local: Token::from_content("local"),
1463            equal: if assign.has_values() {
1464                Some(Token::from_content("="))
1465            } else {
1466                None
1467            },
1468            variable_commas: intersect_with_token(comma_token(), assign.variables_len()),
1469            value_commas: intersect_with_token(comma_token(), assign.values_len()),
1470        }
1471    }
1472
1473    fn generate_local_function_tokens(
1474        &self,
1475        function: &LocalFunctionStatement,
1476    ) -> LocalFunctionTokens {
1477        LocalFunctionTokens {
1478            local: Token::from_content("local"),
1479            function_body: FunctionBodyTokens {
1480                function: Token::from_content("function"),
1481                opening_parenthese: Token::from_content("("),
1482                closing_parenthese: Token::from_content(")"),
1483                end: Token::from_content("end"),
1484                parameter_commas: intersect_with_token(
1485                    comma_token(),
1486                    function.parameters_count() + usize::from(function.is_variadic()),
1487                ),
1488                variable_arguments: if function.is_variadic() {
1489                    Some(Token::from_content("..."))
1490                } else {
1491                    None
1492                },
1493                variable_arguments_colon: if function.has_variadic_type() {
1494                    Some(Token::from_content(":"))
1495                } else {
1496                    None
1497                },
1498                return_type_colon: if function.has_return_type() {
1499                    Some(Token::from_content(":"))
1500                } else {
1501                    None
1502                },
1503            },
1504        }
1505    }
1506
1507    fn generate_numeric_for_tokens(&self, numeric_for: &NumericForStatement) -> NumericForTokens {
1508        NumericForTokens {
1509            r#for: Token::from_content("for"),
1510            equal: Token::from_content("="),
1511            r#do: Token::from_content("do"),
1512            end: Token::from_content("end"),
1513            end_comma: Token::from_content(","),
1514            step_comma: numeric_for.get_step().map(|_| Token::from_content(",")),
1515        }
1516    }
1517
1518    fn generate_repeat_tokens(&self, _repeat: &RepeatStatement) -> RepeatTokens {
1519        RepeatTokens {
1520            repeat: Token::from_content("repeat"),
1521            until: Token::from_content("until"),
1522        }
1523    }
1524
1525    fn generate_while_tokens(&self, _while_statement: &WhileStatement) -> WhileTokens {
1526        WhileTokens {
1527            r#while: Token::from_content("while"),
1528            r#do: Token::from_content("do"),
1529            end: Token::from_content("end"),
1530        }
1531    }
1532
1533    fn generate_type_declaration_tokens(
1534        &self,
1535        statement: &TypeDeclarationStatement,
1536    ) -> TypeDeclarationTokens {
1537        TypeDeclarationTokens {
1538            r#type: Token::from_content("type"),
1539            equal: Token::from_content("="),
1540            export: statement
1541                .is_exported()
1542                .then(|| Token::from_content("export")),
1543        }
1544    }
1545
1546    fn generate_type_function_tokens(
1547        &self,
1548        statement: &TypeFunctionStatement,
1549    ) -> TypeFunctionStatementTokens {
1550        TypeFunctionStatementTokens {
1551            r#type: Token::from_content("type"),
1552            export: statement
1553                .is_exported()
1554                .then(|| Token::from_content("export")),
1555            function_body: FunctionBodyTokens {
1556                function: Token::from_content("function"),
1557                opening_parenthese: Token::from_content("("),
1558                closing_parenthese: Token::from_content(")"),
1559                end: Token::from_content("end"),
1560                parameter_commas: intersect_with_token(
1561                    comma_token(),
1562                    statement.parameters_count() + usize::from(statement.is_variadic()),
1563                ),
1564                variable_arguments: statement.is_variadic().then(|| Token::from_content("...")),
1565                variable_arguments_colon: statement
1566                    .has_variadic_type()
1567                    .then(|| Token::from_content(":")),
1568                return_type_colon: statement
1569                    .has_return_type()
1570                    .then(|| Token::from_content(":")),
1571            },
1572        }
1573    }
1574
1575    fn generate_function_tokens(&self, function: &FunctionExpression) -> FunctionBodyTokens {
1576        FunctionBodyTokens {
1577            function: Token::from_content("function"),
1578            opening_parenthese: Token::from_content("("),
1579            closing_parenthese: Token::from_content(")"),
1580            end: Token::from_content("end"),
1581            parameter_commas: intersect_with_token(
1582                comma_token(),
1583                function.parameters_count() + usize::from(function.is_variadic()),
1584            ),
1585            variable_arguments: if function.is_variadic() {
1586                Some(Token::from_content("..."))
1587            } else {
1588                None
1589            },
1590            variable_arguments_colon: if function.has_variadic_type() {
1591                Some(Token::from_content(":"))
1592            } else {
1593                None
1594            },
1595            return_type_colon: if function.has_return_type() {
1596                Some(Token::from_content(":"))
1597            } else {
1598                None
1599            },
1600        }
1601    }
1602
1603    fn generate_function_call_tokens(&self, call: &FunctionCall) -> FunctionCallTokens {
1604        FunctionCallTokens {
1605            colon: call.get_method().map(|_| Token::from_content(":")),
1606        }
1607    }
1608
1609    fn generate_field_token(&self, _field: &FieldExpression) -> Token {
1610        Token::from_content(".")
1611    }
1612
1613    fn generate_index_tokens(&self, _index: &IndexExpression) -> IndexExpressionTokens {
1614        IndexExpressionTokens {
1615            opening_bracket: Token::from_content("["),
1616            closing_bracket: Token::from_content("]"),
1617        }
1618    }
1619
1620    fn generate_if_tokens(&self, _if_expression: &IfExpression) -> IfExpressionTokens {
1621        IfExpressionTokens {
1622            r#if: Token::from_content("if"),
1623            then: Token::from_content("then"),
1624            r#else: Token::from_content("else"),
1625        }
1626    }
1627
1628    fn generate_if_expression_branch_tokens(
1629        &self,
1630        _branch: &ElseIfExpressionBranch,
1631    ) -> ElseIfExpressionBranchTokens {
1632        ElseIfExpressionBranchTokens {
1633            elseif: Token::from_content("elseif"),
1634            then: Token::from_content("then"),
1635        }
1636    }
1637
1638    fn generate_table_tokens(&self, table: &TableExpression) -> TableTokens {
1639        TableTokens {
1640            opening_brace: Token::from_content("{"),
1641            closing_brace: Token::from_content("}"),
1642            separators: intersect_with_token(comma_token(), table.len()),
1643        }
1644    }
1645
1646    fn generate_table_field_tokens(&self, _entry: &TableFieldEntry) -> Token {
1647        Token::from_content("=")
1648    }
1649
1650    fn generate_table_index_tokens(&self, _entry: &TableIndexEntry) -> TableIndexEntryTokens {
1651        TableIndexEntryTokens {
1652            opening_bracket: Token::from_content("["),
1653            closing_bracket: Token::from_content("]"),
1654            equal: Token::from_content("="),
1655        }
1656    }
1657
1658    fn generate_tuple_arguments_tokens(&self, arguments: &TupleArguments) -> TupleArgumentsTokens {
1659        TupleArgumentsTokens {
1660            opening_parenthese: Token::from_content("("),
1661            closing_parenthese: Token::from_content(")"),
1662            commas: intersect_with_token(comma_token(), arguments.len()),
1663        }
1664    }
1665
1666    fn generate_parenthese_tokens(&self, _parenthese: &ParentheseExpression) -> ParentheseTokens {
1667        ParentheseTokens {
1668            left_parenthese: Token::from_content("("),
1669            right_parenthese: Token::from_content(")"),
1670        }
1671    }
1672
1673    fn generate_type_cast_token(&self, _type_cast: &TypeCastExpression) -> Token {
1674        Token::from_content("::")
1675    }
1676
1677    fn generate_type_parameters_tokens(&self, parameters: &TypeParameters) -> TypeParametersTokens {
1678        TypeParametersTokens {
1679            opening_list: Token::from_content("<"),
1680            closing_list: Token::from_content(">"),
1681            commas: intersect_with_token(comma_token(), parameters.len()),
1682        }
1683    }
1684
1685    fn generate_type_field_token(&self, _type_field: &TypeField) -> Token {
1686        Token::from_content(".")
1687    }
1688
1689    fn generate_array_type_tokens(&self, _array: &ArrayType) -> ArrayTypeTokens {
1690        ArrayTypeTokens {
1691            opening_brace: Token::from_content("{"),
1692            closing_brace: Token::from_content("}"),
1693        }
1694    }
1695
1696    fn generate_table_type_tokens(&self, table_type: &TableType) -> TableTypeTokens {
1697        TableTypeTokens {
1698            opening_brace: Token::from_content("{"),
1699            closing_brace: Token::from_content("}"),
1700            separators: intersect_with_token(comma_token(), table_type.len()),
1701        }
1702    }
1703
1704    fn generate_table_indexer_type_tokens(&self) -> TableIndexTypeTokens {
1705        TableIndexTypeTokens {
1706            opening_bracket: Token::from_content("["),
1707            closing_bracket: Token::from_content("]"),
1708            colon: Token::from_content(":"),
1709            modifier: None,
1710        }
1711    }
1712
1713    fn generate_expression_type_tokens(
1714        &self,
1715        _expression_type: &ExpressionType,
1716    ) -> ExpressionTypeTokens {
1717        ExpressionTypeTokens {
1718            r#typeof: Token::from_content("typeof"),
1719            opening_parenthese: Token::from_content("("),
1720            closing_parenthese: Token::from_content(")"),
1721        }
1722    }
1723
1724    fn generate_parenthese_type_tokens(
1725        &self,
1726        _parenthese_type: &ParentheseType,
1727    ) -> ParentheseTypeTokens {
1728        ParentheseTypeTokens {
1729            left_parenthese: Token::from_content("("),
1730            right_parenthese: Token::from_content(")"),
1731        }
1732    }
1733
1734    fn generate_function_type_tokens(&self, function_type: &FunctionType) -> FunctionTypeTokens {
1735        FunctionTypeTokens {
1736            opening_parenthese: Token::from_content("("),
1737            closing_parenthese: Token::from_content(")"),
1738            arrow: Token::from_content("->"),
1739            commas: intersect_with_token(
1740                comma_token(),
1741                function_type.argument_len()
1742                    + usize::from(function_type.has_variadic_argument_type()),
1743            ),
1744        }
1745    }
1746
1747    fn generate_optional_type_token(&self, _optional: &OptionalType) -> Token {
1748        Token::from_content("?")
1749    }
1750
1751    fn generate_intersection_type_token(
1752        &self,
1753        intersection: &IntersectionType,
1754    ) -> IntersectionTypeTokens {
1755        IntersectionTypeTokens {
1756            leading_token: intersection
1757                .has_leading_token()
1758                .then(|| Token::from_content("&")),
1759            separators: intersect_with_token(Token::from_content("&"), intersection.len()),
1760        }
1761    }
1762
1763    fn generate_union_type_token(&self, union: &UnionType) -> UnionTypeTokens {
1764        UnionTypeTokens {
1765            leading_token: union.has_leading_token().then(|| Token::from_content("|")),
1766            separators: intersect_with_token(Token::from_content("|"), union.len()),
1767        }
1768    }
1769
1770    fn generate_type_pack_tokens(&self, type_pack: &TypePack) -> TypePackTokens {
1771        TypePackTokens {
1772            left_parenthese: Token::from_content("("),
1773            right_parenthese: Token::from_content(")"),
1774            commas: intersect_with_token(
1775                comma_token(),
1776                type_pack.len() + usize::from(type_pack.has_variadic_type()),
1777            ),
1778        }
1779    }
1780
1781    fn generate_generic_parameters_tokens(
1782        &self,
1783        generic_parameters: &GenericParameters,
1784    ) -> GenericParametersTokens {
1785        GenericParametersTokens {
1786            opening_list: Token::from_content("<"),
1787            closing_list: Token::from_content(">"),
1788            commas: intersect_with_token(comma_token(), generic_parameters.len()),
1789        }
1790    }
1791
1792    fn generate_generic_parameters_with_defaults_tokens(
1793        &self,
1794        generic_parameters: &GenericParametersWithDefaults,
1795    ) -> GenericParametersTokens {
1796        GenericParametersTokens {
1797            opening_list: Token::from_content("<"),
1798            closing_list: Token::from_content(">"),
1799            commas: intersect_with_token(comma_token(), generic_parameters.len()),
1800        }
1801    }
1802
1803    fn generate_interpolated_string_tokens(
1804        &self,
1805        _interpolated_string: &InterpolatedStringExpression,
1806    ) -> InterpolatedStringTokens {
1807        InterpolatedStringTokens {
1808            opening_tick: Token::from_content("`"),
1809            closing_tick: Token::from_content("`"),
1810        }
1811    }
1812
1813    fn generate_string_value_segment_tokens(
1814        &self,
1815        _value_segment: &ValueSegment,
1816    ) -> ValueSegmentTokens {
1817        ValueSegmentTokens {
1818            opening_brace: Token::from_content("{"),
1819            closing_brace: Token::from_content("}"),
1820        }
1821    }
1822
1823    fn generate_named_attribute_token(&self, _named: &NamedAttribute) -> Token {
1824        Token::from_content("@")
1825    }
1826
1827    fn generate_attribute_group_tokens(&self, group: &AttributeGroup) -> AttributeGroupTokens {
1828        AttributeGroupTokens {
1829            opening_attribute_list: Token::from_content("@["),
1830            closing_bracket: Token::from_content("]"),
1831            separators: intersect_with_token(comma_token(), group.len()),
1832        }
1833    }
1834
1835    fn generate_literal_table_tokens(&self, table: &LiteralTable) -> TableTokens {
1836        TableTokens {
1837            opening_brace: Token::from_content("{"),
1838            closing_brace: Token::from_content("}"),
1839            separators: intersect_with_token(comma_token(), table.len()),
1840        }
1841    }
1842
1843    fn generate_literal_table_field_token(&self, _field: &LiteralTableFieldEntry) -> Token {
1844        Token::from_content("=")
1845    }
1846
1847    fn generate_attribute_tuple_arguments_tokens(
1848        &self,
1849        tuple: &AttributeTupleArguments,
1850    ) -> TupleArgumentsTokens {
1851        TupleArgumentsTokens {
1852            opening_parenthese: Token::from_content("("),
1853            closing_parenthese: Token::from_content(")"),
1854            commas: intersect_with_token(comma_token(), tuple.len()),
1855        }
1856    }
1857
1858    fn write_symbol(&mut self, symbol: &str) {
1859        if self.currently_commenting {
1860            self.uncomment();
1861        } else if self.needs_space(symbol.chars().next().expect("symbol cannot be empty")) {
1862            self.output.push(' ');
1863        }
1864        self.push_str(symbol);
1865    }
1866
1867    fn write_symbol_without_space_check(&mut self, symbol: &str) {
1868        if self.currently_commenting {
1869            self.uncomment();
1870        }
1871        self.push_str(symbol);
1872    }
1873
1874    fn write_typed_identifier(&mut self, typed_identifier: &TypedIdentifier) {
1875        if let Some(token) = typed_identifier.get_token() {
1876            let name_in_token = token.read(self.original_code);
1877
1878            if name_in_token == typed_identifier.get_name() {
1879                self.write_token(token);
1880            } else {
1881                let mut new_token = token.clone();
1882                new_token.replace_with_content(typed_identifier.get_name().clone());
1883                self.write_token(&new_token);
1884            }
1885        } else {
1886            let name = typed_identifier.get_name();
1887            self.write_symbol(name);
1888        }
1889
1890        if let Some(r#type) = typed_identifier.get_type() {
1891            if let Some(colon) = typed_identifier.get_colon_token() {
1892                self.write_token(colon);
1893            } else {
1894                self.write_symbol(":");
1895            }
1896            self.write_type(r#type);
1897        }
1898    }
1899
1900    #[inline]
1901    fn needs_space(&self, next_character: char) -> bool {
1902        if let Some(last) = self.output.chars().last() {
1903            utils::should_break_with_space(last, next_character)
1904        } else {
1905            false
1906        }
1907    }
1908
1909    #[inline]
1910    fn uncomment(&mut self) {
1911        self.output.push('\n');
1912        self.current_line += 1;
1913        self.currently_commenting = false;
1914    }
1915}
1916
1917fn is_single_line_comment(content: &str) -> bool {
1918    let is_multiline_comment = content.starts_with("--[") && {
1919        if let Some((closing_bracket_index, _)) =
1920            content.chars().skip(3).enumerate().find(|(_, c)| *c == '[')
1921        {
1922            content
1923                .get(3..closing_bracket_index)
1924                .map(|substring| substring.chars().all(|c| c == '='))
1925                .unwrap_or(true)
1926        } else {
1927            false
1928        }
1929    };
1930
1931    !is_multiline_comment
1932}
1933
1934#[inline]
1935fn comma_token() -> Token {
1936    Token::from_content(",").with_trailing_trivia(TriviaKind::Whitespace.with_content(" "))
1937}
1938
1939impl LuaGenerator for TokenBasedLuaGenerator<'_> {
1940    fn into_string(self) -> String {
1941        self.output
1942    }
1943
1944    fn write_block(&mut self, block: &Block) {
1945        if let Some(tokens) = block.get_tokens() {
1946            self.write_block_with_tokens(block, tokens);
1947        } else {
1948            self.write_block_with_tokens(block, &self.generate_block_tokens(block));
1949        }
1950    }
1951
1952    fn write_assign_statement(&mut self, assign: &AssignStatement) {
1953        if let Some(tokens) = assign.get_tokens() {
1954            self.write_assign_with_tokens(assign, tokens);
1955        } else {
1956            self.write_assign_with_tokens(assign, &self.generate_assign_tokens(assign));
1957        }
1958    }
1959
1960    fn write_do_statement(&mut self, do_statement: &DoStatement) {
1961        if let Some(tokens) = do_statement.get_tokens() {
1962            self.write_do_with_tokens(do_statement, tokens);
1963        } else {
1964            self.write_do_with_tokens(do_statement, &self.generate_do_tokens(do_statement));
1965        }
1966    }
1967
1968    fn write_compound_assign(&mut self, assign: &CompoundAssignStatement) {
1969        if let Some(tokens) = assign.get_tokens() {
1970            self.write_compound_assign_with_tokens(assign, tokens);
1971        } else {
1972            self.write_compound_assign_with_tokens(
1973                assign,
1974                &self.generate_compound_assign_tokens(assign),
1975            );
1976        }
1977    }
1978
1979    fn write_generic_for(&mut self, generic_for: &GenericForStatement) {
1980        if let Some(tokens) = generic_for.get_tokens() {
1981            self.write_generic_for_with_tokens(generic_for, tokens);
1982        } else {
1983            self.write_generic_for_with_tokens(
1984                generic_for,
1985                &self.generate_generic_for_tokens(generic_for),
1986            );
1987        }
1988    }
1989
1990    fn write_if_statement(&mut self, if_statement: &IfStatement) {
1991        if let Some(tokens) = if_statement.get_tokens() {
1992            self.write_if_statement_with_tokens(if_statement, tokens);
1993        } else {
1994            self.write_if_statement_with_tokens(
1995                if_statement,
1996                &self.generate_if_statement_tokens(if_statement),
1997            );
1998        }
1999    }
2000
2001    fn write_function_statement(&mut self, function: &FunctionStatement) {
2002        if let Some(tokens) = function.get_tokens() {
2003            self.write_function_statement_with_tokens(function, tokens);
2004        } else {
2005            self.write_function_statement_with_tokens(
2006                function,
2007                &self.generate_function_statement_tokens(function),
2008            );
2009        }
2010    }
2011
2012    fn write_last_statement(&mut self, statement: &LastStatement) {
2013        match statement {
2014            LastStatement::Break(token) => {
2015                if let Some(token) = token {
2016                    self.write_token(token);
2017                } else {
2018                    self.write_symbol("break");
2019                }
2020            }
2021            LastStatement::Continue(token) => {
2022                if let Some(token) = token {
2023                    self.write_token(token);
2024                } else {
2025                    self.write_symbol("continue");
2026                }
2027            }
2028            LastStatement::Return(return_statement) => {
2029                if let Some(tokens) = return_statement.get_tokens() {
2030                    self.write_return_with_tokens(return_statement, tokens);
2031                } else {
2032                    self.write_return_with_tokens(
2033                        return_statement,
2034                        &self.generate_return_tokens(return_statement),
2035                    );
2036                }
2037            }
2038        }
2039    }
2040
2041    fn write_local_assign(&mut self, assign: &LocalAssignStatement) {
2042        if let Some(tokens) = assign.get_tokens() {
2043            self.write_local_assign_with_tokens(assign, tokens);
2044        } else {
2045            self.write_local_assign_with_tokens(assign, &self.generate_local_assign_tokens(assign));
2046        }
2047    }
2048
2049    fn write_local_function(&mut self, function: &LocalFunctionStatement) {
2050        if let Some(tokens) = function.get_tokens() {
2051            self.write_local_function_with_tokens(function, tokens);
2052        } else {
2053            self.write_local_function_with_tokens(
2054                function,
2055                &self.generate_local_function_tokens(function),
2056            );
2057        }
2058    }
2059
2060    fn write_numeric_for(&mut self, numeric_for: &NumericForStatement) {
2061        if let Some(tokens) = numeric_for.get_tokens() {
2062            self.write_numeric_for_with_tokens(numeric_for, tokens);
2063        } else {
2064            self.write_numeric_for_with_tokens(
2065                numeric_for,
2066                &self.generate_numeric_for_tokens(numeric_for),
2067            );
2068        }
2069    }
2070
2071    fn write_repeat_statement(&mut self, repeat: &RepeatStatement) {
2072        if let Some(tokens) = repeat.get_tokens() {
2073            self.write_repeat_with_tokens(repeat, tokens);
2074        } else {
2075            self.write_repeat_with_tokens(repeat, &self.generate_repeat_tokens(repeat));
2076        }
2077    }
2078
2079    fn write_while_statement(&mut self, while_statement: &WhileStatement) {
2080        if let Some(tokens) = while_statement.get_tokens() {
2081            self.write_while_with_tokens(while_statement, tokens);
2082        } else {
2083            self.write_while_with_tokens(
2084                while_statement,
2085                &self.generate_while_tokens(while_statement),
2086            );
2087        }
2088    }
2089
2090    fn write_type_declaration_statement(&mut self, statement: &TypeDeclarationStatement) {
2091        if let Some(tokens) = statement.get_tokens() {
2092            self.write_type_declaration_with_tokens(statement, tokens);
2093        } else {
2094            self.write_type_declaration_with_tokens(
2095                statement,
2096                &self.generate_type_declaration_tokens(statement),
2097            );
2098        }
2099    }
2100
2101    fn write_type_function_statement(&mut self, statement: &TypeFunctionStatement) {
2102        if let Some(tokens) = statement.get_tokens() {
2103            self.write_type_function_with_tokens(statement, tokens);
2104        } else {
2105            self.write_type_function_with_tokens(
2106                statement,
2107                &self.generate_type_function_tokens(statement),
2108            );
2109        }
2110    }
2111
2112    fn write_false_expression(&mut self, token: &Option<Token>) {
2113        if let Some(token) = token {
2114            self.write_token(token);
2115        } else {
2116            self.write_symbol("false");
2117        }
2118    }
2119
2120    fn write_true_expression(&mut self, token: &Option<Token>) {
2121        if let Some(token) = token {
2122            self.write_token(token);
2123        } else {
2124            self.write_symbol("true");
2125        }
2126    }
2127
2128    fn write_nil_expression(&mut self, token: &Option<Token>) {
2129        if let Some(token) = token {
2130            self.write_token(token);
2131        } else {
2132            self.write_symbol("nil");
2133        }
2134    }
2135
2136    fn write_variable_arguments_expression(&mut self, token: &Option<Token>) {
2137        if let Some(token) = token {
2138            self.write_token(token);
2139        } else {
2140            self.write_symbol("...");
2141        }
2142    }
2143
2144    fn write_binary_expression(&mut self, binary: &BinaryExpression) {
2145        let operator = binary.operator();
2146        let left = binary.left();
2147        let right = binary.right();
2148
2149        if operator.left_needs_parentheses(left) {
2150            self.write_symbol("(");
2151            self.write_expression(left);
2152            self.write_symbol(")");
2153        } else {
2154            self.write_expression(left);
2155        }
2156
2157        if let Some(operator) = binary.get_token() {
2158            self.write_token(operator);
2159        } else {
2160            self.write_token(&Token::from_content(binary.operator().to_str()));
2161        }
2162
2163        if operator.right_needs_parentheses(right) {
2164            self.write_symbol("(");
2165            self.write_expression(right);
2166            self.write_symbol(")");
2167        } else {
2168            self.write_expression(right);
2169        }
2170    }
2171
2172    fn write_unary_expression(&mut self, unary: &UnaryExpression) {
2173        if let Some(operator) = unary.get_token() {
2174            self.write_token(operator);
2175        } else {
2176            self.write_token(&Token::from_content(unary.operator().to_str()));
2177        }
2178
2179        let expression = unary.get_expression();
2180        match expression {
2181            Expression::Binary(binary) if !binary.operator().precedes_unary_expression() => {
2182                self.write_symbol("(");
2183                self.write_expression(expression);
2184                self.write_symbol(")");
2185            }
2186            _ => self.write_expression(expression),
2187        }
2188    }
2189
2190    fn write_function(&mut self, function: &FunctionExpression) {
2191        if let Some(tokens) = function.get_tokens() {
2192            self.write_function_with_tokens(function, tokens);
2193        } else {
2194            self.write_function_with_tokens(function, &self.generate_function_tokens(function));
2195        }
2196    }
2197
2198    fn write_function_call(&mut self, call: &FunctionCall) {
2199        if let Some(tokens) = call.get_tokens() {
2200            self.write_function_call_with_tokens(call, tokens);
2201        } else {
2202            self.write_function_call_with_tokens(call, &self.generate_function_call_tokens(call));
2203        }
2204    }
2205
2206    fn write_field(&mut self, field: &FieldExpression) {
2207        if let Some(token) = field.get_token() {
2208            self.write_field_with_token(field, token);
2209        } else {
2210            self.write_field_with_token(field, &self.generate_field_token(field));
2211        }
2212    }
2213
2214    fn write_index(&mut self, index: &IndexExpression) {
2215        if let Some(tokens) = index.get_tokens() {
2216            self.write_index_with_tokens(index, tokens);
2217        } else {
2218            self.write_index_with_tokens(index, &self.generate_index_tokens(index));
2219        }
2220    }
2221
2222    fn write_if_expression(&mut self, if_expression: &IfExpression) {
2223        if let Some(token) = if_expression.get_tokens() {
2224            self.write_if_expression_with_token(if_expression, token);
2225        } else {
2226            self.write_if_expression_with_token(
2227                if_expression,
2228                &self.generate_if_tokens(if_expression),
2229            );
2230        }
2231    }
2232
2233    fn write_table(&mut self, table: &TableExpression) {
2234        if let Some(tokens) = table.get_tokens() {
2235            self.write_table_with_tokens(table, tokens);
2236        } else {
2237            self.write_table_with_tokens(table, &self.generate_table_tokens(table));
2238        }
2239    }
2240
2241    fn write_table_entry(&mut self, entry: &TableEntry) {
2242        match entry {
2243            TableEntry::Field(entry) => {
2244                if let Some(tokens) = entry.get_token() {
2245                    self.write_table_field_with_tokens(entry, tokens);
2246                } else {
2247                    self.write_table_field_with_tokens(
2248                        entry,
2249                        &self.generate_table_field_tokens(entry),
2250                    );
2251                }
2252            }
2253            TableEntry::Index(entry) => {
2254                if let Some(tokens) = entry.get_tokens() {
2255                    self.write_table_index_with_tokens(entry, tokens);
2256                } else {
2257                    self.write_table_index_with_tokens(
2258                        entry,
2259                        &self.generate_table_index_tokens(entry),
2260                    );
2261                }
2262            }
2263            TableEntry::Value(expression) => self.write_expression(expression),
2264        }
2265    }
2266
2267    fn write_number(&mut self, number: &NumberExpression) {
2268        if let Some(token) = number.get_token() {
2269            self.write_token(token);
2270        } else {
2271            self.write_token(&Token::from_content(utils::write_number(number)));
2272        }
2273    }
2274
2275    fn write_tuple_arguments(&mut self, arguments: &TupleArguments) {
2276        if let Some(tokens) = arguments.get_tokens() {
2277            self.write_tuple_arguments_with_tokens(arguments, tokens);
2278        } else {
2279            self.write_tuple_arguments_with_tokens(
2280                arguments,
2281                &self.generate_tuple_arguments_tokens(arguments),
2282            );
2283        }
2284    }
2285
2286    fn write_string(&mut self, string: &StringExpression) {
2287        if let Some(token) = string.get_token() {
2288            self.write_token(token);
2289        } else {
2290            self.write_symbol(&utils::write_string(string.get_value()));
2291        }
2292    }
2293
2294    fn write_interpolated_string(&mut self, interpolated_string: &InterpolatedStringExpression) {
2295        if let Some(tokens) = interpolated_string.get_tokens() {
2296            self.write_interpolated_string_with_tokens(interpolated_string, tokens);
2297        } else {
2298            self.write_interpolated_string_with_tokens(
2299                interpolated_string,
2300                &self.generate_interpolated_string_tokens(interpolated_string),
2301            );
2302        }
2303    }
2304
2305    fn write_literal_table(&mut self, table: &LiteralTable) {
2306        if let Some(tokens) = table.get_tokens() {
2307            self.write_literal_table_with_tokens(table, tokens);
2308        } else {
2309            self.write_literal_table_with_tokens(table, &self.generate_literal_table_tokens(table));
2310        }
2311    }
2312
2313    fn write_literal_table_entry(&mut self, entry: &LiteralTableEntry) {
2314        match entry {
2315            LiteralTableEntry::Field(field) => {
2316                if let Some(token) = field.get_token() {
2317                    self.write_literal_table_field_with_token(field, token);
2318                } else {
2319                    self.write_literal_table_field_with_token(
2320                        field,
2321                        &self.generate_literal_table_field_token(field),
2322                    );
2323                }
2324            }
2325            LiteralTableEntry::Value(value) => {
2326                self.write_literal_expression(value);
2327            }
2328        }
2329    }
2330
2331    fn write_attribute_tuple_arguments(&mut self, tuple: &AttributeTupleArguments) {
2332        if let Some(tokens) = tuple.get_tokens() {
2333            self.write_attribute_tuple_arguments_with_tokens(tuple, tokens);
2334        } else {
2335            self.write_attribute_tuple_arguments_with_tokens(
2336                tuple,
2337                &self.generate_attribute_tuple_arguments_tokens(tuple),
2338            );
2339        }
2340    }
2341
2342    fn write_identifier(&mut self, identifier: &Identifier) {
2343        if let Some(token) = identifier.get_token() {
2344            let name_in_token = token.read(self.original_code);
2345
2346            if name_in_token == identifier.get_name() {
2347                self.write_token(token);
2348            } else {
2349                let mut new_token = token.clone();
2350                new_token.replace_with_content(identifier.get_name().clone());
2351                self.write_token(&new_token);
2352            }
2353        } else {
2354            let name = identifier.get_name();
2355            self.write_symbol(name);
2356        }
2357    }
2358
2359    fn write_parenthese(&mut self, parenthese: &ParentheseExpression) {
2360        if let Some(tokens) = parenthese.get_tokens() {
2361            self.write_parenthese_with_tokens(parenthese, tokens);
2362        } else {
2363            self.write_parenthese_with_tokens(
2364                parenthese,
2365                &self.generate_parenthese_tokens(parenthese),
2366            );
2367        }
2368    }
2369
2370    fn write_type_cast(&mut self, type_cast: &TypeCastExpression) {
2371        if let Some(token) = type_cast.get_token() {
2372            self.write_type_cast_with_tokens(type_cast, token);
2373        } else {
2374            self.write_type_cast_with_tokens(type_cast, &self.generate_type_cast_token(type_cast));
2375        }
2376    }
2377
2378    fn write_type_name(&mut self, type_name: &TypeName) {
2379        self.write_identifier(type_name.get_type_name());
2380        if let Some(parameters) = type_name.get_type_parameters() {
2381            if let Some(tokens) = parameters.get_tokens() {
2382                self.write_type_parameters_with_tokens(parameters, tokens);
2383            } else {
2384                self.write_type_parameters_with_tokens(
2385                    parameters,
2386                    &self.generate_type_parameters_tokens(parameters),
2387                );
2388            }
2389        }
2390    }
2391
2392    fn write_type_field(&mut self, type_field: &TypeField) {
2393        if let Some(tokens) = type_field.get_token() {
2394            self.write_type_field_with_token(type_field, tokens);
2395        } else {
2396            self.write_type_field_with_token(
2397                type_field,
2398                &self.generate_type_field_token(type_field),
2399            );
2400        }
2401    }
2402
2403    fn write_true_type(&mut self, token: &Option<Token>) {
2404        if let Some(token) = token {
2405            self.write_token(token);
2406        } else {
2407            self.write_symbol("true");
2408        }
2409    }
2410
2411    fn write_false_type(&mut self, token: &Option<Token>) {
2412        if let Some(token) = token {
2413            self.write_token(token);
2414        } else {
2415            self.write_symbol("false");
2416        }
2417    }
2418
2419    fn write_nil_type(&mut self, token: &Option<Token>) {
2420        if let Some(token) = token {
2421            self.write_token(token);
2422        } else {
2423            self.write_symbol("nil");
2424        }
2425    }
2426
2427    fn write_string_type(&mut self, string_type: &StringType) {
2428        if let Some(token) = string_type.get_token() {
2429            self.write_token(token);
2430        } else {
2431            self.write_symbol(&utils::write_string(string_type.get_value()));
2432        }
2433    }
2434
2435    fn write_array_type(&mut self, array: &ArrayType) {
2436        if let Some(tokens) = array.get_tokens() {
2437            self.write_array_type_with_tokens(array, tokens);
2438        } else {
2439            self.write_array_type_with_tokens(array, &self.generate_array_type_tokens(array));
2440        }
2441    }
2442
2443    fn write_table_type(&mut self, table_type: &TableType) {
2444        if let Some(tokens) = table_type.get_tokens() {
2445            self.write_table_type_with_tokens(table_type, tokens);
2446        } else {
2447            self.write_table_type_with_tokens(
2448                table_type,
2449                &self.generate_table_type_tokens(table_type),
2450            );
2451        }
2452    }
2453
2454    fn write_expression_type(&mut self, expression_type: &ExpressionType) {
2455        if let Some(tokens) = expression_type.get_tokens() {
2456            self.write_expression_type_with_tokens(expression_type, tokens);
2457        } else {
2458            self.write_expression_type_with_tokens(
2459                expression_type,
2460                &self.generate_expression_type_tokens(expression_type),
2461            );
2462        }
2463    }
2464
2465    fn write_parenthese_type(&mut self, parenthese_type: &ParentheseType) {
2466        if let Some(tokens) = parenthese_type.get_tokens() {
2467            self.write_parenthese_type_with_tokens(parenthese_type, tokens);
2468        } else {
2469            self.write_parenthese_type_with_tokens(
2470                parenthese_type,
2471                &self.generate_parenthese_type_tokens(parenthese_type),
2472            );
2473        }
2474    }
2475
2476    fn write_function_type(&mut self, function_type: &FunctionType) {
2477        if let Some(tokens) = function_type.get_tokens() {
2478            self.write_function_type_with_tokens(function_type, tokens);
2479        } else {
2480            self.write_function_type_with_tokens(
2481                function_type,
2482                &self.generate_function_type_tokens(function_type),
2483            );
2484        }
2485    }
2486
2487    fn write_optional_type(&mut self, optional: &OptionalType) {
2488        if let Some(token) = optional.get_token() {
2489            self.write_optional_type_with_token(optional, token);
2490        } else {
2491            self.write_optional_type_with_token(
2492                optional,
2493                &self.generate_optional_type_token(optional),
2494            );
2495        }
2496    }
2497
2498    fn write_intersection_type(&mut self, intersection: &IntersectionType) {
2499        if let Some(token) = intersection.get_token() {
2500            self.write_intersection_type_with_token(intersection, token);
2501        } else {
2502            self.write_intersection_type_with_token(
2503                intersection,
2504                &self.generate_intersection_type_token(intersection),
2505            );
2506        }
2507    }
2508
2509    fn write_union_type(&mut self, union: &UnionType) {
2510        if let Some(token) = union.get_token() {
2511            self.write_union_type_with_token(union, token);
2512        } else {
2513            self.write_union_type_with_token(union, &self.generate_union_type_token(union));
2514        }
2515    }
2516
2517    fn write_type_pack(&mut self, type_pack: &TypePack) {
2518        if let Some(tokens) = type_pack.get_tokens() {
2519            self.write_type_pack_with_tokens(type_pack, tokens);
2520        } else {
2521            self.write_type_pack_with_tokens(type_pack, &self.generate_type_pack_tokens(type_pack));
2522        }
2523    }
2524
2525    fn write_variadic_type_pack(&mut self, variadic_type_pack: &VariadicTypePack) {
2526        self.push_str("...");
2527        self.write_type(variadic_type_pack.get_type());
2528    }
2529
2530    fn write_generic_type_pack(&mut self, generic_type_pack: &GenericTypePack) {
2531        self.write_identifier(generic_type_pack.get_name());
2532        self.push_str("...");
2533    }
2534}
2535
2536fn intersect_with_token(token: Token, list_length: usize) -> Vec<Token> {
2537    iter::repeat_with(|| token.clone())
2538        .take(list_length.saturating_sub(1))
2539        .collect()
2540}
2541
2542#[cfg(test)]
2543mod test {
2544    use super::*;
2545
2546    macro_rules! test_output {
2547        ($($name:ident => $code:literal),* $(,)?) => {
2548            $(
2549                #[test]
2550                fn $name() {
2551                    let parser = crate::Parser::default().preserve_tokens();
2552                    let block = parser.parse($code)
2553                        .expect(&format!("failed to parse `{}`", $code));
2554
2555                    let mut generator = TokenBasedLuaGenerator::new($code);
2556
2557                    generator.write_block(&block);
2558
2559                    let output = generator.into_string();
2560
2561                    assert_eq!($code, &output);
2562                }
2563            )*
2564
2565            mod without_tokens {
2566                use super::*;
2567                $(
2568                    #[test]
2569                    fn $name() {
2570                        let parser = crate::Parser::default();
2571                        let block = parser.parse($code)
2572                            .expect(&format!("failed to parse `{}`", $code));
2573
2574                        let mut generator = TokenBasedLuaGenerator::new($code);
2575
2576                        generator.write_block(&block);
2577
2578                        let output = generator.into_string();
2579
2580                        let parsed_output_block = parser.parse(&output)
2581                            .expect(&format!("failed to parse generated code `{}`", &output));
2582
2583                        pretty_assertions::assert_eq!(block, parsed_output_block);
2584                    }
2585                )*
2586            }
2587        };
2588    }
2589
2590    test_output!(
2591        // statements
2592        assign => "var = true",
2593        assign_multiple => "var, var2 =\n\ttrue,\tfalse\n",
2594        empty_do => "do end\n",
2595        nested_do => "do\n    do end\nend\n",
2596        call_without_arguments => "call()",
2597        call_print => "print('hi')",
2598        call_print_with_string_argument => "print 'hi' -- no parentheses",
2599        call_function_with_table_multiline => "process {\n\targ = true,\n\tflag = false,\n}\n",
2600        call_method_without_arguments => "foo:bar()",
2601        call_method_with_arguments => "foo:bar(true, false)",
2602        call_string_format => "('foo'):rep(3)",
2603        call_math_floor => "math.floor(value)",
2604        call_with_index => "object[ key ](i)",
2605        compound_increment => "i += 1\n",
2606        empty_function_declaration => "function process()\nend",
2607        empty_static_function_declaration => "function Class .new()\nend",
2608        empty_method_function_declaration => "function Class : process()\nend",
2609        empty_nested_method_function_declaration => "function Class . foo.bar : help ()\nend",
2610        empty_function_declaration_with_params => "function process(a, b --[[ optional ]]) end",
2611        empty_variadic_function_declaration => "function process (...) end",
2612        empty_variadic_function_declaration_with_one_param => "function format (str, ... --[[ optional strings ]]) end",
2613        variadic_function_returns => "function identity(...)\n\treturn ...\nend\n",
2614
2615        // function attributes
2616        function_statement_with_attribute => "@native\nfunction process()\nend",
2617        local_function_with_attribute => "@native\nlocal function process()\nend",
2618        function_expression_with_attribute => "return @native\nfunction()\nend",
2619        function_statement_with_two_attributes => "@native\n@deprecated\nfunction process()\nend",
2620        local_function_with_two_attributes => "@native\n@deprecated\nlocal function process()\nend",
2621        function_expression_with_two_attributes => "return @native\n@deprecated\nfunction()\nend",
2622        // function_statement_with_attribute_group => "@[native]\nfunction process()\nend",
2623        // local_function_with_attribute_group => "@[native]\nlocal function process()\nend",
2624        // function_expression_with_attribute_group => "return @[native]\nfunction()\nend",
2625        // function_statement_with_attribute_group_two => "@[native, deprecated]\nfunction process()\nend",
2626        // local_function_with_attribute_group_two => "@[native, deprecated]\nlocal function process()\nend",
2627        // function_expression_with_attribute_group_two => "return @[native, deprecated]\nfunction()\nend",
2628        // function_statement_with_attribute_empty_tuple => "@[native()]\nfunction process()\nend",
2629        // local_function_with_attribute_empty_tuple => "@[native()]\nlocal function process()\nend",
2630        // function_expression_with_attribute_empty_tuple => "return @[native()]\nfunction()\nend",
2631        // function_statement_with_attribute_string => "@[native 'luau']\nfunction process()\nend",
2632        // local_function_with_attribute_string => "@[native 'luau']\nlocal function process()\nend",
2633        // function_expression_with_attribute_string => "return @[native 'luau']\nfunction()\nend",
2634        // function_statement_with_attribute_table => "@[config {}]\nfunction process()\nend",
2635        // local_function_with_attribute_table => "@[config {}]\nlocal function process()\nend",
2636        // function_expression_with_attribute_table => "return @[config {}]\nfunction()\nend",
2637        // function_statement_with_attribute_table_values => "@[config { debug = true }]\nfunction process()\nend",
2638        // local_function_with_attribute_table_values => "@[config { debug = true }]\nlocal function process()\nend",
2639        // function_expression_with_attribute_table_values => "return @[config { debug = true }]\nfunction()\nend",
2640        // local_function_with_attribute_nil => "@[default(nil)]\nlocal function process()\nend",
2641        // function_statement_with_attribute_true => "@[enabled(true)]\nfunction process()\nend",
2642        // function_expression_with_attribute_false => "return @[enabled(false)]\nfunction()\nend",
2643        // local_function_with_attribute_number => "@[version(1)]\nlocal function process()\nend",
2644        // function_expression_with_attribute_tuple_string => "return @[tag('important')]\nfunction()\nend",
2645        // function_statement_with_attribute_multiple_values => "@[meta(1, 'test', true, nil)]\nfunction process()\nend",
2646        // local_function_with_attribute_tuple_table => "@[data({ key = 42 })]\nlocal function process()\nend",
2647        // local_function_with_attribute_tuple_array_table => "@[data({ 'hello', 42 })]\nlocal function process()\nend",
2648
2649        empty_generic_for => "for key, value in pairs(result) do\n\t-- help\nend",
2650        empty_generic_for_key_only => "for key in pairs(dict) do end",
2651        generic_for_with_next => "for key,value in next, dict do\n\tprint(key, value)\nend\n",
2652        empty_if => "if true then\nend",
2653        if_condition_return => "if condition then\n\treturn\nend",
2654        empty_if_with_empty_elseif => "if true then\nelseif false then\nend\n",
2655        empty_if_with_two_empty_elseif => "if a then\nelseif b then\nelseif c then\n\tprint(c)\nend\n",
2656        empty_if_with_empty_else => "if true then\nelse\nend\n",
2657        empty_if_with_else_block => "if true then\n\t-- help\nelse\n\treturn\nend\n",
2658        declare_one_variable => "local var\n",
2659        declare_two_variables => "local var, var2\n",
2660        local_assign_one_variable => "local var = true",
2661        local_assign_two_variables => "local var, var2 = true, false",
2662        local_empty_function => "local function process()\nend",
2663        local_empty_variadic_function => "local function process(...)\nend",
2664        local_empty_function_with_one_argument => "local function process( a )\nend",
2665        local_empty_function_with_two_arguments => "local function process(a, b)\nend",
2666        local_empty_variadic_function_with_two_arguments => "local function process(a, b, ...)\nend",
2667        local_identity_function => "local function identity(...)\n\treturn ...\nend",
2668        empty_numeric_for => "for i = 1, final do\nend\n",
2669        empty_numeric_for_with_step => "for i = 1, final, step do\nend\n",
2670        numeric_for => "for i = 1, #list do\n\tprocess(list[i])\nend",
2671        empty_repeat => "repeat until false",
2672        repeat_break_immediately => "repeat break until false",
2673        empty_while => "while true do end",
2674        while_break_immediately => "while true do\n\tbreak\nend",
2675
2676        // last statements
2677        break_with_comment => "break -- exit loop",
2678        continue_with_comment => "continue -- skip to next iteration",
2679        empty_return => "return\n",
2680
2681        // expressions
2682        return_true => "return true",
2683        return_false => "return false",
2684        return_nil => "return nil",
2685        return_single_quote_string => "return 'ok'",
2686        return_double_quote_string => "return \"ok\"",
2687        return_identifier => "return var",
2688        return_bracket_string => "return [[   [ok]   ]]",
2689        return_empty_interpolated_string => "return ``",
2690        return_interpolated_string_escape_curly_brace => "return `Open: \\{`",
2691        return_interpolated_string_followed_by_comment => "return `ok` -- comment",
2692        return_interpolated_string_with_true_value => "return `{ true }`",
2693        return_interpolated_string_with_true_value_and_prefix => "return `Result = { true }`",
2694        return_interpolated_string_with_true_value_and_suffix => "return `{ variable } !`",
2695        return_interpolated_string_with_various_segments => "return `Variable = { variable } ({ --[[len]] #variable })` -- display",
2696        return_empty_table => "return { }",
2697        return_table_with_field => "return { field = {} }",
2698        return_table_with_index => "return { [field] = {} }",
2699        return_list_of_one_element => "return { true, }",
2700        return_list_of_two_elements => "return { true, false }",
2701        return_mixed_table => "return { true, field = false, [\"hello\"] = true }",
2702        return_parenthese_call => "return ( call() )",
2703        return_variable_arguments => "return ...",
2704        return_unary_minus => "return - number",
2705        return_unary_length => "return #list\n",
2706        return_unary_not => "return not condition\n",
2707        return_binary_and => "return a and b",
2708        return_binary_or => "return a or b",
2709        return_binary_plus => "return 10 + 15",
2710        return_empty_function => "return function() end",
2711        return_empty_variadic_function => "return function(...)\nend",
2712        return_empty_function_with_one_argument => "return function( a )\nend",
2713        return_empty_function_with_two_arguments => "return function(a, b)\nend",
2714        return_empty_variadic_function_with_two_arguments => "return function(a, b, ...)\nend",
2715        return_identity_function => "return function(...)\n\treturn ...\nend",
2716        return_field => "return math.huge",
2717        return_field_ending_with_number => "return UDim2.new",
2718        return_field_split_on_lines => "return value.\n\tproperty\n\t.name",
2719    );
2720
2721    #[test]
2722    fn inserts_a_new_line_after_a_comment_for_a_token() {
2723        let statement = RepeatStatement::new(Block::default(), true).with_tokens(RepeatTokens {
2724            repeat: Token::from_content("repeat")
2725                .with_trailing_trivia(TriviaKind::Comment.with_content("-- hello")),
2726            until: Token::from_content("until"),
2727        });
2728
2729        let mut generator = TokenBasedLuaGenerator::new("");
2730
2731        generator.write_repeat_statement(&statement);
2732
2733        let output = generator.into_string();
2734
2735        crate::Parser::default()
2736            .parse(&output)
2737            .unwrap_or_else(|_| panic!("failed to parse generated code `{}`", &output));
2738    }
2739
2740    #[test]
2741    fn inserts_a_new_line_after_custom_added_comments() {
2742        let code = "call(a--comment\n\t,b\n)";
2743        let mut block = crate::Parser::default()
2744            .preserve_tokens()
2745            .parse(code)
2746            .unwrap();
2747
2748        let call = match block.iter_mut_statements().last().unwrap() {
2749            Statement::Call(call) => call,
2750            _ => panic!("unexpected statement"),
2751        };
2752        let tuple = match call.mutate_arguments() {
2753            Arguments::Tuple(tuple) => tuple,
2754            _ => panic!("unexpected arguments"),
2755        };
2756        let mut tokens = tuple.get_tokens().unwrap().clone();
2757
2758        tuple.iter_mut_values().for_each(|value| match value {
2759            Expression::Identifier(identifier) => {
2760                let name = identifier.mutate_name();
2761                let new_token = {
2762                    Token::from_content(name.to_owned())
2763                        .with_trailing_trivia(TriviaKind::Comment.with_content("--new comment"))
2764                };
2765                identifier.set_token(new_token);
2766            }
2767            _ => panic!("unexpected expression"),
2768        });
2769
2770        // drop a comma and verify that the generator does not screw things up
2771        tokens.commas.pop();
2772        tuple.set_tokens(tokens);
2773
2774        let mut generator = TokenBasedLuaGenerator::new(code);
2775
2776        generator.write_block(&block);
2777
2778        let output = generator.into_string();
2779
2780        crate::Parser::default()
2781            .parse(&output)
2782            .unwrap_or_else(|_| panic!("failed to parse generated code `{}`", &output));
2783
2784        insta::assert_snapshot!("inserts_a_new_line_after_custom_added_comments", output);
2785    }
2786
2787    #[test]
2788    fn break_long_comments_on_new_lines() {
2789        let token = Token::from_content("")
2790            .with_leading_trivia(TriviaKind::Comment.with_content("-- first line"))
2791            .with_leading_trivia(TriviaKind::Comment.with_content("--[[\nnext comment ]]"));
2792        let block = Block::default().with_tokens(BlockTokens {
2793            semicolons: Default::default(),
2794            last_semicolon: Default::default(),
2795            final_token: Some(token),
2796        });
2797
2798        let mut generator = TokenBasedLuaGenerator::new("");
2799        generator.write_block(&block);
2800
2801        insta::assert_snapshot!(generator.into_string(), @r###"
2802        -- first line
2803        --[[
2804        next comment ]]
2805        "###);
2806    }
2807}