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