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);
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 i < last_index {
827                if let Some(comma) = tokens.separators.get(i) {
828                    self.write_token(comma);
829                } else {
830                    self.write_symbol(",");
831                }
832            }
833        }
834
835        self.write_token(&tokens.closing_brace);
836    }
837
838    fn write_table_indexer_type_with_tokens(
839        &mut self,
840        indexer_type: &TableIndexerType,
841        tokens: &TableIndexTypeTokens,
842    ) {
843        self.write_token(&tokens.opening_bracket);
844
845        let key_type = indexer_type.get_key_type();
846
847        let need_parentheses = matches!(
848            key_type,
849            Type::Optional(_) | Type::Intersection(_) | Type::Union(_)
850        );
851
852        if need_parentheses {
853            self.write_symbol("(");
854            self.write_type(key_type);
855            self.write_symbol(")");
856        } else {
857            self.write_type(key_type);
858        }
859
860        self.write_token(&tokens.closing_bracket);
861        self.write_token(&tokens.colon);
862        self.write_type(indexer_type.get_value_type());
863    }
864
865    fn write_table_literal_property_type_with_tokens(
866        &mut self,
867        property: &TableLiteralPropertyType,
868        tokens: &TableIndexTypeTokens,
869    ) {
870        self.write_token(&tokens.opening_bracket);
871        self.write_string_type(property.get_string());
872        self.write_token(&tokens.closing_bracket);
873        self.write_token(&tokens.colon);
874        self.write_type(property.get_type());
875    }
876
877    fn write_expression_type_with_tokens(
878        &mut self,
879        expression_type: &ExpressionType,
880        tokens: &ExpressionTypeTokens,
881    ) {
882        self.write_token(&tokens.r#typeof);
883        self.write_token(&tokens.opening_parenthese);
884        self.write_expression(expression_type.get_expression());
885        self.write_token(&tokens.closing_parenthese);
886    }
887
888    fn write_parenthese_type_with_tokens(
889        &mut self,
890        parenthese_type: &ParentheseType,
891        tokens: &ParentheseTypeTokens,
892    ) {
893        self.write_token(&tokens.left_parenthese);
894        self.write_type(parenthese_type.get_inner_type());
895        self.write_token(&tokens.right_parenthese);
896    }
897
898    fn write_function_type_with_tokens(
899        &mut self,
900        function_type: &FunctionType,
901        tokens: &FunctionTypeTokens,
902    ) {
903        if let Some(generic_parameters) = function_type.get_generic_parameters() {
904            self.write_function_generics(generic_parameters);
905        }
906
907        self.write_token(&tokens.opening_parenthese);
908
909        let argument_len = function_type.argument_len();
910        let last_index = argument_len.saturating_sub(1);
911
912        for (i, argument) in function_type.iter_arguments().enumerate() {
913            if let Some(name) = argument.get_name() {
914                self.write_identifier(name);
915
916                if let Some(token) = argument.get_token() {
917                    self.write_token(token);
918                } else {
919                    self.write_symbol(":");
920                }
921            }
922
923            self.write_type(argument.get_type());
924
925            if i < last_index {
926                if let Some(comma) = tokens.commas.get(i) {
927                    self.write_token(comma);
928                } else {
929                    self.write_symbol(",");
930                }
931            }
932        }
933
934        if let Some(variadic_argument_type) = function_type.get_variadic_argument_type() {
935            if argument_len > 0 {
936                if let Some(comma) = tokens.commas.get(argument_len) {
937                    self.write_token(comma);
938                } else {
939                    self.write_symbol(",");
940                }
941            }
942            self.write_variadic_argument_type(variadic_argument_type);
943        }
944
945        self.write_token(&tokens.closing_parenthese);
946        self.write_token(&tokens.arrow);
947        self.write_function_return_type(function_type.get_return_type());
948    }
949
950    fn write_function_generics(&mut self, generic_parameters: &GenericParameters) {
951        if generic_parameters.is_empty() {
952            return;
953        }
954        if let Some(generic_tokens) = generic_parameters.get_tokens() {
955            self.write_generic_parameters_with_tokens(generic_parameters, generic_tokens);
956        } else {
957            self.write_generic_parameters_with_tokens(
958                generic_parameters,
959                &self.generate_generic_parameters_tokens(generic_parameters),
960            );
961        }
962    }
963
964    fn write_generic_parameters_with_tokens(
965        &mut self,
966        generic_parameters: &GenericParameters,
967        tokens: &GenericParametersTokens,
968    ) {
969        self.write_token(&tokens.opening_list);
970
971        let last_index = generic_parameters.len().saturating_sub(1);
972
973        for (i, type_variable) in generic_parameters.iter_type_variable().enumerate() {
974            self.write_identifier(type_variable);
975
976            if i < last_index {
977                if let Some(comma) = tokens.commas.get(i) {
978                    self.write_token(comma);
979                } else {
980                    self.write_symbol(",");
981                }
982            }
983        }
984
985        let type_variables_len = generic_parameters.type_variables_len();
986
987        for (i, generic_type_pack) in generic_parameters.iter_generic_type_pack().enumerate() {
988            self.write_generic_type_pack(generic_type_pack);
989
990            if (i + type_variables_len) < last_index {
991                if let Some(comma) = tokens.commas.get(i) {
992                    self.write_token(comma);
993                } else {
994                    self.write_symbol(",");
995                }
996            }
997        }
998
999        self.write_token(&tokens.closing_list);
1000    }
1001
1002    fn write_type_pack_with_tokens(&mut self, type_pack: &TypePack, tokens: &TypePackTokens) {
1003        self.write_token(&tokens.left_parenthese);
1004
1005        let last_index = type_pack
1006            .len()
1007            .saturating_sub(if type_pack.has_variadic_type() { 0 } else { 1 });
1008
1009        for (i, r#type) in type_pack.iter().enumerate() {
1010            self.write_type(r#type);
1011
1012            if i < last_index {
1013                if let Some(comma) = tokens.commas.get(i) {
1014                    self.write_token(comma);
1015                } else {
1016                    self.write_symbol(",");
1017                }
1018            }
1019        }
1020
1021        if let Some(variadic_argument_type) = type_pack.get_variadic_type() {
1022            self.write_variadic_argument_type(variadic_argument_type);
1023        }
1024
1025        self.write_token(&tokens.right_parenthese);
1026    }
1027
1028    fn write_optional_type_with_token(&mut self, optional: &OptionalType, token: &Token) {
1029        let inner_type = optional.get_inner_type();
1030        if OptionalType::needs_parentheses(inner_type) {
1031            self.write_symbol("(");
1032            self.write_type(inner_type);
1033            self.write_symbol(")");
1034        } else {
1035            self.write_type(inner_type);
1036        }
1037        self.write_token(token);
1038    }
1039
1040    fn write_intersection_type_with_token(
1041        &mut self,
1042        intersection: &IntersectionType,
1043        tokens: &IntersectionTypeTokens,
1044    ) {
1045        let length = intersection.len();
1046        let last_index = length.saturating_sub(1);
1047
1048        for (i, r#type) in intersection.iter_types().enumerate() {
1049            if i == 0 {
1050                if let Some(leading) = &tokens.leading_token {
1051                    self.write_token(leading);
1052                }
1053            } else if let Some(token) = tokens.separators.get(i.saturating_sub(1)) {
1054                self.write_token(token);
1055            } else {
1056                self.write_symbol("&");
1057            }
1058
1059            let need_parentheses = if i == last_index {
1060                IntersectionType::last_needs_parentheses(r#type)
1061            } else {
1062                IntersectionType::intermediate_needs_parentheses(r#type)
1063            };
1064
1065            if need_parentheses {
1066                self.write_symbol("(");
1067                self.write_type(r#type);
1068                self.write_symbol(")");
1069            } else {
1070                self.write_type(r#type);
1071            }
1072        }
1073    }
1074
1075    fn write_union_type_with_token(&mut self, union: &UnionType, tokens: &UnionTypeTokens) {
1076        let length = union.len();
1077        let last_index = length.saturating_sub(1);
1078
1079        for (i, r#type) in union.iter_types().enumerate() {
1080            if i == 0 {
1081                if let Some(leading) = &tokens.leading_token {
1082                    self.write_token(leading);
1083                }
1084            } else if let Some(token) = tokens.separators.get(i.saturating_sub(1)) {
1085                self.write_token(token);
1086            } else {
1087                self.write_symbol("|");
1088            }
1089
1090            let need_parentheses = if i == last_index {
1091                UnionType::last_needs_parentheses(r#type)
1092            } else {
1093                UnionType::intermediate_needs_parentheses(r#type)
1094            };
1095
1096            if need_parentheses {
1097                self.write_symbol("(");
1098                self.write_type(r#type);
1099                self.write_symbol(")");
1100            } else {
1101                self.write_type(r#type);
1102            }
1103        }
1104    }
1105
1106    fn write_interpolated_string_with_tokens(
1107        &mut self,
1108        interpolated_string: &InterpolatedStringExpression,
1109        tokens: &InterpolatedStringTokens,
1110    ) {
1111        self.write_token(&tokens.opening_tick);
1112
1113        for segment in interpolated_string.iter_segments() {
1114            match segment {
1115                InterpolationSegment::String(string_segment) => {
1116                    if let Some(token) = string_segment.get_token() {
1117                        self.write_token(token);
1118                    } else {
1119                        self.write_symbol(&utils::write_interpolated_string_segment(string_segment))
1120                    }
1121                }
1122                InterpolationSegment::Value(value) => {
1123                    if let Some(tokens) = value.get_tokens() {
1124                        self.write_string_value_segment_with_tokens(value, tokens);
1125                    } else {
1126                        self.write_string_value_segment_with_tokens(
1127                            value,
1128                            &self.generate_string_value_segment_tokens(value),
1129                        );
1130                    }
1131                }
1132            }
1133        }
1134
1135        self.write_token(&tokens.closing_tick);
1136    }
1137
1138    fn write_string_value_segment_with_tokens(
1139        &mut self,
1140        value: &ValueSegment,
1141        tokens: &ValueSegmentTokens,
1142    ) {
1143        self.write_token(&tokens.opening_brace);
1144        let expression = value.get_expression();
1145        if self.output.ends_with('{') {
1146            if let Some(table) = utils::starts_with_table(expression) {
1147                if table
1148                    .get_tokens()
1149                    .and_then(|tokens| {
1150                        tokens
1151                            .opening_brace
1152                            .iter_leading_trivia()
1153                            .next()
1154                            .filter(|trivia| !trivia.read(self.original_code).is_empty())
1155                    })
1156                    .is_none()
1157                {
1158                    self.output.push(' ');
1159                }
1160            }
1161        }
1162        self.write_expression(expression);
1163        self.write_token(&tokens.closing_brace);
1164    }
1165
1166    fn generate_block_tokens(&self, _block: &Block) -> BlockTokens {
1167        BlockTokens {
1168            semicolons: Vec::new(),
1169            last_semicolon: None,
1170            final_token: None,
1171        }
1172    }
1173
1174    fn generate_assign_tokens(&self, assign: &AssignStatement) -> AssignTokens {
1175        AssignTokens {
1176            equal: Token::from_content("="),
1177            variable_commas: intersect_with_token(comma_token(), assign.variables_len()),
1178            value_commas: intersect_with_token(comma_token(), assign.values_len()),
1179        }
1180    }
1181
1182    fn generate_do_tokens(&self, _do_statement: &DoStatement) -> DoTokens {
1183        DoTokens {
1184            r#do: Token::from_content("do"),
1185            end: Token::from_content("end"),
1186        }
1187    }
1188
1189    fn generate_compound_assign_tokens(
1190        &self,
1191        assign: &CompoundAssignStatement,
1192    ) -> CompoundAssignTokens {
1193        CompoundAssignTokens {
1194            operator: Token::from_content(assign.get_operator().to_str()),
1195        }
1196    }
1197
1198    fn generate_generic_for_tokens(&self, generic_for: &GenericForStatement) -> GenericForTokens {
1199        GenericForTokens {
1200            r#for: Token::from_content("for"),
1201            r#in: Token::from_content("in"),
1202            r#do: Token::from_content("do"),
1203            end: Token::from_content("end"),
1204            identifier_commas: intersect_with_token(comma_token(), generic_for.identifiers_len()),
1205            value_commas: intersect_with_token(comma_token(), generic_for.expressions_len()),
1206        }
1207    }
1208
1209    fn generate_if_statement_tokens(&self, if_statement: &IfStatement) -> IfStatementTokens {
1210        IfStatementTokens {
1211            r#if: Token::from_content("if"),
1212            then: Token::from_content("then"),
1213            end: Token::from_content("end"),
1214            r#else: if_statement
1215                .get_else_block()
1216                .map(|_| Token::from_content("else")),
1217        }
1218    }
1219
1220    fn generate_if_branch_tokens(&self, _branch: &IfBranch) -> IfBranchTokens {
1221        IfBranchTokens {
1222            elseif: Token::from_content("elseif"),
1223            then: Token::from_content("then"),
1224        }
1225    }
1226
1227    fn generate_function_statement_tokens(
1228        &self,
1229        function: &FunctionStatement,
1230    ) -> FunctionBodyTokens {
1231        FunctionBodyTokens {
1232            function: Token::from_content("function"),
1233            opening_parenthese: Token::from_content("("),
1234            closing_parenthese: Token::from_content(")"),
1235            end: Token::from_content("end"),
1236            parameter_commas: intersect_with_token(
1237                comma_token(),
1238                function.parameters_count() + usize::from(function.is_variadic()),
1239            ),
1240            variable_arguments: if function.is_variadic() {
1241                Some(Token::from_content("..."))
1242            } else {
1243                None
1244            },
1245            variable_arguments_colon: if function.has_variadic_type() {
1246                Some(Token::from_content(":"))
1247            } else {
1248                None
1249            },
1250            return_type_colon: if function.has_return_type() {
1251                Some(Token::from_content(":"))
1252            } else {
1253                None
1254            },
1255        }
1256    }
1257
1258    fn generate_function_name_tokens(&self, name: &FunctionName) -> FunctionNameTokens {
1259        FunctionNameTokens {
1260            periods: iter::repeat_with(|| Token::from_content("."))
1261                .take(name.get_field_names().len())
1262                .collect(),
1263            colon: name.get_method().map(|_| Token::from_content(":")),
1264        }
1265    }
1266
1267    fn generate_return_tokens(&self, return_statement: &ReturnStatement) -> ReturnTokens {
1268        ReturnTokens {
1269            r#return: Token::from_content("return")
1270                .with_trailing_trivia(TriviaKind::Whitespace.with_content(" ")),
1271            commas: intersect_with_token(comma_token(), return_statement.len()),
1272        }
1273    }
1274
1275    fn generate_local_assign_tokens(&self, assign: &LocalAssignStatement) -> LocalAssignTokens {
1276        LocalAssignTokens {
1277            local: Token::from_content("local"),
1278            equal: if assign.has_values() {
1279                Some(Token::from_content("="))
1280            } else {
1281                None
1282            },
1283            variable_commas: intersect_with_token(comma_token(), assign.variables_len()),
1284            value_commas: intersect_with_token(comma_token(), assign.values_len()),
1285        }
1286    }
1287
1288    fn generate_local_function_tokens(
1289        &self,
1290        function: &LocalFunctionStatement,
1291    ) -> LocalFunctionTokens {
1292        LocalFunctionTokens {
1293            local: Token::from_content("local"),
1294            function_body: FunctionBodyTokens {
1295                function: Token::from_content("function"),
1296                opening_parenthese: Token::from_content("("),
1297                closing_parenthese: Token::from_content(")"),
1298                end: Token::from_content("end"),
1299                parameter_commas: intersect_with_token(
1300                    comma_token(),
1301                    function.parameters_count() + usize::from(function.is_variadic()),
1302                ),
1303                variable_arguments: if function.is_variadic() {
1304                    Some(Token::from_content("..."))
1305                } else {
1306                    None
1307                },
1308                variable_arguments_colon: if function.has_variadic_type() {
1309                    Some(Token::from_content(":"))
1310                } else {
1311                    None
1312                },
1313                return_type_colon: if function.has_return_type() {
1314                    Some(Token::from_content(":"))
1315                } else {
1316                    None
1317                },
1318            },
1319        }
1320    }
1321
1322    fn generate_numeric_for_tokens(&self, numeric_for: &NumericForStatement) -> NumericForTokens {
1323        NumericForTokens {
1324            r#for: Token::from_content("for"),
1325            equal: Token::from_content("="),
1326            r#do: Token::from_content("do"),
1327            end: Token::from_content("end"),
1328            end_comma: Token::from_content(","),
1329            step_comma: numeric_for.get_step().map(|_| Token::from_content(",")),
1330        }
1331    }
1332
1333    fn generate_repeat_tokens(&self, _repeat: &RepeatStatement) -> RepeatTokens {
1334        RepeatTokens {
1335            repeat: Token::from_content("repeat"),
1336            until: Token::from_content("until"),
1337        }
1338    }
1339
1340    fn generate_while_tokens(&self, _while_statement: &WhileStatement) -> WhileTokens {
1341        WhileTokens {
1342            r#while: Token::from_content("while"),
1343            r#do: Token::from_content("do"),
1344            end: Token::from_content("end"),
1345        }
1346    }
1347
1348    fn generate_type_declaration_tokens(
1349        &self,
1350        statement: &TypeDeclarationStatement,
1351    ) -> TypeDeclarationTokens {
1352        TypeDeclarationTokens {
1353            r#type: Token::from_content("type"),
1354            equal: Token::from_content("="),
1355            export: if statement.is_exported() {
1356                Some(Token::from_content("export"))
1357            } else {
1358                None
1359            },
1360        }
1361    }
1362
1363    fn generate_function_tokens(&self, function: &FunctionExpression) -> FunctionBodyTokens {
1364        FunctionBodyTokens {
1365            function: Token::from_content("function"),
1366            opening_parenthese: Token::from_content("("),
1367            closing_parenthese: Token::from_content(")"),
1368            end: Token::from_content("end"),
1369            parameter_commas: intersect_with_token(
1370                comma_token(),
1371                function.parameters_count() + usize::from(function.is_variadic()),
1372            ),
1373            variable_arguments: if function.is_variadic() {
1374                Some(Token::from_content("..."))
1375            } else {
1376                None
1377            },
1378            variable_arguments_colon: if function.has_variadic_type() {
1379                Some(Token::from_content(":"))
1380            } else {
1381                None
1382            },
1383            return_type_colon: if function.has_return_type() {
1384                Some(Token::from_content(":"))
1385            } else {
1386                None
1387            },
1388        }
1389    }
1390
1391    fn generate_function_call_tokens(&self, call: &FunctionCall) -> FunctionCallTokens {
1392        FunctionCallTokens {
1393            colon: call.get_method().map(|_| Token::from_content(":")),
1394        }
1395    }
1396
1397    fn generate_field_token(&self, _field: &FieldExpression) -> Token {
1398        Token::from_content(".")
1399    }
1400
1401    fn generate_index_tokens(&self, _index: &IndexExpression) -> IndexExpressionTokens {
1402        IndexExpressionTokens {
1403            opening_bracket: Token::from_content("["),
1404            closing_bracket: Token::from_content("]"),
1405        }
1406    }
1407
1408    fn generate_if_tokens(&self, _if_expression: &IfExpression) -> IfExpressionTokens {
1409        IfExpressionTokens {
1410            r#if: Token::from_content("if"),
1411            then: Token::from_content("then"),
1412            r#else: Token::from_content("else"),
1413        }
1414    }
1415
1416    fn generate_if_expression_branch_tokens(
1417        &self,
1418        _branch: &ElseIfExpressionBranch,
1419    ) -> ElseIfExpressionBranchTokens {
1420        ElseIfExpressionBranchTokens {
1421            elseif: Token::from_content("elseif"),
1422            then: Token::from_content("then"),
1423        }
1424    }
1425
1426    fn generate_table_tokens(&self, table: &TableExpression) -> TableTokens {
1427        TableTokens {
1428            opening_brace: Token::from_content("{"),
1429            closing_brace: Token::from_content("}"),
1430            separators: intersect_with_token(comma_token(), table.len()),
1431        }
1432    }
1433
1434    fn generate_table_field_tokens(&self, _entry: &TableFieldEntry) -> Token {
1435        Token::from_content("=")
1436    }
1437
1438    fn generate_table_index_tokens(&self, _entry: &TableIndexEntry) -> TableIndexEntryTokens {
1439        TableIndexEntryTokens {
1440            opening_bracket: Token::from_content("["),
1441            closing_bracket: Token::from_content("]"),
1442            equal: Token::from_content("="),
1443        }
1444    }
1445
1446    fn generate_tuple_arguments_tokens(&self, arguments: &TupleArguments) -> TupleArgumentsTokens {
1447        TupleArgumentsTokens {
1448            opening_parenthese: Token::from_content("("),
1449            closing_parenthese: Token::from_content(")"),
1450            commas: intersect_with_token(comma_token(), arguments.len()),
1451        }
1452    }
1453
1454    fn generate_parenthese_tokens(&self, _parenthese: &ParentheseExpression) -> ParentheseTokens {
1455        ParentheseTokens {
1456            left_parenthese: Token::from_content("("),
1457            right_parenthese: Token::from_content(")"),
1458        }
1459    }
1460
1461    fn generate_type_cast_token(&self, _type_cast: &TypeCastExpression) -> Token {
1462        Token::from_content("::")
1463    }
1464
1465    fn generate_type_parameters_tokens(&self, parameters: &TypeParameters) -> TypeParametersTokens {
1466        TypeParametersTokens {
1467            opening_list: Token::from_content("<"),
1468            closing_list: Token::from_content(">"),
1469            commas: intersect_with_token(comma_token(), parameters.len()),
1470        }
1471    }
1472
1473    fn generate_type_field_token(&self, _type_field: &TypeField) -> Token {
1474        Token::from_content(".")
1475    }
1476
1477    fn generate_array_type_tokens(&self, _array: &ArrayType) -> ArrayTypeTokens {
1478        ArrayTypeTokens {
1479            opening_brace: Token::from_content("{"),
1480            closing_brace: Token::from_content("}"),
1481        }
1482    }
1483
1484    fn generate_table_type_tokens(&self, table_type: &TableType) -> TableTypeTokens {
1485        TableTypeTokens {
1486            opening_brace: Token::from_content("{"),
1487            closing_brace: Token::from_content("}"),
1488            separators: intersect_with_token(comma_token(), table_type.len()),
1489        }
1490    }
1491
1492    fn generate_table_indexer_type_tokens(&self) -> TableIndexTypeTokens {
1493        TableIndexTypeTokens {
1494            opening_bracket: Token::from_content("["),
1495            closing_bracket: Token::from_content("]"),
1496            colon: Token::from_content(":"),
1497        }
1498    }
1499
1500    fn generate_expression_type_tokens(
1501        &self,
1502        _expression_type: &ExpressionType,
1503    ) -> ExpressionTypeTokens {
1504        ExpressionTypeTokens {
1505            r#typeof: Token::from_content("typeof"),
1506            opening_parenthese: Token::from_content("("),
1507            closing_parenthese: Token::from_content(")"),
1508        }
1509    }
1510
1511    fn generate_parenthese_type_tokens(
1512        &self,
1513        _parenthese_type: &ParentheseType,
1514    ) -> ParentheseTypeTokens {
1515        ParentheseTypeTokens {
1516            left_parenthese: Token::from_content("("),
1517            right_parenthese: Token::from_content(")"),
1518        }
1519    }
1520
1521    fn generate_function_type_tokens(&self, function_type: &FunctionType) -> FunctionTypeTokens {
1522        FunctionTypeTokens {
1523            opening_parenthese: Token::from_content("("),
1524            closing_parenthese: Token::from_content(")"),
1525            arrow: Token::from_content("->"),
1526            commas: intersect_with_token(
1527                comma_token(),
1528                function_type.argument_len()
1529                    + usize::from(function_type.has_variadic_argument_type()),
1530            ),
1531        }
1532    }
1533
1534    fn generate_optional_type_token(&self, _optional: &OptionalType) -> Token {
1535        Token::from_content("?")
1536    }
1537
1538    fn generate_intersection_type_token(
1539        &self,
1540        intersection: &IntersectionType,
1541    ) -> IntersectionTypeTokens {
1542        IntersectionTypeTokens {
1543            leading_token: intersection
1544                .has_leading_token()
1545                .then(|| Token::from_content("&")),
1546            separators: intersect_with_token(Token::from_content("&"), intersection.len()),
1547        }
1548    }
1549
1550    fn generate_union_type_token(&self, union: &UnionType) -> UnionTypeTokens {
1551        UnionTypeTokens {
1552            leading_token: union.has_leading_token().then(|| Token::from_content("|")),
1553            separators: intersect_with_token(Token::from_content("|"), union.len()),
1554        }
1555    }
1556
1557    fn generate_type_pack_tokens(&self, type_pack: &TypePack) -> TypePackTokens {
1558        TypePackTokens {
1559            left_parenthese: Token::from_content("("),
1560            right_parenthese: Token::from_content(")"),
1561            commas: intersect_with_token(
1562                comma_token(),
1563                type_pack.len() + usize::from(type_pack.has_variadic_type()),
1564            ),
1565        }
1566    }
1567
1568    fn generate_generic_parameters_tokens(
1569        &self,
1570        generic_parameters: &GenericParameters,
1571    ) -> GenericParametersTokens {
1572        GenericParametersTokens {
1573            opening_list: Token::from_content("<"),
1574            closing_list: Token::from_content(">"),
1575            commas: intersect_with_token(comma_token(), generic_parameters.len()),
1576        }
1577    }
1578
1579    fn generate_generic_parameters_with_defaults_tokens(
1580        &self,
1581        generic_parameters: &GenericParametersWithDefaults,
1582    ) -> GenericParametersTokens {
1583        GenericParametersTokens {
1584            opening_list: Token::from_content("<"),
1585            closing_list: Token::from_content(">"),
1586            commas: intersect_with_token(comma_token(), generic_parameters.len()),
1587        }
1588    }
1589
1590    fn generate_interpolated_string_tokens(
1591        &self,
1592        _interpolated_string: &InterpolatedStringExpression,
1593    ) -> InterpolatedStringTokens {
1594        InterpolatedStringTokens {
1595            opening_tick: Token::from_content("`"),
1596            closing_tick: Token::from_content("`"),
1597        }
1598    }
1599
1600    fn generate_string_value_segment_tokens(
1601        &self,
1602        _value_segment: &ValueSegment,
1603    ) -> ValueSegmentTokens {
1604        ValueSegmentTokens {
1605            opening_brace: Token::from_content("{"),
1606            closing_brace: Token::from_content("}"),
1607        }
1608    }
1609
1610    fn write_symbol(&mut self, symbol: &str) {
1611        if self.currently_commenting {
1612            self.uncomment();
1613        } else if self.needs_space(symbol.chars().next().expect("symbol cannot be empty")) {
1614            self.output.push(' ');
1615        }
1616        self.push_str(symbol);
1617    }
1618
1619    fn write_symbol_without_space_check(&mut self, symbol: &str) {
1620        if self.currently_commenting {
1621            self.uncomment();
1622        }
1623        self.push_str(symbol);
1624    }
1625
1626    fn write_typed_identifier(&mut self, typed_identifier: &TypedIdentifier) {
1627        if let Some(token) = typed_identifier.get_token() {
1628            let name_in_token = token.read(self.original_code);
1629
1630            if name_in_token == typed_identifier.get_name() {
1631                self.write_token(token);
1632            } else {
1633                let mut new_token = token.clone();
1634                new_token.replace_with_content(typed_identifier.get_name().clone());
1635                self.write_token(&new_token);
1636            }
1637        } else {
1638            let name = typed_identifier.get_name();
1639            self.write_symbol(name);
1640        }
1641
1642        if let Some(r#type) = typed_identifier.get_type() {
1643            if let Some(colon) = typed_identifier.get_colon_token() {
1644                self.write_token(colon);
1645            } else {
1646                self.write_symbol(":");
1647            }
1648            self.write_type(r#type);
1649        }
1650    }
1651
1652    #[inline]
1653    fn needs_space(&self, next_character: char) -> bool {
1654        if let Some(last) = self.output.chars().last() {
1655            utils::should_break_with_space(last, next_character)
1656        } else {
1657            false
1658        }
1659    }
1660
1661    #[inline]
1662    fn uncomment(&mut self) {
1663        self.output.push('\n');
1664        self.current_line += 1;
1665        self.currently_commenting = false;
1666    }
1667}
1668
1669fn is_single_line_comment(content: &str) -> bool {
1670    let is_multiline_comment = content.starts_with("--[") && {
1671        if let Some((closing_bracket_index, _)) =
1672            content.chars().skip(3).enumerate().find(|(_, c)| *c == '[')
1673        {
1674            content
1675                .get(3..closing_bracket_index)
1676                .map(|substring| substring.chars().all(|c| c == '='))
1677                .unwrap_or(true)
1678        } else {
1679            false
1680        }
1681    };
1682
1683    !is_multiline_comment
1684}
1685
1686#[inline]
1687fn comma_token() -> Token {
1688    Token::from_content(",").with_trailing_trivia(TriviaKind::Whitespace.with_content(" "))
1689}
1690
1691impl<'a> LuaGenerator for TokenBasedLuaGenerator<'a> {
1692    fn into_string(self) -> String {
1693        self.output
1694    }
1695
1696    fn write_block(&mut self, block: &Block) {
1697        if let Some(tokens) = block.get_tokens() {
1698            self.write_block_with_tokens(block, tokens);
1699        } else {
1700            self.write_block_with_tokens(block, &self.generate_block_tokens(block));
1701        }
1702    }
1703
1704    fn write_assign_statement(&mut self, assign: &AssignStatement) {
1705        if let Some(tokens) = assign.get_tokens() {
1706            self.write_assign_with_tokens(assign, tokens);
1707        } else {
1708            self.write_assign_with_tokens(assign, &self.generate_assign_tokens(assign));
1709        }
1710    }
1711
1712    fn write_do_statement(&mut self, do_statement: &DoStatement) {
1713        if let Some(tokens) = do_statement.get_tokens() {
1714            self.write_do_with_tokens(do_statement, tokens);
1715        } else {
1716            self.write_do_with_tokens(do_statement, &self.generate_do_tokens(do_statement));
1717        }
1718    }
1719
1720    fn write_compound_assign(&mut self, assign: &CompoundAssignStatement) {
1721        if let Some(tokens) = assign.get_tokens() {
1722            self.write_compound_assign_with_tokens(assign, tokens);
1723        } else {
1724            self.write_compound_assign_with_tokens(
1725                assign,
1726                &self.generate_compound_assign_tokens(assign),
1727            );
1728        }
1729    }
1730
1731    fn write_generic_for(&mut self, generic_for: &GenericForStatement) {
1732        if let Some(tokens) = generic_for.get_tokens() {
1733            self.write_generic_for_with_tokens(generic_for, tokens);
1734        } else {
1735            self.write_generic_for_with_tokens(
1736                generic_for,
1737                &self.generate_generic_for_tokens(generic_for),
1738            );
1739        }
1740    }
1741
1742    fn write_if_statement(&mut self, if_statement: &IfStatement) {
1743        if let Some(tokens) = if_statement.get_tokens() {
1744            self.write_if_statement_with_tokens(if_statement, tokens);
1745        } else {
1746            self.write_if_statement_with_tokens(
1747                if_statement,
1748                &self.generate_if_statement_tokens(if_statement),
1749            );
1750        }
1751    }
1752
1753    fn write_function_statement(&mut self, function: &FunctionStatement) {
1754        if let Some(tokens) = function.get_tokens() {
1755            self.write_function_statement_with_tokens(function, tokens);
1756        } else {
1757            self.write_function_statement_with_tokens(
1758                function,
1759                &self.generate_function_statement_tokens(function),
1760            );
1761        }
1762    }
1763
1764    fn write_last_statement(&mut self, statement: &LastStatement) {
1765        match statement {
1766            LastStatement::Break(token) => {
1767                if let Some(token) = token {
1768                    self.write_token(token);
1769                } else {
1770                    self.write_symbol("break");
1771                }
1772            }
1773            LastStatement::Continue(token) => {
1774                if let Some(token) = token {
1775                    self.write_token(token);
1776                } else {
1777                    self.write_symbol("continue");
1778                }
1779            }
1780            LastStatement::Return(return_statement) => {
1781                if let Some(tokens) = return_statement.get_tokens() {
1782                    self.write_return_with_tokens(return_statement, tokens);
1783                } else {
1784                    self.write_return_with_tokens(
1785                        return_statement,
1786                        &self.generate_return_tokens(return_statement),
1787                    );
1788                }
1789            }
1790        }
1791    }
1792
1793    fn write_local_assign(&mut self, assign: &LocalAssignStatement) {
1794        if let Some(tokens) = assign.get_tokens() {
1795            self.write_local_assign_with_tokens(assign, tokens);
1796        } else {
1797            self.write_local_assign_with_tokens(assign, &self.generate_local_assign_tokens(assign));
1798        }
1799    }
1800
1801    fn write_local_function(&mut self, function: &LocalFunctionStatement) {
1802        if let Some(tokens) = function.get_tokens() {
1803            self.write_local_function_with_tokens(function, tokens);
1804        } else {
1805            self.write_local_function_with_tokens(
1806                function,
1807                &self.generate_local_function_tokens(function),
1808            );
1809        }
1810    }
1811
1812    fn write_numeric_for(&mut self, numeric_for: &NumericForStatement) {
1813        if let Some(tokens) = numeric_for.get_tokens() {
1814            self.write_numeric_for_with_tokens(numeric_for, tokens);
1815        } else {
1816            self.write_numeric_for_with_tokens(
1817                numeric_for,
1818                &self.generate_numeric_for_tokens(numeric_for),
1819            );
1820        }
1821    }
1822
1823    fn write_repeat_statement(&mut self, repeat: &RepeatStatement) {
1824        if let Some(tokens) = repeat.get_tokens() {
1825            self.write_repeat_with_tokens(repeat, tokens);
1826        } else {
1827            self.write_repeat_with_tokens(repeat, &self.generate_repeat_tokens(repeat));
1828        }
1829    }
1830
1831    fn write_while_statement(&mut self, while_statement: &WhileStatement) {
1832        if let Some(tokens) = while_statement.get_tokens() {
1833            self.write_while_with_tokens(while_statement, tokens);
1834        } else {
1835            self.write_while_with_tokens(
1836                while_statement,
1837                &self.generate_while_tokens(while_statement),
1838            );
1839        }
1840    }
1841
1842    fn write_type_declaration_statement(&mut self, statement: &TypeDeclarationStatement) {
1843        if let Some(tokens) = statement.get_tokens() {
1844            self.write_type_declaration_with_tokens(statement, tokens);
1845        } else {
1846            self.write_type_declaration_with_tokens(
1847                statement,
1848                &self.generate_type_declaration_tokens(statement),
1849            );
1850        }
1851    }
1852
1853    fn write_false_expression(&mut self, token: &Option<Token>) {
1854        if let Some(token) = token {
1855            self.write_token(token);
1856        } else {
1857            self.write_symbol("false");
1858        }
1859    }
1860
1861    fn write_true_expression(&mut self, token: &Option<Token>) {
1862        if let Some(token) = token {
1863            self.write_token(token);
1864        } else {
1865            self.write_symbol("true");
1866        }
1867    }
1868
1869    fn write_nil_expression(&mut self, token: &Option<Token>) {
1870        if let Some(token) = token {
1871            self.write_token(token);
1872        } else {
1873            self.write_symbol("nil");
1874        }
1875    }
1876
1877    fn write_variable_arguments_expression(&mut self, token: &Option<Token>) {
1878        if let Some(token) = token {
1879            self.write_token(token);
1880        } else {
1881            self.write_symbol("...");
1882        }
1883    }
1884
1885    fn write_binary_expression(&mut self, binary: &BinaryExpression) {
1886        let operator = binary.operator();
1887        let left = binary.left();
1888        let right = binary.right();
1889
1890        if operator.left_needs_parentheses(left) {
1891            self.write_symbol("(");
1892            self.write_expression(left);
1893            self.write_symbol(")");
1894        } else {
1895            self.write_expression(left);
1896        }
1897
1898        if let Some(operator) = binary.get_token() {
1899            self.write_token(operator);
1900        } else {
1901            self.write_token(&Token::from_content(binary.operator().to_str()));
1902        }
1903
1904        if operator.right_needs_parentheses(right) {
1905            self.write_symbol("(");
1906            self.write_expression(right);
1907            self.write_symbol(")");
1908        } else {
1909            self.write_expression(right);
1910        }
1911    }
1912
1913    fn write_unary_expression(&mut self, unary: &UnaryExpression) {
1914        if let Some(operator) = unary.get_token() {
1915            self.write_token(operator);
1916        } else {
1917            self.write_token(&Token::from_content(unary.operator().to_str()));
1918        }
1919
1920        let expression = unary.get_expression();
1921        match expression {
1922            Expression::Binary(binary) if !binary.operator().precedes_unary_expression() => {
1923                self.write_symbol("(");
1924                self.write_expression(expression);
1925                self.write_symbol(")");
1926            }
1927            _ => self.write_expression(expression),
1928        }
1929    }
1930
1931    fn write_function(&mut self, function: &FunctionExpression) {
1932        if let Some(tokens) = function.get_tokens() {
1933            self.write_function_with_tokens(function, tokens);
1934        } else {
1935            self.write_function_with_tokens(function, &self.generate_function_tokens(function));
1936        }
1937    }
1938
1939    fn write_function_call(&mut self, call: &FunctionCall) {
1940        if let Some(tokens) = call.get_tokens() {
1941            self.write_function_call_with_tokens(call, tokens);
1942        } else {
1943            self.write_function_call_with_tokens(call, &self.generate_function_call_tokens(call));
1944        }
1945    }
1946
1947    fn write_field(&mut self, field: &FieldExpression) {
1948        if let Some(token) = field.get_token() {
1949            self.write_field_with_token(field, token);
1950        } else {
1951            self.write_field_with_token(field, &self.generate_field_token(field));
1952        }
1953    }
1954
1955    fn write_index(&mut self, index: &IndexExpression) {
1956        if let Some(tokens) = index.get_tokens() {
1957            self.write_index_with_tokens(index, tokens);
1958        } else {
1959            self.write_index_with_tokens(index, &self.generate_index_tokens(index));
1960        }
1961    }
1962
1963    fn write_if_expression(&mut self, if_expression: &IfExpression) {
1964        if let Some(token) = if_expression.get_tokens() {
1965            self.write_if_expression_with_token(if_expression, token);
1966        } else {
1967            self.write_if_expression_with_token(
1968                if_expression,
1969                &self.generate_if_tokens(if_expression),
1970            );
1971        }
1972    }
1973
1974    fn write_table(&mut self, table: &TableExpression) {
1975        if let Some(tokens) = table.get_tokens() {
1976            self.write_table_with_tokens(table, tokens);
1977        } else {
1978            self.write_table_with_tokens(table, &self.generate_table_tokens(table));
1979        }
1980    }
1981
1982    fn write_table_entry(&mut self, entry: &TableEntry) {
1983        match entry {
1984            TableEntry::Field(entry) => {
1985                if let Some(tokens) = entry.get_token() {
1986                    self.write_table_field_with_tokens(entry, tokens);
1987                } else {
1988                    self.write_table_field_with_tokens(
1989                        entry,
1990                        &self.generate_table_field_tokens(entry),
1991                    );
1992                }
1993            }
1994            TableEntry::Index(entry) => {
1995                if let Some(tokens) = entry.get_tokens() {
1996                    self.write_table_index_with_tokens(entry, tokens);
1997                } else {
1998                    self.write_table_index_with_tokens(
1999                        entry,
2000                        &self.generate_table_index_tokens(entry),
2001                    );
2002                }
2003            }
2004            TableEntry::Value(expression) => self.write_expression(expression),
2005        }
2006    }
2007
2008    fn write_number(&mut self, number: &NumberExpression) {
2009        if let Some(token) = number.get_token() {
2010            self.write_token(token);
2011        } else {
2012            self.write_token(&Token::from_content(utils::write_number(number)));
2013        }
2014    }
2015
2016    fn write_tuple_arguments(&mut self, arguments: &TupleArguments) {
2017        if let Some(tokens) = arguments.get_tokens() {
2018            self.write_tuple_arguments_with_tokens(arguments, tokens);
2019        } else {
2020            self.write_tuple_arguments_with_tokens(
2021                arguments,
2022                &self.generate_tuple_arguments_tokens(arguments),
2023            );
2024        }
2025    }
2026
2027    fn write_string(&mut self, string: &StringExpression) {
2028        if let Some(token) = string.get_token() {
2029            self.write_token(token);
2030        } else {
2031            self.write_symbol(&utils::write_string(string.get_value()));
2032        }
2033    }
2034
2035    fn write_interpolated_string(&mut self, interpolated_string: &InterpolatedStringExpression) {
2036        if let Some(tokens) = interpolated_string.get_tokens() {
2037            self.write_interpolated_string_with_tokens(interpolated_string, tokens);
2038        } else {
2039            self.write_interpolated_string_with_tokens(
2040                interpolated_string,
2041                &self.generate_interpolated_string_tokens(interpolated_string),
2042            );
2043        }
2044    }
2045
2046    fn write_identifier(&mut self, identifier: &Identifier) {
2047        if let Some(token) = identifier.get_token() {
2048            let name_in_token = token.read(self.original_code);
2049
2050            if name_in_token == identifier.get_name() {
2051                self.write_token(token);
2052            } else {
2053                let mut new_token = token.clone();
2054                new_token.replace_with_content(identifier.get_name().clone());
2055                self.write_token(&new_token);
2056            }
2057        } else {
2058            let name = identifier.get_name();
2059            self.write_symbol(name);
2060        }
2061    }
2062
2063    fn write_parenthese(&mut self, parenthese: &ParentheseExpression) {
2064        if let Some(tokens) = parenthese.get_tokens() {
2065            self.write_parenthese_with_tokens(parenthese, tokens);
2066        } else {
2067            self.write_parenthese_with_tokens(
2068                parenthese,
2069                &self.generate_parenthese_tokens(parenthese),
2070            );
2071        }
2072    }
2073
2074    fn write_type_cast(&mut self, type_cast: &TypeCastExpression) {
2075        if let Some(token) = type_cast.get_token() {
2076            self.write_type_cast_with_tokens(type_cast, token);
2077        } else {
2078            self.write_type_cast_with_tokens(type_cast, &self.generate_type_cast_token(type_cast));
2079        }
2080    }
2081
2082    fn write_type_name(&mut self, type_name: &TypeName) {
2083        self.write_identifier(type_name.get_type_name());
2084        if let Some(parameters) = type_name.get_type_parameters() {
2085            if let Some(tokens) = parameters.get_tokens() {
2086                self.write_type_parameters_with_tokens(parameters, tokens);
2087            } else {
2088                self.write_type_parameters_with_tokens(
2089                    parameters,
2090                    &self.generate_type_parameters_tokens(parameters),
2091                );
2092            }
2093        }
2094    }
2095
2096    fn write_type_field(&mut self, type_field: &TypeField) {
2097        if let Some(tokens) = type_field.get_token() {
2098            self.write_type_field_with_token(type_field, tokens);
2099        } else {
2100            self.write_type_field_with_token(
2101                type_field,
2102                &self.generate_type_field_token(type_field),
2103            );
2104        }
2105    }
2106
2107    fn write_true_type(&mut self, token: &Option<Token>) {
2108        if let Some(token) = token {
2109            self.write_token(token);
2110        } else {
2111            self.write_symbol("true");
2112        }
2113    }
2114
2115    fn write_false_type(&mut self, token: &Option<Token>) {
2116        if let Some(token) = token {
2117            self.write_token(token);
2118        } else {
2119            self.write_symbol("false");
2120        }
2121    }
2122
2123    fn write_nil_type(&mut self, token: &Option<Token>) {
2124        if let Some(token) = token {
2125            self.write_token(token);
2126        } else {
2127            self.write_symbol("nil");
2128        }
2129    }
2130
2131    fn write_string_type(&mut self, string_type: &StringType) {
2132        if let Some(token) = string_type.get_token() {
2133            self.write_token(token);
2134        } else {
2135            self.write_symbol(&utils::write_string(string_type.get_value()));
2136        }
2137    }
2138
2139    fn write_array_type(&mut self, array: &ArrayType) {
2140        if let Some(tokens) = array.get_tokens() {
2141            self.write_array_type_with_tokens(array, tokens);
2142        } else {
2143            self.write_array_type_with_tokens(array, &self.generate_array_type_tokens(array));
2144        }
2145    }
2146
2147    fn write_table_type(&mut self, table_type: &TableType) {
2148        if let Some(tokens) = table_type.get_tokens() {
2149            self.write_table_type_with_tokens(table_type, tokens);
2150        } else {
2151            self.write_table_type_with_tokens(
2152                table_type,
2153                &self.generate_table_type_tokens(table_type),
2154            );
2155        }
2156    }
2157
2158    fn write_expression_type(&mut self, expression_type: &ExpressionType) {
2159        if let Some(tokens) = expression_type.get_tokens() {
2160            self.write_expression_type_with_tokens(expression_type, tokens);
2161        } else {
2162            self.write_expression_type_with_tokens(
2163                expression_type,
2164                &self.generate_expression_type_tokens(expression_type),
2165            );
2166        }
2167    }
2168
2169    fn write_parenthese_type(&mut self, parenthese_type: &ParentheseType) {
2170        if let Some(tokens) = parenthese_type.get_tokens() {
2171            self.write_parenthese_type_with_tokens(parenthese_type, tokens);
2172        } else {
2173            self.write_parenthese_type_with_tokens(
2174                parenthese_type,
2175                &self.generate_parenthese_type_tokens(parenthese_type),
2176            );
2177        }
2178    }
2179
2180    fn write_function_type(&mut self, function_type: &FunctionType) {
2181        if let Some(tokens) = function_type.get_tokens() {
2182            self.write_function_type_with_tokens(function_type, tokens);
2183        } else {
2184            self.write_function_type_with_tokens(
2185                function_type,
2186                &self.generate_function_type_tokens(function_type),
2187            );
2188        }
2189    }
2190
2191    fn write_optional_type(&mut self, optional: &OptionalType) {
2192        if let Some(token) = optional.get_token() {
2193            self.write_optional_type_with_token(optional, token);
2194        } else {
2195            self.write_optional_type_with_token(
2196                optional,
2197                &self.generate_optional_type_token(optional),
2198            );
2199        }
2200    }
2201
2202    fn write_intersection_type(&mut self, intersection: &IntersectionType) {
2203        if let Some(token) = intersection.get_token() {
2204            self.write_intersection_type_with_token(intersection, token);
2205        } else {
2206            self.write_intersection_type_with_token(
2207                intersection,
2208                &self.generate_intersection_type_token(intersection),
2209            );
2210        }
2211    }
2212
2213    fn write_union_type(&mut self, union: &UnionType) {
2214        if let Some(token) = union.get_token() {
2215            self.write_union_type_with_token(union, token);
2216        } else {
2217            self.write_union_type_with_token(union, &self.generate_union_type_token(union));
2218        }
2219    }
2220
2221    fn write_type_pack(&mut self, type_pack: &TypePack) {
2222        if let Some(tokens) = type_pack.get_tokens() {
2223            self.write_type_pack_with_tokens(type_pack, tokens);
2224        } else {
2225            self.write_type_pack_with_tokens(type_pack, &self.generate_type_pack_tokens(type_pack));
2226        }
2227    }
2228
2229    fn write_variadic_type_pack(&mut self, variadic_type_pack: &VariadicTypePack) {
2230        self.push_str("...");
2231        self.write_type(variadic_type_pack.get_type());
2232    }
2233
2234    fn write_generic_type_pack(&mut self, generic_type_pack: &GenericTypePack) {
2235        self.write_identifier(generic_type_pack.get_name());
2236        self.push_str("...");
2237    }
2238}
2239
2240fn intersect_with_token(token: Token, list_length: usize) -> Vec<Token> {
2241    iter::repeat_with(|| token.clone())
2242        .take(list_length.saturating_sub(1))
2243        .collect()
2244}
2245
2246#[cfg(test)]
2247mod test {
2248    use super::*;
2249
2250    macro_rules! test_output {
2251        ($($name:ident => $code:literal),* $(,)?) => {
2252            $(
2253                #[test]
2254                fn $name() {
2255                    let parser = crate::Parser::default().preserve_tokens();
2256                    let block = parser.parse($code)
2257                        .expect(&format!("failed to parse `{}`", $code));
2258
2259                    let mut generator = TokenBasedLuaGenerator::new($code);
2260
2261                    generator.write_block(&block);
2262
2263                    let output = generator.into_string();
2264
2265                    assert_eq!($code, &output);
2266                }
2267            )*
2268
2269            mod without_tokens {
2270                use super::*;
2271                $(
2272                    #[test]
2273                    fn $name() {
2274                        let parser = crate::Parser::default();
2275                        let block = parser.parse($code)
2276                            .expect(&format!("failed to parse `{}`", $code));
2277
2278                        let mut generator = TokenBasedLuaGenerator::new($code);
2279
2280                        generator.write_block(&block);
2281
2282                        let output = generator.into_string();
2283
2284                        let parsed_output_block = parser.parse(&output)
2285                            .expect(&format!("failed to parse generated code `{}`", &output));
2286
2287                        pretty_assertions::assert_eq!(block, parsed_output_block);
2288                    }
2289                )*
2290            }
2291        };
2292    }
2293
2294    test_output!(
2295        // statements
2296        assign => "var = true",
2297        assign_multiple => "var, var2 =\n\ttrue,\tfalse\n",
2298        empty_do => "do end\n",
2299        nested_do => "do\n    do end\nend\n",
2300        call_without_arguments => "call()",
2301        call_print => "print('hi')",
2302        call_print_with_string_argument => "print 'hi' -- no parentheses",
2303        call_function_with_table_multiline => "process {\n\targ = true,\n\tflag = false,\n}\n",
2304        call_method_without_arguments => "foo:bar()",
2305        call_method_with_arguments => "foo:bar(true, false)",
2306        call_string_format => "('foo'):rep(3)",
2307        call_math_floor => "math.floor(value)",
2308        call_with_index => "object[ key ](i)",
2309        compound_increment => "i += 1\n",
2310        empty_function_declaration => "function process()\nend",
2311        empty_static_function_declaration => "function Class .new()\nend",
2312        empty_method_function_declaration => "function Class : process()\nend",
2313        empty_nested_method_function_declaration => "function Class . foo.bar : help ()\nend",
2314        empty_function_declaration_with_params => "function process(a, b --[[ optional ]]) end",
2315        empty_variadic_function_declaration => "function process (...) end",
2316        empty_variadic_function_declaration_with_one_param => "function format (str, ... --[[ optional strings ]]) end",
2317        variadic_function_returns => "function identity(...)\n\treturn ...\nend\n",
2318        empty_generic_for => "for key, value in pairs(result) do\n\t-- help\nend",
2319        empty_generic_for_key_only => "for key in pairs(dict) do end",
2320        generic_for_with_next => "for key,value in next, dict do\n\tprint(key, value)\nend\n",
2321        empty_if => "if true then\nend",
2322        if_condition_return => "if condition then\n\treturn\nend",
2323        empty_if_with_empty_elseif => "if true then\nelseif false then\nend\n",
2324        empty_if_with_two_empty_elseif => "if a then\nelseif b then\nelseif c then\n\tprint(c)\nend\n",
2325        empty_if_with_empty_else => "if true then\nelse\nend\n",
2326        empty_if_with_else_block => "if true then\n\t-- help\nelse\n\treturn\nend\n",
2327        declare_one_variable => "local var\n",
2328        declare_two_variables => "local var, var2\n",
2329        local_assign_one_variable => "local var = true",
2330        local_assign_two_variables => "local var, var2 = true, false",
2331        local_empty_function => "local function process()\nend",
2332        local_empty_variadic_function => "local function process(...)\nend",
2333        local_empty_function_with_one_argument => "local function process( a )\nend",
2334        local_empty_function_with_two_arguments => "local function process(a, b)\nend",
2335        local_empty_variadic_function_with_two_arguments => "local function process(a, b, ...)\nend",
2336        local_identity_function => "local function identity(...)\n\treturn ...\nend",
2337        empty_numeric_for => "for i = 1, final do\nend\n",
2338        empty_numeric_for_with_step => "for i = 1, final, step do\nend\n",
2339        numeric_for => "for i = 1, #list do\n\tprocess(list[i])\nend",
2340        empty_repeat => "repeat until false",
2341        repeat_break_immediately => "repeat break until false",
2342        empty_while => "while true do end",
2343        while_break_immediately => "while true do\n\tbreak\nend",
2344
2345        // last statements
2346        break_with_comment => "break -- exit loop",
2347        continue_with_comment => "continue -- skip to next iteration",
2348        empty_return => "return\n",
2349
2350        // expressions
2351        return_true => "return true",
2352        return_false => "return false",
2353        return_nil => "return nil",
2354        return_single_quote_string => "return 'ok'",
2355        return_double_quote_string => "return \"ok\"",
2356        return_identifier => "return var",
2357        return_bracket_string => "return [[   [ok]   ]]",
2358        return_empty_interpolated_string => "return ``",
2359        return_interpolated_string_escape_curly_brace => "return `Open: \\{`",
2360        return_interpolated_string_followed_by_comment => "return `ok` -- comment",
2361        return_interpolated_string_with_true_value => "return `{ true }`",
2362        return_interpolated_string_with_true_value_and_prefix => "return `Result = { true }`",
2363        return_interpolated_string_with_true_value_and_suffix => "return `{ variable } !`",
2364        return_interpolated_string_with_various_segments => "return `Variable = { variable } ({ --[[len]] #variable })` -- display",
2365        return_empty_table => "return { }",
2366        return_table_with_field => "return { field = {} }",
2367        return_table_with_index => "return { [field] = {} }",
2368        return_list_of_one_element => "return { true, }",
2369        return_list_of_two_elements => "return { true, false }",
2370        return_mixed_table => "return { true, field = false, [\"hello\"] = true }",
2371        return_parenthese_call => "return ( call() )",
2372        return_variable_arguments => "return ...",
2373        return_unary_minus => "return - number",
2374        return_unary_length => "return #list\n",
2375        return_unary_not => "return not condition\n",
2376        return_binary_and => "return a and b",
2377        return_binary_or => "return a or b",
2378        return_binary_plus => "return 10 + 15",
2379        return_empty_function => "return function() end",
2380        return_empty_variadic_function => "return function(...)\nend",
2381        return_empty_function_with_one_argument => "return function( a )\nend",
2382        return_empty_function_with_two_arguments => "return function(a, b)\nend",
2383        return_empty_variadic_function_with_two_arguments => "return function(a, b, ...)\nend",
2384        return_identity_function => "return function(...)\n\treturn ...\nend",
2385        return_field => "return math.huge",
2386        return_field_ending_with_number => "return UDim2.new",
2387        return_field_split_on_lines => "return value.\n\tproperty\n\t.name",
2388    );
2389
2390    #[test]
2391    fn inserts_a_new_line_after_a_comment_for_a_token() {
2392        let statement = RepeatStatement::new(Block::default(), true).with_tokens(RepeatTokens {
2393            repeat: Token::from_content("repeat")
2394                .with_trailing_trivia(TriviaKind::Comment.with_content("-- hello")),
2395            until: Token::from_content("until"),
2396        });
2397
2398        let mut generator = TokenBasedLuaGenerator::new("");
2399
2400        generator.write_repeat_statement(&statement);
2401
2402        let output = generator.into_string();
2403
2404        crate::Parser::default()
2405            .parse(&output)
2406            .unwrap_or_else(|_| panic!("failed to parse generated code `{}`", &output));
2407    }
2408
2409    #[test]
2410    fn inserts_a_new_line_after_custom_added_comments() {
2411        let code = "call(a--comment\n\t,b\n)";
2412        let mut block = crate::Parser::default()
2413            .preserve_tokens()
2414            .parse(code)
2415            .unwrap();
2416
2417        let call = match block.iter_mut_statements().last().unwrap() {
2418            Statement::Call(call) => call,
2419            _ => panic!("unexpected statement"),
2420        };
2421        let tuple = match call.mutate_arguments() {
2422            Arguments::Tuple(tuple) => tuple,
2423            _ => panic!("unexpected arguments"),
2424        };
2425        let mut tokens = tuple.get_tokens().unwrap().clone();
2426
2427        tuple.iter_mut_values().for_each(|value| match value {
2428            Expression::Identifier(identifier) => {
2429                let name = identifier.mutate_name();
2430                let new_token = {
2431                    Token::from_content(name.to_owned())
2432                        .with_trailing_trivia(TriviaKind::Comment.with_content("--new comment"))
2433                };
2434                identifier.set_token(new_token);
2435            }
2436            _ => panic!("unexpected expression"),
2437        });
2438
2439        // drop a comma and verify that the generator does not screw things up
2440        tokens.commas.pop();
2441        tuple.set_tokens(tokens);
2442
2443        let mut generator = TokenBasedLuaGenerator::new(code);
2444
2445        generator.write_block(&block);
2446
2447        let output = generator.into_string();
2448
2449        crate::Parser::default()
2450            .parse(&output)
2451            .unwrap_or_else(|_| panic!("failed to parse generated code `{}`", &output));
2452
2453        insta::assert_snapshot!("inserts_a_new_line_after_custom_added_comments", output);
2454    }
2455}