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