1use crate::generator::{utils, LuaGenerator};
2use crate::nodes;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5enum StatementType {
6 Assign,
7 Do,
8 Call,
9 CompoundAssign,
10 Function,
11 GenericFor,
12 If,
13 LocalAssign,
14 LocalFunction,
15 NumericFor,
16 Repeat,
17 While,
18 TypeDeclaration,
19 Return,
20 Break,
21 Continue,
22}
23
24impl From<&nodes::Statement> for StatementType {
25 fn from(statement: &nodes::Statement) -> Self {
26 use nodes::Statement::*;
27 match statement {
28 Assign(_) => Self::Assign,
29 Do(_) => Self::Do,
30 Call(_) => Self::Call,
31 CompoundAssign(_) => Self::CompoundAssign,
32 Function(_) => Self::Function,
33 GenericFor(_) => Self::GenericFor,
34 If(_) => Self::If,
35 LocalAssign(_) => Self::LocalAssign,
36 LocalFunction(_) => Self::LocalFunction,
37 NumericFor(_) => Self::NumericFor,
38 Repeat(_) => Self::Repeat,
39 While(_) => Self::While,
40 TypeDeclaration(_) => Self::TypeDeclaration,
41 }
42 }
43}
44
45impl From<&nodes::LastStatement> for StatementType {
46 fn from(statement: &nodes::LastStatement) -> Self {
47 use nodes::LastStatement::*;
48 match statement {
49 Break(_) => Self::Break,
50 Continue(_) => Self::Continue,
51 Return(_) => Self::Return,
52 }
53 }
54}
55
56#[derive(Debug, Clone)]
59pub struct ReadableLuaGenerator {
60 column_span: usize,
61 indentation: usize,
62 current_line_length: usize,
63 current_indentation: usize,
64 output: String,
65 last_push_length: usize,
66 can_add_new_line_stack: Vec<bool>,
67}
68
69impl ReadableLuaGenerator {
70 pub fn new(column_span: usize) -> Self {
71 Self {
72 column_span,
73 indentation: 4,
74 current_line_length: 0,
75 current_indentation: 0,
76 output: String::new(),
77 last_push_length: 0,
78 can_add_new_line_stack: Vec::new(),
79 }
80 }
81
82 #[inline]
83 fn can_add_new_line(&self) -> bool {
84 self.can_add_new_line_stack.last().copied().unwrap_or(true)
85 }
86
87 #[inline]
88 fn push_can_add_new_line(&mut self, value: bool) {
89 self.can_add_new_line_stack.push(value);
90 }
91
92 #[inline]
93 fn pop_can_add_new_line(&mut self) {
94 self.can_add_new_line_stack.pop();
95 }
96
97 #[inline]
98 fn push_indentation(&mut self) {
99 self.current_indentation += 1;
100 }
101
102 #[inline]
103 fn pop_indentation(&mut self) {
104 self.current_indentation -= 1;
105 }
106
107 #[inline]
108 fn write_indentation(&mut self) {
109 let indentation = " ".repeat(self.indentation * self.current_indentation);
110 self.raw_push_str(&indentation);
111 }
112
113 #[inline]
114 fn push_new_line(&mut self) {
115 self.output.push('\n');
116 self.current_line_length = 0;
117 }
118
119 #[inline]
120 fn fits_on_current_line(&self, length: usize) -> bool {
121 self.current_line_length + length <= self.column_span
122 }
123
124 #[inline]
125 fn push_space(&mut self) {
126 self.output.push(' ');
127 self.current_line_length += 1;
128 }
129
130 fn push_str(&mut self, content: &str) {
133 if let Some(next_char) = content.chars().next() {
134 self.push_space_if_needed(next_char, content.len());
135 self.raw_push_str(content);
136 }
137 }
138
139 fn push_char(&mut self, character: char) {
141 self.push_space_if_needed(character, 1);
142
143 self.output.push(character);
144 self.current_line_length += 1;
145 self.last_push_length = 1;
146 }
147
148 #[inline]
149 fn raw_push_str(&mut self, content: &str) {
150 self.output.push_str(content);
151 self.last_push_length = content.len();
152 self.current_line_length += self.last_push_length;
153 }
154
155 #[inline]
156 fn raw_push_char(&mut self, character: char) {
157 self.output.push(character);
158 self.last_push_length = 1;
159 self.current_line_length += 1;
160 }
161
162 #[inline]
163 fn needs_space(&self, next_character: char) -> bool {
164 if let Some(previous) = self.output.chars().last() {
165 utils::should_break_with_space(previous, next_character)
166 } else {
167 false
168 }
169 }
170
171 #[inline]
172 fn indent_and_write_block(&mut self, block: &nodes::Block) {
173 self.push_indentation();
174 self.write_block(block);
175 self.pop_indentation();
176 }
177
178 fn push_new_line_if_needed(&mut self, pushed_length: usize) {
179 if self.current_line_length == 0 && self.current_indentation != 0 {
180 self.write_indentation();
181 }
182
183 if self.can_add_new_line() {
184 if self.current_line_length >= self.column_span {
185 self.push_new_line();
186 } else {
187 let total_length = self.current_line_length + pushed_length;
188
189 if total_length > self.column_span {
190 self.push_new_line();
191 }
192 }
193 }
194 }
195
196 fn push_space_if_needed(&mut self, next_character: char, pushed_length: usize) {
197 if self.current_line_length == 0 && self.current_indentation != 0 {
198 self.write_indentation();
199 }
200
201 if self.can_add_new_line() {
202 if self.current_line_length >= self.column_span {
203 self.push_new_line();
204 } else {
205 let total_length = self.current_line_length + pushed_length;
206
207 if self.needs_space(next_character) {
208 if total_length + 1 > self.column_span {
209 self.push_new_line();
210 } else {
211 self.push_space();
212 }
213 } else if total_length > self.column_span {
214 self.push_new_line();
215 }
216 }
217 } else if self.needs_space(next_character) {
218 self.push_space();
219 }
220 }
221
222 fn push_str_and_break_if<F>(&mut self, content: &str, predicate: F)
225 where
226 F: Fn(&str) -> bool,
227 {
228 if predicate(self.get_last_push_str()) {
229 if self.fits_on_current_line(1 + content.len()) {
230 self.push_space();
231 } else {
232 self.push_new_line();
233 }
234 } else if !self.fits_on_current_line(content.len()) {
235 self.push_new_line();
236 }
237 self.raw_push_str(content);
238 }
239
240 fn get_last_push_str(&self) -> &str {
241 self.output
242 .get((self.output.len() - self.last_push_length)..)
243 .unwrap_or("")
244 }
245
246 fn table_fits_on_line(&self, entries: &[nodes::TableEntry], _width: usize) -> bool {
247 use nodes::TableEntry;
248
249 entries.len() < 4
251 && entries.iter().all(|entry| match entry {
252 TableEntry::Value(value) => self.is_small_expression(value),
253 _ => false,
254 })
255 || entries.len() == 1
256 && entries.iter().all(|entry| match entry {
257 TableEntry::Field(entry) => self.is_small_expression(entry.get_value()),
258 TableEntry::Index(entry) => {
259 self.is_small_expression(entry.get_key())
260 && self.is_small_expression(entry.get_value())
261 }
262 _ => false,
263 })
264 }
265
266 fn is_small_expression(&self, expression: &nodes::Expression) -> bool {
267 use nodes::Expression::*;
268 match expression {
269 True(_) | False(_) | Nil(_) | Identifier(_) | VariableArguments(_) | Number(_) => true,
270 Table(table) => table.is_empty(),
271 _ => false,
272 }
273 }
274
275 fn write_function_parameters(
276 &mut self,
277 parameters: &[nodes::TypedIdentifier],
278 is_variadic: bool,
279 variadic_type: Option<&nodes::FunctionVariadicType>,
280 ) {
281 let mut parameters_length = parameters.iter().fold(0, |acc, parameter| {
282 acc + parameter.get_name().len()
283 + if parameter.has_type() {
284 10
286 } else {
287 0
288 }
289 });
290 parameters_length += parameters.len() * 2;
292
293 if is_variadic {
294 parameters_length += 3;
296 if parameters.len() > 1 {
297 parameters_length += 2;
299 }
300 }
301
302 let last_index = parameters.len().saturating_sub(1);
303
304 if self.fits_on_current_line(parameters_length) {
305 parameters.iter().enumerate().for_each(|(index, variable)| {
306 self.write_typed_identifier(variable);
307
308 if index != last_index {
309 self.raw_push_char(',');
310 self.raw_push_char(' ');
311 }
312 });
313
314 if is_variadic {
315 if !parameters.is_empty() {
316 self.raw_push_char(',');
317 self.raw_push_char(' ');
318 };
319 self.raw_push_str("...");
320
321 if let Some(variadic_type) = variadic_type {
322 self.raw_push_char(':');
323 self.raw_push_char(' ');
324 self.write_function_variadic_type(r#variadic_type);
325 }
326 };
327 } else {
328 self.push_indentation();
329
330 parameters.iter().enumerate().for_each(|(index, variable)| {
331 self.push_new_line();
332 self.write_indentation();
333 self.write_typed_identifier(variable);
334
335 if index != last_index {
336 self.raw_push_char(',');
337 }
338 });
339
340 if is_variadic {
341 if !parameters.is_empty() {
342 self.raw_push_char(',');
343 };
344 self.push_new_line();
345 self.write_indentation();
346 self.raw_push_str("...");
347
348 if let Some(variadic_type) = variadic_type {
349 self.raw_push_char(':');
350 self.raw_push_char(' ');
351 self.write_function_variadic_type(r#variadic_type);
352 }
353 };
354
355 self.pop_indentation();
356 self.push_new_line();
357 self.write_indentation();
358 }
359 }
360
361 fn write_variable(&mut self, variable: &nodes::Variable) {
362 use nodes::Variable::*;
363 match variable {
364 Identifier(identifier) => self.push_str(identifier.get_name()),
365 Field(field) => self.write_field(field),
366 Index(index) => self.write_index(index),
367 }
368 }
369
370 fn write_typed_identifier(&mut self, typed_identifier: &nodes::TypedIdentifier) {
371 self.push_str(typed_identifier.get_name());
372
373 if let Some(r#type) = typed_identifier.get_type() {
374 self.push_char(':');
375 self.push_space();
376 self.write_type(r#type);
377 }
378 }
379
380 fn write_function_return_type(&mut self, return_type: &nodes::FunctionReturnType) {
381 match return_type {
382 nodes::FunctionReturnType::Type(r#type) => self.write_type(r#type),
383 nodes::FunctionReturnType::TypePack(type_pack) => self.write_type_pack(type_pack),
384 nodes::FunctionReturnType::VariadicTypePack(variadic_type_pack) => {
385 self.write_variadic_type_pack(variadic_type_pack);
386 }
387 nodes::FunctionReturnType::GenericTypePack(generic_type_pack) => {
388 self.write_generic_type_pack(generic_type_pack);
389 }
390 }
391 }
392
393 fn write_function_return_type_suffix(&mut self, return_type: &nodes::FunctionReturnType) {
394 self.raw_push_char(':');
395 self.raw_push_char(' ');
396 self.write_function_return_type(return_type);
397 }
398
399 fn write_expression_in_parentheses(&mut self, expression: &nodes::Expression) {
400 self.push_char('(');
401 self.write_expression(expression);
402 self.push_char(')');
403 }
404
405 fn write_type_in_parentheses(&mut self, r#type: &nodes::Type) {
406 self.push_char('(');
407 self.write_type(r#type);
408 self.push_char(')');
409 }
410
411 fn write_function_generics(&mut self, generics: &nodes::GenericParameters) {
412 if generics.is_empty() {
413 return;
414 }
415 self.push_char('<');
416 let mut write_comma = false;
417 for type_variable in generics.iter_type_variable() {
418 if write_comma {
419 self.push_char(',');
420 self.push_char(' ');
421 } else {
422 write_comma = true;
423 }
424 self.write_identifier(type_variable);
425 }
426 for generic_pack in generics.iter_generic_type_pack() {
427 if write_comma {
428 self.push_char(',');
429 self.push_char(' ');
430 } else {
431 write_comma = true;
432 }
433 self.write_generic_type_pack(generic_pack);
434 }
435 self.push_char('>');
436 }
437}
438
439impl Default for ReadableLuaGenerator {
440 fn default() -> Self {
441 Self::new(80)
442 }
443}
444
445impl LuaGenerator for ReadableLuaGenerator {
446 fn into_string(self) -> String {
447 self.output
448 }
449
450 fn write_block(&mut self, block: &nodes::Block) {
451 let mut statements = block.iter_statements().peekable();
452
453 while let Some(statement) = statements.next() {
454 let current_type: StatementType = statement.into();
455
456 self.push_can_add_new_line(false);
457 self.write_statement(statement);
458
459 if let Some(next_statement) = statements.peek() {
460 if utils::starts_with_parenthese(next_statement)
461 && utils::ends_with_prefix(statement)
462 {
463 self.push_char(';');
464 }
465
466 if current_type != (*next_statement).into() {
467 self.push_new_line();
468 }
469 }
470
471 self.pop_can_add_new_line();
472 self.push_new_line();
473 }
474
475 if let Some(last_statement) = block.get_last_statement() {
476 if block.iter_statements().next().is_some() {
477 self.push_new_line();
478 }
479 self.write_last_statement(last_statement);
480 self.push_new_line();
481 }
482 }
483
484 fn write_last_statement(&mut self, statement: &nodes::LastStatement) {
485 use nodes::LastStatement::*;
486
487 match statement {
488 Break(_) => self.push_str("break"),
489 Continue(_) => self.push_str("continue"),
490 Return(expressions) => {
491 self.push_str("return");
492 self.push_can_add_new_line(false);
493 let last_index = expressions.len().saturating_sub(1);
494
495 if !expressions.is_empty() {
496 self.raw_push_char(' ');
497 }
498
499 expressions
500 .iter_expressions()
501 .enumerate()
502 .for_each(|(index, expression)| {
503 self.write_expression(expression);
504
505 if index != last_index {
506 self.raw_push_char(',');
507 self.raw_push_char(' ');
508 }
509 });
510
511 self.pop_can_add_new_line();
512 }
513 }
514 }
515
516 fn write_assign_statement(&mut self, assign: &nodes::AssignStatement) {
517 self.push_can_add_new_line(false);
518
519 let variables = assign.get_variables();
520 let last_variable_index = variables.len() - 1;
521 variables.iter().enumerate().for_each(|(index, variable)| {
522 self.write_variable(variable);
523
524 if index != last_variable_index {
525 self.raw_push_char(',');
526 self.raw_push_char(' ');
527 }
528 });
529
530 self.raw_push_str(" = ");
531
532 let last_value_index = assign.values_len() - 1;
533 assign.iter_values().enumerate().for_each(|(index, value)| {
534 self.write_expression(value);
535
536 if index != last_value_index {
537 self.raw_push_char(',');
538 self.raw_push_char(' ');
539 }
540 });
541
542 self.pop_can_add_new_line();
543 }
544
545 fn write_local_assign(&mut self, assign: &nodes::LocalAssignStatement) {
546 self.push_str("local ");
547
548 self.push_can_add_new_line(false);
549
550 let variables = assign.get_variables();
551 let last_variable_index = variables.len().saturating_sub(1);
552
553 variables.iter().enumerate().for_each(|(index, variable)| {
554 self.write_typed_identifier(variable);
555
556 if index != last_variable_index {
557 self.raw_push_char(',');
558 self.raw_push_char(' ');
559 }
560 });
561
562 if assign.has_values() {
563 self.raw_push_str(" = ");
564
565 let last_value_index = assign.values_len() - 1;
566
567 assign.iter_values().enumerate().for_each(|(index, value)| {
568 self.write_expression(value);
569
570 if index != last_value_index {
571 self.raw_push_char(',');
572 self.raw_push_char(' ');
573 }
574 });
575 };
576
577 self.pop_can_add_new_line();
578 }
579
580 fn write_compound_assign(&mut self, assign: &nodes::CompoundAssignStatement) {
581 self.push_can_add_new_line(false);
582
583 self.write_variable(assign.get_variable());
584
585 self.raw_push_char(' ');
586 self.raw_push_str(assign.get_operator().to_str());
587 self.push_space();
588
589 self.write_expression(assign.get_value());
590
591 self.pop_can_add_new_line();
592 }
593
594 fn write_local_function(&mut self, function: &nodes::LocalFunctionStatement) {
595 self.push_str("local function ");
596 self.raw_push_str(function.get_name());
597
598 if let Some(generics) = function.get_generic_parameters() {
599 self.write_function_generics(generics);
600 }
601
602 self.raw_push_char('(');
603
604 let parameters = function.get_parameters();
605 self.write_function_parameters(
606 parameters,
607 function.is_variadic(),
608 function.get_variadic_type(),
609 );
610 self.raw_push_char(')');
611
612 if let Some(return_type) = function.get_return_type() {
613 self.write_function_return_type_suffix(return_type);
614 }
615
616 let block = function.get_block();
617
618 if block.is_empty() {
619 self.raw_push_str(" end");
620 } else {
621 self.push_new_line();
622 self.indent_and_write_block(block);
623 self.push_str("end");
624 }
625 }
626
627 fn write_generic_for(&mut self, generic_for: &nodes::GenericForStatement) {
628 self.push_str("for ");
629
630 let identifiers = generic_for.get_identifiers();
631 let last_identifier_index = identifiers.len().saturating_sub(1);
632 identifiers
633 .iter()
634 .enumerate()
635 .for_each(|(index, identifier)| {
636 self.write_typed_identifier(identifier);
637
638 if index != last_identifier_index {
639 self.raw_push_char(',');
640 self.raw_push_char(' ');
641 }
642 });
643
644 self.raw_push_str(" in ");
645
646 let expressions = generic_for.get_expressions();
647 let last_expression_index = expressions.len().saturating_sub(1);
648 expressions
649 .iter()
650 .enumerate()
651 .for_each(|(index, expression)| {
652 self.write_expression(expression);
653
654 if index != last_expression_index {
655 self.raw_push_char(',');
656 self.raw_push_char(' ');
657 }
658 });
659
660 let block = generic_for.get_block();
661
662 if block.is_empty() {
663 self.raw_push_str(" do end");
664 } else {
665 self.push_str("do");
666 self.push_new_line();
667 self.indent_and_write_block(block);
668 self.push_str("end");
669 }
670 }
671
672 fn write_numeric_for(&mut self, numeric_for: &nodes::NumericForStatement) {
673 self.push_str("for ");
674
675 self.write_typed_identifier(numeric_for.get_identifier());
676 self.raw_push_char(' ');
677 self.raw_push_char('=');
678 self.raw_push_char(' ');
679 self.write_expression(numeric_for.get_start());
680 self.raw_push_char(',');
681 self.raw_push_char(' ');
682 self.write_expression(numeric_for.get_end());
683
684 if let Some(step) = numeric_for.get_step() {
685 self.raw_push_char(',');
686 self.raw_push_char(' ');
687 self.write_expression(step);
688 }
689
690 let block = numeric_for.get_block();
691
692 if block.is_empty() {
693 self.raw_push_str(" do end");
694 } else {
695 self.push_str("do");
696 self.push_new_line();
697 self.indent_and_write_block(block);
698 self.push_str("end");
699 }
700 }
701
702 fn write_if_statement(&mut self, if_statement: &nodes::IfStatement) {
703 let branches = if_statement.get_branches();
704
705 branches.iter().enumerate().for_each(|(index, branch)| {
706 if index == 0 {
707 self.push_str("if ");
708 } else {
709 self.push_str("elseif ");
710 }
711
712 self.write_expression(branch.get_condition());
713 self.raw_push_str(" then");
714 self.push_new_line();
715 self.indent_and_write_block(branch.get_block());
716 });
717
718 if let Some(else_block) = if_statement.get_else_block() {
719 self.push_str("else");
720 self.push_new_line();
721 self.indent_and_write_block(else_block);
722 }
723
724 self.push_str("end");
725 }
726
727 fn write_function_statement(&mut self, function: &nodes::FunctionStatement) {
728 self.push_str("function ");
729 let name = function.get_name();
730
731 self.raw_push_str(name.get_name().get_name());
732 name.get_field_names().iter().for_each(|field| {
733 self.raw_push_char('.');
734 self.raw_push_str(field.get_name());
735 });
736
737 if let Some(method) = name.get_method() {
738 self.raw_push_char(':');
739 self.raw_push_str(method.get_name());
740 }
741
742 if let Some(generics) = function.get_generic_parameters() {
743 self.write_function_generics(generics);
744 }
745
746 self.raw_push_char('(');
747 self.write_function_parameters(
748 function.get_parameters(),
749 function.is_variadic(),
750 function.get_variadic_type(),
751 );
752 self.raw_push_char(')');
753
754 if let Some(return_type) = function.get_return_type() {
755 self.write_function_return_type_suffix(return_type);
756 }
757
758 let block = function.get_block();
759
760 if block.is_empty() {
761 self.raw_push_str(" end");
762 } else {
763 self.push_new_line();
764 self.indent_and_write_block(block);
765 self.push_str("end");
766 }
767 }
768
769 fn write_do_statement(&mut self, do_statement: &nodes::DoStatement) {
770 let block = do_statement.get_block();
771
772 if block.is_empty() {
773 self.push_str("do end");
774 } else {
775 self.push_str("do");
776 self.push_new_line();
777 self.indent_and_write_block(block);
778 self.push_str("end");
779 }
780 }
781
782 fn write_repeat_statement(&mut self, repeat: &nodes::RepeatStatement) {
783 self.push_str("repeat");
784
785 let block = repeat.get_block();
786
787 if block.is_empty() {
788 self.raw_push_str(" until ");
789 } else {
790 self.push_new_line();
791 self.indent_and_write_block(block);
792 self.push_str("until ");
793 }
794
795 self.write_expression(repeat.get_condition());
796 }
797
798 fn write_while_statement(&mut self, while_statement: &nodes::WhileStatement) {
799 self.push_str("while");
800 self.push_can_add_new_line(false);
801 self.write_expression(while_statement.get_condition());
802 self.pop_can_add_new_line();
803
804 let block = while_statement.get_block();
805
806 if block.is_empty() {
807 self.raw_push_str(" do end");
808 } else {
809 self.raw_push_str(" do");
810 self.push_new_line();
811 self.indent_and_write_block(block);
812 self.push_str("end");
813 }
814 }
815
816 fn write_type_declaration_statement(&mut self, statement: &nodes::TypeDeclarationStatement) {
817 if statement.is_exported() {
818 self.push_str("export");
819 }
820 self.push_can_add_new_line(false);
821 self.push_str("type");
822
823 self.write_identifier(statement.get_name());
824
825 if let Some(generic_parameters) = statement
826 .get_generic_parameters()
827 .filter(|generic_parameters| !generic_parameters.is_empty())
828 {
829 self.push_char('<');
830 let last_index = generic_parameters.len().saturating_sub(1);
831 for (i, parameter) in generic_parameters.iter().enumerate() {
832 use nodes::GenericParameterRef;
833
834 match parameter {
835 GenericParameterRef::TypeVariable(identifier) => {
836 self.write_identifier(identifier);
837 }
838 GenericParameterRef::TypeVariableWithDefault(identifier_with_default) => {
839 self.write_identifier(identifier_with_default.get_type_variable());
840 self.push_char('=');
841 self.write_type(identifier_with_default.get_default_type());
842 }
843 GenericParameterRef::GenericTypePack(generic_type_pack) => {
844 self.write_generic_type_pack(generic_type_pack);
845 }
846 GenericParameterRef::GenericTypePackWithDefault(generic_pack_with_default) => {
847 self.write_generic_type_pack(
848 generic_pack_with_default.get_generic_type_pack(),
849 );
850 self.push_char('=');
851 self.write_generic_type_pack_default(
852 generic_pack_with_default.get_default_type(),
853 );
854 }
855 }
856
857 if i != last_index {
858 self.push_char(',');
859 self.push_char(' ');
860 }
861 }
862 self.push_char('>');
863 }
864
865 self.push_char(' ');
866 self.push_char('=');
867 self.push_char(' ');
868
869 self.pop_can_add_new_line();
870
871 self.write_type(statement.get_type());
872 }
873
874 fn write_false_expression(&mut self, _token: &Option<nodes::Token>) {
875 self.push_str("false");
876 }
877
878 fn write_true_expression(&mut self, _token: &Option<nodes::Token>) {
879 self.push_str("true");
880 }
881
882 fn write_nil_expression(&mut self, _token: &Option<nodes::Token>) {
883 self.push_str("nil");
884 }
885
886 fn write_variable_arguments_expression(&mut self, _token: &Option<nodes::Token>) {
887 self.push_str_and_break_if("...", utils::break_variable_arguments);
888 }
889
890 fn write_binary_expression(&mut self, binary: &nodes::BinaryExpression) {
891 let operator = binary.operator();
892 let left = binary.left();
893 let right = binary.right();
894
895 if operator.left_needs_parentheses(left) {
896 self.write_expression_in_parentheses(left);
897 } else {
898 self.write_expression(left);
899 }
900
901 self.push_space();
902 self.push_str(binary.operator().to_str());
903 self.push_space();
904
905 if operator.right_needs_parentheses(right) {
906 self.write_expression_in_parentheses(right);
907 } else {
908 self.write_expression(right);
909 }
910 }
911
912 fn write_unary_expression(&mut self, unary: &nodes::UnaryExpression) {
913 use nodes::{Expression, UnaryOperator::*};
914
915 match unary.operator() {
916 Length => self.push_char('#'),
917 Minus => self.push_str_and_break_if("-", utils::break_minus),
918 Not => self.push_str("not "),
919 }
920
921 let expression = unary.get_expression();
922
923 match expression {
924 Expression::Binary(binary) if !binary.operator().precedes_unary_expression() => {
925 self.write_expression_in_parentheses(expression);
926 }
927 _ => self.write_expression(expression),
928 }
929 }
930
931 fn write_function(&mut self, function: &nodes::FunctionExpression) {
932 self.push_str("function");
933
934 if let Some(generics) = function.get_generic_parameters() {
935 self.write_function_generics(generics);
936 }
937
938 self.push_char('(');
939
940 let parameters = function.get_parameters();
941 self.write_function_parameters(
942 parameters,
943 function.is_variadic(),
944 function.get_variadic_type(),
945 );
946 self.raw_push_char(')');
947
948 if let Some(return_type) = function.get_return_type() {
949 self.write_function_return_type_suffix(return_type);
950 }
951
952 let block = function.get_block();
953
954 if block.is_empty() {
955 self.raw_push_str(" end");
956 } else {
957 self.push_new_line();
958 self.indent_and_write_block(block);
959 self.push_str("end");
960 }
961 }
962
963 fn write_function_call(&mut self, call: &nodes::FunctionCall) {
964 self.push_can_add_new_line(false);
965 self.write_prefix(call.get_prefix());
966
967 if let Some(method) = &call.get_method() {
968 self.push_char(':');
969 self.push_str(method.get_name());
970 }
971
972 self.write_arguments(call.get_arguments());
973
974 self.pop_can_add_new_line();
975 }
976
977 fn write_tuple_arguments(&mut self, arguments: &nodes::TupleArguments) {
978 self.raw_push_char('(');
979
980 let last_index = arguments.len().saturating_sub(1);
981 arguments
982 .iter_values()
983 .enumerate()
984 .for_each(|(index, expression)| {
985 self.write_expression(expression);
986
987 if index != last_index {
988 self.raw_push_char(',');
989 self.raw_push_char(' ');
990 }
991 });
992
993 self.push_char(')');
994 }
995
996 fn write_field(&mut self, field: &nodes::FieldExpression) {
997 self.push_can_add_new_line(false);
998 self.write_prefix(field.get_prefix());
999 self.pop_can_add_new_line();
1000
1001 self.push_new_line_if_needed(1);
1002 self.raw_push_char('.');
1003 self.raw_push_str(field.get_field().get_name());
1004 }
1005
1006 fn write_index(&mut self, index: &nodes::IndexExpression) {
1007 self.push_can_add_new_line(false);
1008
1009 self.write_prefix(index.get_prefix());
1010
1011 self.push_char('[');
1012 self.write_expression(index.get_index());
1013 self.push_char(']');
1014
1015 self.pop_can_add_new_line();
1016 }
1017
1018 fn write_if_expression(&mut self, if_expression: &nodes::IfExpression) {
1019 self.push_str("if");
1020 self.write_expression(if_expression.get_condition());
1021
1022 if if_expression.has_elseif_branch() {
1023 self.push_indentation();
1024
1025 self.push_new_line();
1026 self.write_indentation();
1027 self.push_str("then");
1028 self.write_expression(if_expression.get_result());
1029
1030 for branch in if_expression.iter_branches() {
1031 self.push_new_line();
1032 self.write_indentation();
1033 self.push_str("elseif");
1034 self.write_expression(branch.get_condition());
1035
1036 self.push_new_line();
1037 self.write_indentation();
1038 self.push_str("then");
1039 self.write_expression(branch.get_result());
1040 }
1041
1042 self.push_new_line();
1043 self.write_indentation();
1044 self.push_str("else");
1045 self.write_expression(if_expression.get_else_result());
1046
1047 self.pop_indentation();
1048 } else {
1049 self.push_str("then");
1050 self.write_expression(if_expression.get_result());
1051 self.push_str("else");
1052 self.write_expression(if_expression.get_else_result());
1053 }
1054 }
1055
1056 fn write_table(&mut self, table: &nodes::TableExpression) {
1057 self.push_char('{');
1058
1059 let entries = table.get_entries();
1060 let table_len = entries.len();
1061
1062 if table_len == 0 {
1063 self.raw_push_char('}');
1064 } else {
1065 let column_space = self.column_span.saturating_sub(self.current_line_length);
1066 if self.table_fits_on_line(entries, column_space) {
1067 let last_index = table_len.saturating_sub(1);
1068
1069 entries.iter().enumerate().for_each(|(index, entry)| {
1070 self.write_table_entry(entry);
1071
1072 if index != last_index {
1073 self.raw_push_char(',');
1074 self.raw_push_char(' ');
1075 }
1076 });
1077 } else {
1078 self.push_indentation();
1079
1080 entries.iter().for_each(|entry| {
1081 self.push_new_line();
1082 self.write_indentation();
1083 self.write_table_entry(entry);
1084
1085 self.raw_push_char(',');
1086 });
1087
1088 self.pop_indentation();
1089 self.push_new_line();
1090 }
1091
1092 self.push_char('}');
1093 }
1094 }
1095
1096 fn write_table_entry(&mut self, entry: &nodes::TableEntry) {
1097 match entry {
1098 nodes::TableEntry::Field(entry) => {
1099 self.raw_push_str(entry.get_field().get_name());
1100 self.raw_push_str(" = ");
1101 self.write_expression(entry.get_value());
1102 }
1103 nodes::TableEntry::Index(entry) => {
1104 self.raw_push_char('[');
1105 self.push_can_add_new_line(false);
1106 self.write_expression(entry.get_key());
1107 self.pop_can_add_new_line();
1108 self.raw_push_str("] = ");
1109 self.write_expression(entry.get_value());
1110 }
1111 nodes::TableEntry::Value(expression) => self.write_expression(expression),
1112 }
1113 }
1114
1115 fn write_number(&mut self, number: &nodes::NumberExpression) {
1116 self.push_str(&utils::write_number(number));
1117 }
1118
1119 fn write_string(&mut self, string: &nodes::StringExpression) {
1120 let result = utils::write_string(string.get_value());
1121 if result.starts_with('[') {
1122 self.push_str_and_break_if(&result, utils::break_long_string);
1123 } else {
1124 self.push_str(&result);
1125 }
1126 }
1127
1128 fn write_interpolated_string(
1129 &mut self,
1130 interpolated_string: &nodes::InterpolatedStringExpression,
1131 ) {
1132 self.push_char('`');
1133
1134 for segment in interpolated_string.iter_segments() {
1135 match segment {
1136 nodes::InterpolationSegment::String(string_segment) => {
1137 self.raw_push_str(&utils::write_interpolated_string_segment(string_segment));
1138 }
1139 nodes::InterpolationSegment::Value(value) => {
1140 self.raw_push_char('{');
1141 let expression = value.get_expression();
1143 if utils::starts_with_table(expression).is_some() {
1144 self.raw_push_char(' ');
1145 }
1146 self.write_expression(expression);
1147 self.push_char('}');
1148 }
1149 }
1150 }
1151
1152 self.raw_push_char('`');
1153 }
1154
1155 fn write_identifier(&mut self, identifier: &nodes::Identifier) {
1156 self.push_str(identifier.get_name());
1157 }
1158
1159 fn write_parenthese(&mut self, parenthese: &nodes::ParentheseExpression) {
1160 self.push_char('(');
1161 self.push_can_add_new_line(false);
1162
1163 self.write_expression(parenthese.inner_expression());
1164
1165 self.pop_can_add_new_line();
1166 self.push_char(')');
1167 }
1168
1169 fn write_type_cast(&mut self, type_cast: &nodes::TypeCastExpression) {
1170 let inner_expression = type_cast.get_expression();
1171
1172 if nodes::TypeCastExpression::needs_parentheses(inner_expression) {
1173 self.push_char('(');
1174 self.push_can_add_new_line(false);
1175 self.write_expression(inner_expression);
1176 self.pop_can_add_new_line();
1177 self.push_char(')');
1178 } else {
1179 self.write_expression(inner_expression);
1180 }
1181
1182 self.push_can_add_new_line(false);
1183 self.push_str("::");
1184 self.write_type(type_cast.get_type());
1185 self.pop_can_add_new_line();
1186 }
1187
1188 fn write_type_name(&mut self, type_name: &nodes::TypeName) {
1189 self.write_identifier(type_name.get_type_name());
1190 if let Some(parameters) = type_name.get_type_parameters() {
1191 self.push_char('<');
1192 self.push_can_add_new_line(false);
1193 let last_index = parameters.len().saturating_sub(1);
1194 for (index, parameter) in parameters.iter().enumerate() {
1195 self.write_type_parameter(parameter);
1196 if index != last_index {
1197 self.push_char(',');
1198 self.push_char(' ');
1199 }
1200 }
1201
1202 self.pop_can_add_new_line();
1203 self.push_char('>');
1204 }
1205 }
1206
1207 fn write_type_field(&mut self, type_field: &nodes::TypeField) {
1208 self.write_identifier(type_field.get_namespace());
1209 self.push_new_line_if_needed(1);
1210 self.raw_push_char('.');
1211 self.write_type_name(type_field.get_type_name());
1212 }
1213
1214 fn write_true_type(&mut self, _: &Option<nodes::Token>) {
1215 self.push_str("true");
1216 }
1217
1218 fn write_false_type(&mut self, _: &Option<nodes::Token>) {
1219 self.push_str("false");
1220 }
1221
1222 fn write_nil_type(&mut self, _: &Option<nodes::Token>) {
1223 self.push_str("nil");
1224 }
1225
1226 fn write_string_type(&mut self, string_type: &nodes::StringType) {
1227 let result = utils::write_string(string_type.get_value());
1228 if result.starts_with('[') {
1229 self.push_str_and_break_if(&result, utils::break_long_string);
1230 } else {
1231 self.push_str(&result);
1232 }
1233 }
1234
1235 fn write_array_type(&mut self, array: &nodes::ArrayType) {
1236 self.push_char('{');
1237 self.write_type(array.get_element_type());
1238 self.push_char('}');
1239 }
1240
1241 fn write_table_type(&mut self, table_type: &nodes::TableType) {
1242 self.push_char('{');
1243
1244 let last_index = table_type.len().saturating_sub(1);
1245 for (index, property) in table_type.iter_entries().enumerate() {
1246 match property {
1247 nodes::TableEntryType::Property(property) => {
1248 self.write_identifier(property.get_identifier());
1249 self.push_char(':');
1250 self.push_char(' ');
1251 self.write_type(property.get_type());
1252 }
1253 nodes::TableEntryType::Literal(property) => {
1254 self.push_char('[');
1255 self.write_string_type(property.get_string());
1256 self.push_char(']');
1257 self.push_char(':');
1258 self.push_char(' ');
1259 self.write_type(property.get_type());
1260 }
1261 nodes::TableEntryType::Indexer(indexer) => {
1262 self.push_char('[');
1263
1264 let key_type = indexer.get_key_type();
1265
1266 let need_parentheses = matches!(
1267 key_type,
1268 nodes::Type::Optional(_)
1269 | nodes::Type::Intersection(_)
1270 | nodes::Type::Union(_)
1271 );
1272
1273 if need_parentheses {
1274 self.push_char('(');
1275 self.write_type(key_type);
1276 self.push_char(')');
1277 } else {
1278 self.write_type(key_type);
1279 }
1280
1281 self.push_char(']');
1282 self.push_char(':');
1283 self.push_char(' ');
1284 self.write_type(indexer.get_value_type());
1285 }
1286 }
1287 if index != last_index {
1288 self.push_char(',');
1289 self.push_char(' ');
1290 }
1291 }
1292
1293 self.push_char('}');
1294 }
1295
1296 fn write_expression_type(&mut self, expression_type: &nodes::ExpressionType) {
1297 self.push_str("typeof(");
1298 self.write_expression(expression_type.get_expression());
1299 self.push_char(')');
1300 }
1301
1302 fn write_parenthese_type(&mut self, parenthese_type: &nodes::ParentheseType) {
1303 self.write_type_in_parentheses(parenthese_type.get_inner_type());
1304 }
1305
1306 fn write_function_type(&mut self, function_type: &nodes::FunctionType) {
1307 if let Some(generics) = function_type.get_generic_parameters() {
1308 self.write_function_generics(generics);
1309 }
1310
1311 self.push_char('(');
1312
1313 let last_index = function_type.argument_len().saturating_sub(1);
1314
1315 for (index, argument) in function_type.iter_arguments().enumerate() {
1316 if let Some(name) = argument.get_name() {
1317 self.write_identifier(name);
1318 self.push_char(':');
1319 }
1320 self.write_type(argument.get_type());
1321
1322 if index != last_index {
1323 self.push_char(',');
1324 self.push_space();
1325 }
1326 }
1327
1328 if let Some(variadic_argument_type) = function_type.get_variadic_argument_type() {
1329 if function_type.argument_len() > 0 {
1330 self.push_char(',');
1331 self.push_space();
1332 }
1333 self.write_variadic_argument_type(variadic_argument_type);
1334 }
1335
1336 self.push_str(") -> ");
1337 self.write_function_return_type(function_type.get_return_type());
1338 }
1339
1340 fn write_optional_type(&mut self, optional: &nodes::OptionalType) {
1341 let inner_type = optional.get_inner_type();
1342 if nodes::OptionalType::needs_parentheses(inner_type) {
1343 self.write_type_in_parentheses(inner_type);
1344 } else {
1345 self.write_type(inner_type);
1346 }
1347 self.push_char('?');
1348 }
1349
1350 fn write_intersection_type(&mut self, intersection: &nodes::IntersectionType) {
1351 if intersection.has_leading_token() {
1352 self.push_char('&');
1353 }
1354
1355 let length = intersection.len();
1356 let last_index = length.saturating_sub(1);
1357
1358 for (i, r#type) in intersection.iter_types().enumerate() {
1359 if i != 0 {
1360 self.push_char('&');
1361 }
1362
1363 let need_parentheses = if i == last_index {
1364 nodes::IntersectionType::last_needs_parentheses(r#type)
1365 } else {
1366 nodes::IntersectionType::intermediate_needs_parentheses(r#type)
1367 };
1368
1369 if need_parentheses {
1370 self.write_type_in_parentheses(r#type);
1371 } else {
1372 self.write_type(r#type);
1373 }
1374 }
1375 }
1376
1377 fn write_union_type(&mut self, union: &nodes::UnionType) {
1378 let length = union.len();
1379 let last_index = length.saturating_sub(1);
1380
1381 if union.has_leading_token() {
1382 self.push_char('|');
1383 self.push_space();
1384 }
1385
1386 for (i, r#type) in union.iter_types().enumerate() {
1387 if i != 0 {
1388 self.push_space();
1389 self.push_char('|');
1390 self.push_space();
1391 }
1392
1393 let need_parentheses = if i == last_index {
1394 nodes::UnionType::last_needs_parentheses(r#type)
1395 } else {
1396 nodes::UnionType::intermediate_needs_parentheses(r#type)
1397 };
1398
1399 if need_parentheses {
1400 self.write_type_in_parentheses(r#type);
1401 } else {
1402 self.write_type(r#type);
1403 }
1404 }
1405 }
1406
1407 fn write_type_pack(&mut self, type_pack: &nodes::TypePack) {
1408 self.push_char('(');
1409
1410 let last_index = type_pack.len().saturating_sub(1);
1411
1412 for (index, r#type) in type_pack.into_iter().enumerate() {
1413 self.write_type(r#type);
1414 if index != last_index {
1415 self.push_char(',');
1416 }
1417 }
1418
1419 if let Some(variadic_argument_type) = type_pack.get_variadic_type() {
1420 if !type_pack.is_empty() {
1421 self.push_char(',');
1422 }
1423 self.write_variadic_argument_type(variadic_argument_type);
1424 }
1425
1426 self.push_char(')');
1427 }
1428
1429 fn write_variadic_type_pack(&mut self, variadic_type_pack: &nodes::VariadicTypePack) {
1430 self.push_str("...");
1431 self.write_type(variadic_type_pack.get_type());
1432 }
1433
1434 fn write_generic_type_pack(&mut self, generic_type_pack: &nodes::GenericTypePack) {
1435 self.write_identifier(generic_type_pack.get_name());
1436 self.push_str("...");
1437 }
1438}