Skip to main content

darklua_core/generator/
token_based.rs

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