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