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