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