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