darklua_core/generator/
dense.rs

1use crate::generator::{utils, LuaGenerator};
2use crate::nodes;
3
4/// This implementation of [LuaGenerator](trait.LuaGenerator.html) attempts to produce Lua code as
5/// small as possible. It is not meant to be read by humans.
6#[derive(Debug, Clone)]
7pub struct DenseLuaGenerator {
8    column_span: usize,
9    current_line_length: usize,
10    output: String,
11    last_push_length: usize,
12}
13
14impl DenseLuaGenerator {
15    /// Creates a generator that will wrap the code on a new line after the amount of
16    /// characters given by the `column_span` argument.
17    pub fn new(column_span: usize) -> Self {
18        Self {
19            column_span,
20            current_line_length: 0,
21            output: String::new(),
22            last_push_length: 0,
23        }
24    }
25
26    /// Appends a string to the current content of the DenseLuaGenerator. A space may be added
27    /// depending of the last character of the current content and the first character pushed.
28    fn push_str(&mut self, content: &str) {
29        if let Some(next_char) = content.chars().next() {
30            self.push_space_if_needed(next_char, content.len());
31            self.raw_push_str(content);
32        }
33    }
34
35    /// Same as the `push_str` function, but for a single character.
36    fn push_char(&mut self, character: char) {
37        self.push_space_if_needed(character, 1);
38
39        self.output.push(character);
40        self.current_line_length += 1;
41        self.last_push_length = 1;
42    }
43
44    /// This function pushes a character into the string, without appending a new line
45    /// or a space between the last pushed content.
46    fn merge_char(&mut self, character: char) {
47        if self.fits_on_current_line(1) {
48            self.raw_push_char(character);
49        } else {
50            let last_push_content = self.get_last_push_str().to_owned();
51            (0..self.last_push_length).for_each(|_| {
52                self.output.pop();
53            });
54
55            let mut last_char = self.output.pop();
56
57            while let Some(' ') = last_char {
58                last_char = self.output.pop();
59            }
60
61            if let Some(last_char) = last_char {
62                self.output.push(last_char);
63            }
64
65            self.output.push('\n');
66            self.output.push_str(&last_push_content);
67            self.output.push(character);
68            self.last_push_length += 1;
69            self.current_line_length = self.last_push_length;
70        }
71    }
72
73    fn push_new_line_if_needed(&mut self, pushed_length: usize) {
74        if self.current_line_length >= self.column_span {
75            self.push_new_line();
76        } else {
77            let total_length = self.current_line_length + pushed_length;
78
79            if total_length > self.column_span {
80                self.push_new_line();
81            }
82        }
83    }
84
85    fn push_space_if_needed(&mut self, next_character: char, pushed_length: usize) {
86        if self.current_line_length >= self.column_span {
87            self.push_new_line();
88        } else {
89            let total_length = self.current_line_length + pushed_length;
90
91            if self.needs_space(next_character) {
92                if total_length + 1 > self.column_span {
93                    self.push_new_line();
94                } else {
95                    self.output.push(' ');
96                    self.current_line_length += 1;
97                }
98            } else if total_length > self.column_span {
99                self.push_new_line();
100            }
101        }
102    }
103
104    #[inline]
105    fn push_new_line(&mut self) {
106        self.output.push('\n');
107        self.current_line_length = 0;
108    }
109
110    #[inline]
111    fn push_space(&mut self) {
112        self.output.push(' ');
113        self.current_line_length += 1;
114    }
115
116    #[inline]
117    fn fits_on_current_line(&self, length: usize) -> bool {
118        self.current_line_length + length <= self.column_span
119    }
120
121    #[inline]
122    fn needs_space(&self, next_character: char) -> bool {
123        if let Some(previous) = self.output.chars().last() {
124            utils::should_break_with_space(previous, next_character)
125        } else {
126            false
127        }
128    }
129
130    /// Consumes the LuaGenerator and produce a String object.
131    pub fn into_string(self) -> String {
132        self.output
133    }
134
135    #[inline]
136    fn raw_push_str(&mut self, content: &str) {
137        self.output.push_str(content);
138        self.last_push_length = content.len();
139        self.current_line_length += self.last_push_length;
140    }
141
142    #[inline]
143    fn raw_push_char(&mut self, character: char) {
144        self.output.push(character);
145        self.last_push_length = 1;
146        self.current_line_length += 1;
147    }
148
149    /// This function only insert a space or a new line if the given predicate returns true. In
150    /// the other case, the string is added to the current generator content.
151    fn push_str_and_break_if<F>(&mut self, content: &str, predicate: F)
152    where
153        F: Fn(&str) -> bool,
154    {
155        if predicate(self.get_last_push_str()) {
156            if self.fits_on_current_line(1 + content.len()) {
157                self.push_space();
158            } else {
159                self.push_new_line();
160            }
161        } else if !self.fits_on_current_line(content.len()) {
162            self.push_new_line();
163        }
164        self.raw_push_str(content);
165    }
166
167    /// Same as `push_str_and_break_if` but for a single character
168    fn push_char_and_break_if<F>(&mut self, content: char, predicate: F)
169    where
170        F: Fn(&str) -> bool,
171    {
172        if predicate(self.get_last_push_str()) {
173            if self.fits_on_current_line(2) {
174                self.push_space();
175            } else {
176                self.push_new_line();
177            }
178        } else if !self.fits_on_current_line(1) {
179            self.push_new_line();
180        }
181        self.raw_push_char(content);
182    }
183
184    fn get_last_push_str(&self) -> &str {
185        self.output
186            .get((self.output.len() - self.last_push_length)..)
187            .unwrap_or("")
188    }
189
190    fn write_function_parameters(
191        &mut self,
192        parameters: &[nodes::TypedIdentifier],
193        is_variadic: bool,
194        variadic_type: Option<&nodes::FunctionVariadicType>,
195    ) {
196        let last_index = parameters.len().saturating_sub(1);
197
198        parameters.iter().enumerate().for_each(|(index, variable)| {
199            self.write_typed_identifier(variable);
200
201            if index != last_index {
202                self.push_char(',');
203            }
204        });
205
206        if is_variadic {
207            if !parameters.is_empty() {
208                self.push_char(',');
209            };
210            self.push_str("...");
211
212            if let Some(variadic_type) = variadic_type {
213                self.push_char(':');
214                self.write_function_variadic_type(variadic_type);
215            }
216        };
217    }
218
219    fn write_typed_identifier(&mut self, typed_identifier: &nodes::TypedIdentifier) {
220        self.push_str(typed_identifier.get_name());
221
222        if let Some(r#type) = typed_identifier.get_type() {
223            self.push_char(':');
224            self.write_type(r#type);
225        }
226    }
227
228    fn write_function_return_type(&mut self, return_type: &nodes::FunctionReturnType) {
229        match return_type {
230            nodes::FunctionReturnType::Type(r#type) => self.write_type(r#type),
231            nodes::FunctionReturnType::TypePack(type_pack) => self.write_type_pack(type_pack),
232            nodes::FunctionReturnType::VariadicTypePack(variadic_type_pack) => {
233                self.write_variadic_type_pack(variadic_type_pack);
234            }
235            nodes::FunctionReturnType::GenericTypePack(generic_type_pack) => {
236                self.write_generic_type_pack(generic_type_pack);
237            }
238        }
239    }
240
241    fn write_expression_in_parentheses(&mut self, expression: &nodes::Expression) {
242        self.push_char('(');
243        self.write_expression(expression);
244        self.push_char(')');
245    }
246
247    fn write_type_in_parentheses(&mut self, r#type: &nodes::Type) {
248        self.push_char('(');
249        self.write_type(r#type);
250        self.push_char(')');
251    }
252
253    fn write_function_generics(&mut self, generics: &nodes::GenericParameters) {
254        if generics.is_empty() {
255            return;
256        }
257        self.push_char('<');
258        let mut write_comma = false;
259        for type_variable in generics.iter_type_variable() {
260            if write_comma {
261                self.push_char(',');
262            } else {
263                write_comma = true;
264            }
265            self.write_identifier(type_variable);
266        }
267        for generic_pack in generics.iter_generic_type_pack() {
268            if write_comma {
269                self.push_char(',');
270            } else {
271                write_comma = true;
272            }
273            self.write_generic_type_pack(generic_pack);
274        }
275        self.push_char('>');
276    }
277}
278
279impl Default for DenseLuaGenerator {
280    fn default() -> Self {
281        Self::new(80)
282    }
283}
284
285impl LuaGenerator for DenseLuaGenerator {
286    /// Consumes the LuaGenerator and produce a String object.
287    fn into_string(self) -> String {
288        self.output
289    }
290
291    fn write_block(&mut self, block: &nodes::Block) {
292        let mut statements = block.iter_statements().peekable();
293
294        while let Some(statement) = statements.next() {
295            self.write_statement(statement);
296
297            if let Some(next_statement) = statements.peek() {
298                if utils::starts_with_parenthese(next_statement)
299                    && utils::ends_with_prefix(statement)
300                {
301                    self.push_char(';');
302                }
303            }
304        }
305
306        if let Some(last_statement) = block.get_last_statement() {
307            self.write_last_statement(last_statement);
308        }
309    }
310
311    fn write_assign_statement(&mut self, assign: &nodes::AssignStatement) {
312        let variables = assign.get_variables();
313        let last_variable_index = variables.len().saturating_sub(1);
314
315        variables.iter().enumerate().for_each(|(index, variable)| {
316            self.write_variable(variable);
317
318            if index != last_variable_index {
319                self.push_char(',');
320            }
321        });
322
323        self.push_char_and_break_if('=', utils::break_equal);
324
325        let last_value_index = assign.values_len().saturating_sub(1);
326
327        assign.iter_values().enumerate().for_each(|(index, value)| {
328            self.write_expression(value);
329
330            if index != last_value_index {
331                self.push_char(',');
332            }
333        });
334    }
335
336    fn write_do_statement(&mut self, do_statement: &nodes::DoStatement) {
337        self.push_str("do");
338        self.write_block(do_statement.get_block());
339        self.push_str("end");
340    }
341
342    fn write_generic_for(&mut self, generic_for: &nodes::GenericForStatement) {
343        self.push_str("for");
344
345        let identifiers = generic_for.get_identifiers();
346        let last_identifier_index = identifiers.len().saturating_sub(1);
347        identifiers
348            .iter()
349            .enumerate()
350            .for_each(|(index, identifier)| {
351                self.write_typed_identifier(identifier);
352
353                if index != last_identifier_index {
354                    self.push_char(',');
355                }
356            });
357        self.push_str("in");
358
359        let expressions = generic_for.get_expressions();
360        let last_expression_index = expressions.len().saturating_sub(1);
361        expressions
362            .iter()
363            .enumerate()
364            .for_each(|(index, expression)| {
365                self.write_expression(expression);
366
367                if index != last_expression_index {
368                    self.push_char(',');
369                }
370            });
371
372        self.push_str("do");
373        self.write_block(generic_for.get_block());
374        self.push_str("end");
375    }
376
377    fn write_if_statement(&mut self, if_statement: &nodes::IfStatement) {
378        let branches = if_statement.get_branches();
379
380        branches.iter().enumerate().for_each(|(index, branch)| {
381            if index == 0 {
382                self.push_str("if");
383            } else {
384                self.push_str("elseif");
385            }
386
387            self.write_expression(branch.get_condition());
388            self.push_str("then");
389            self.write_block(branch.get_block());
390        });
391
392        if let Some(else_block) = if_statement.get_else_block() {
393            self.push_str("else");
394            self.write_block(else_block)
395        }
396
397        self.push_str("end");
398    }
399
400    fn write_function_statement(&mut self, function: &nodes::FunctionStatement) {
401        self.push_str("function");
402        let name = function.get_name();
403
404        self.push_str(name.get_name().get_name());
405        name.get_field_names().iter().for_each(|field| {
406            self.push_new_line_if_needed(1);
407            self.raw_push_char('.');
408            self.push_str(field.get_name());
409        });
410
411        if let Some(method) = name.get_method() {
412            self.push_char(':');
413            self.push_str(method.get_name());
414        }
415
416        if let Some(generics) = function.get_generic_parameters() {
417            self.write_function_generics(generics);
418        }
419
420        self.push_char('(');
421        self.write_function_parameters(
422            function.get_parameters(),
423            function.is_variadic(),
424            function.get_variadic_type(),
425        );
426        self.push_char(')');
427
428        if let Some(return_type) = function.get_return_type() {
429            self.push_char(':');
430            self.write_function_return_type(return_type);
431        }
432
433        let block = function.get_block();
434
435        if !block.is_empty() {
436            self.write_block(block);
437        }
438        self.push_str("end");
439    }
440
441    fn write_last_statement(&mut self, statement: &nodes::LastStatement) {
442        use nodes::LastStatement::*;
443
444        match statement {
445            Break(_) => self.push_str("break"),
446            Continue(_) => self.push_str("continue"),
447            Return(expressions) => {
448                self.push_str("return");
449                let last_index = expressions.len().saturating_sub(1);
450
451                expressions
452                    .iter_expressions()
453                    .enumerate()
454                    .for_each(|(index, expression)| {
455                        self.write_expression(expression);
456
457                        if index != last_index {
458                            self.push_char(',');
459                        }
460                    });
461            }
462        }
463    }
464
465    fn write_local_assign(&mut self, assign: &nodes::LocalAssignStatement) {
466        self.push_str("local");
467
468        let variables = assign.get_variables();
469        let last_variable_index = variables.len().saturating_sub(1);
470
471        variables.iter().enumerate().for_each(|(index, variable)| {
472            self.write_typed_identifier(variable);
473
474            if index != last_variable_index {
475                self.push_char(',');
476            }
477        });
478
479        if assign.has_values() {
480            self.push_char_and_break_if('=', utils::break_equal);
481
482            let last_value_index = assign.values_len() - 1;
483
484            assign.iter_values().enumerate().for_each(|(index, value)| {
485                self.write_expression(value);
486
487                if index != last_value_index {
488                    self.push_char(',');
489                }
490            });
491        };
492    }
493
494    fn write_compound_assign(&mut self, assign: &nodes::CompoundAssignStatement) {
495        self.write_variable(assign.get_variable());
496
497        self.push_str(assign.get_operator().to_str());
498
499        self.write_expression(assign.get_value());
500    }
501
502    fn write_local_function(&mut self, function: &nodes::LocalFunctionStatement) {
503        self.push_str("local function");
504        self.push_str(function.get_name());
505
506        if let Some(generics) = function.get_generic_parameters() {
507            self.write_function_generics(generics);
508        }
509
510        self.push_char('(');
511
512        let parameters = function.get_parameters();
513        self.write_function_parameters(
514            parameters,
515            function.is_variadic(),
516            function.get_variadic_type(),
517        );
518        self.push_char(')');
519
520        if let Some(return_type) = function.get_return_type() {
521            self.push_char(':');
522            self.write_function_return_type(return_type);
523        }
524
525        let block = function.get_block();
526
527        if !block.is_empty() {
528            self.write_block(block);
529        }
530        self.push_str("end");
531    }
532
533    fn write_numeric_for(&mut self, numeric_for: &nodes::NumericForStatement) {
534        self.push_str("for");
535
536        self.write_typed_identifier(numeric_for.get_identifier());
537
538        self.push_char_and_break_if('=', utils::break_equal);
539
540        self.write_expression(numeric_for.get_start());
541        self.push_char(',');
542        self.write_expression(numeric_for.get_end());
543
544        if let Some(step) = numeric_for.get_step() {
545            self.push_char(',');
546            self.write_expression(step);
547        }
548
549        let block = numeric_for.get_block();
550
551        if block.is_empty() {
552            self.push_str("do end");
553        } else {
554            self.push_str("do");
555            self.write_block(block);
556            self.push_str("end");
557        }
558    }
559
560    fn write_repeat_statement(&mut self, repeat: &nodes::RepeatStatement) {
561        self.push_str("repeat");
562
563        let block = repeat.get_block();
564
565        if !block.is_empty() {
566            self.write_block(block);
567        }
568
569        self.push_str("until");
570        self.write_expression(repeat.get_condition());
571    }
572
573    fn write_while_statement(&mut self, while_statement: &nodes::WhileStatement) {
574        self.push_str("while");
575        self.write_expression(while_statement.get_condition());
576
577        let block = while_statement.get_block();
578
579        if block.is_empty() {
580            self.push_str("do end");
581        } else {
582            self.push_str("do");
583            self.write_block(block);
584            self.push_str("end");
585        }
586    }
587
588    fn write_type_declaration_statement(&mut self, statement: &nodes::TypeDeclarationStatement) {
589        if statement.is_exported() {
590            self.push_str("export");
591        }
592        self.push_str("type");
593
594        self.write_identifier(statement.get_name());
595
596        if let Some(generic_parameters) = statement
597            .get_generic_parameters()
598            .filter(|generic_parameters| !generic_parameters.is_empty())
599        {
600            self.push_char('<');
601            let last_index = generic_parameters.len().saturating_sub(1);
602            for (i, parameter) in generic_parameters.iter().enumerate() {
603                use nodes::GenericParameterRef;
604
605                match parameter {
606                    GenericParameterRef::TypeVariable(identifier) => {
607                        self.write_identifier(identifier);
608                    }
609                    GenericParameterRef::TypeVariableWithDefault(identifier_with_default) => {
610                        self.write_identifier(identifier_with_default.get_type_variable());
611                        self.push_char('=');
612                        self.write_type(identifier_with_default.get_default_type());
613                    }
614                    GenericParameterRef::GenericTypePack(generic_type_pack) => {
615                        self.write_generic_type_pack(generic_type_pack);
616                    }
617                    GenericParameterRef::GenericTypePackWithDefault(generic_pack_with_default) => {
618                        self.write_generic_type_pack(
619                            generic_pack_with_default.get_generic_type_pack(),
620                        );
621                        self.push_char('=');
622                        self.write_generic_type_pack_default(
623                            generic_pack_with_default.get_default_type(),
624                        );
625                    }
626                }
627
628                if i != last_index {
629                    self.push_char(',');
630                }
631            }
632
633            self.push_char('>');
634        }
635
636        self.push_char_and_break_if('=', utils::break_equal);
637        self.write_type(statement.get_type());
638    }
639
640    fn write_false_expression(&mut self, _token: &Option<nodes::Token>) {
641        self.push_str("false");
642    }
643
644    fn write_true_expression(&mut self, _token: &Option<nodes::Token>) {
645        self.push_str("true");
646    }
647
648    fn write_nil_expression(&mut self, _token: &Option<nodes::Token>) {
649        self.push_str("nil");
650    }
651
652    fn write_variable_arguments_expression(&mut self, _token: &Option<nodes::Token>) {
653        self.push_str_and_break_if("...", utils::break_variable_arguments);
654    }
655
656    fn write_binary_expression(&mut self, binary: &nodes::BinaryExpression) {
657        use nodes::BinaryOperator;
658
659        let operator = binary.operator();
660        let left = binary.left();
661        let right = binary.right();
662
663        if operator.left_needs_parentheses(left) {
664            self.write_expression_in_parentheses(left);
665        } else {
666            self.write_expression(left);
667        }
668
669        match operator {
670            BinaryOperator::Concat => self.push_str_and_break_if("..", utils::break_concat),
671            _ => self.push_str(operator.to_str()),
672        }
673
674        if operator.right_needs_parentheses(right) {
675            self.write_expression_in_parentheses(right);
676        } else {
677            self.write_expression(right);
678        }
679    }
680
681    fn write_unary_expression(&mut self, unary: &nodes::UnaryExpression) {
682        use nodes::{Expression, UnaryOperator::*};
683
684        match unary.operator() {
685            Length => self.push_char('#'),
686            Minus => self.push_char_and_break_if('-', utils::break_minus),
687            Not => self.push_str("not"),
688        }
689
690        let expression = unary.get_expression();
691
692        match expression {
693            Expression::Binary(binary) if !binary.operator().precedes_unary_expression() => {
694                self.write_expression_in_parentheses(expression);
695            }
696            _ => self.write_expression(expression),
697        }
698    }
699
700    fn write_function(&mut self, function: &nodes::FunctionExpression) {
701        self.push_str("function");
702
703        if let Some(generics) = function.get_generic_parameters() {
704            self.write_function_generics(generics);
705        }
706
707        self.push_char('(');
708
709        let parameters = function.get_parameters();
710        self.write_function_parameters(
711            parameters,
712            function.is_variadic(),
713            function.get_variadic_type(),
714        );
715        self.push_char(')');
716
717        if let Some(return_type) = function.get_return_type() {
718            self.push_char(':');
719            self.write_function_return_type(return_type);
720        }
721
722        let block = function.get_block();
723
724        if !block.is_empty() {
725            self.write_block(block);
726        }
727        self.push_str("end");
728    }
729
730    fn write_function_call(&mut self, call: &nodes::FunctionCall) {
731        self.write_prefix(call.get_prefix());
732
733        if let Some(method) = &call.get_method() {
734            self.push_char(':');
735            self.push_str(method.get_name());
736        }
737
738        self.write_arguments(call.get_arguments());
739    }
740
741    fn write_field(&mut self, field: &nodes::FieldExpression) {
742        self.write_prefix(field.get_prefix());
743
744        self.push_new_line_if_needed(1);
745        self.raw_push_char('.');
746
747        self.push_str(field.get_field().get_name());
748    }
749
750    fn write_index(&mut self, index: &nodes::IndexExpression) {
751        self.write_prefix(index.get_prefix());
752
753        self.push_char('[');
754        self.write_expression(index.get_index());
755        self.push_char(']');
756    }
757
758    fn write_if_expression(&mut self, if_expression: &nodes::IfExpression) {
759        self.push_str("if");
760        self.write_expression(if_expression.get_condition());
761        self.push_str("then");
762        self.write_expression(if_expression.get_result());
763
764        for branch in if_expression.iter_branches() {
765            self.push_str("elseif");
766            self.write_expression(branch.get_condition());
767            self.push_str("then");
768            self.write_expression(branch.get_result());
769        }
770
771        self.push_str("else");
772        self.write_expression(if_expression.get_else_result());
773    }
774
775    fn write_table(&mut self, table: &nodes::TableExpression) {
776        self.push_char('{');
777
778        let entries = table.get_entries();
779        let last_index = entries.len().saturating_sub(1);
780
781        entries.iter().enumerate().for_each(|(index, entry)| {
782            self.write_table_entry(entry);
783
784            if index != last_index {
785                self.push_char(',');
786            }
787        });
788
789        self.push_char('}');
790    }
791
792    fn write_table_entry(&mut self, entry: &nodes::TableEntry) {
793        match entry {
794            nodes::TableEntry::Field(entry) => {
795                self.push_str(entry.get_field().get_name());
796                self.push_char('=');
797                self.write_expression(entry.get_value());
798            }
799            nodes::TableEntry::Index(entry) => {
800                self.push_char('[');
801                self.write_expression(entry.get_key());
802                self.push_char(']');
803                self.push_char('=');
804                self.write_expression(entry.get_value());
805            }
806            nodes::TableEntry::Value(expression) => self.write_expression(expression),
807        }
808    }
809
810    fn write_number(&mut self, number: &nodes::NumberExpression) {
811        use nodes::NumberExpression::*;
812
813        match number {
814            Decimal(number) => {
815                let float = number.get_raw_float();
816                if float.is_nan() {
817                    self.push_char('(');
818                    self.push_char('0');
819                    self.push_char('/');
820                    self.push_char('0');
821                    self.push_char(')');
822                } else if float.is_infinite() {
823                    self.push_char('(');
824                    if float.is_sign_negative() {
825                        self.push_char('-');
826                    }
827                    self.push_char('1');
828                    self.push_char('/');
829                    self.push_char('0');
830                    self.push_char(')');
831                } else {
832                    let mut result = format!("{}", float);
833
834                    if let Some(exponent) = number.get_exponent() {
835                        let exponent_char = number
836                            .is_uppercase()
837                            .map(|is_uppercase| if is_uppercase { 'E' } else { 'e' })
838                            .unwrap_or('e');
839
840                        result.push(exponent_char);
841                        result.push_str(&format!("{}", exponent));
842                    };
843
844                    self.push_str(&result);
845                }
846            }
847            Hex(number) => {
848                let mut result = format!(
849                    "0{}{:x}",
850                    if number.is_x_uppercase() { 'X' } else { 'x' },
851                    number.get_raw_integer()
852                );
853
854                if let Some(exponent) = number.get_exponent() {
855                    let exponent_char = number
856                        .is_exponent_uppercase()
857                        .map(|is_uppercase| if is_uppercase { 'P' } else { 'p' })
858                        .unwrap_or('p');
859
860                    result.push(exponent_char);
861                    result.push_str(&format!("{}", exponent));
862                };
863
864                self.push_str(&result);
865            }
866            Binary(number) => {
867                self.push_str(&format!(
868                    "0{}{:b}",
869                    if number.is_b_uppercase() { 'B' } else { 'b' },
870                    number.get_raw_value()
871                ));
872            }
873        }
874    }
875
876    fn write_tuple_arguments(&mut self, arguments: &nodes::TupleArguments) {
877        self.merge_char('(');
878
879        let last_index = arguments.len().saturating_sub(1);
880        arguments
881            .iter_values()
882            .enumerate()
883            .for_each(|(index, expression)| {
884                self.write_expression(expression);
885
886                if index != last_index {
887                    self.push_char(',');
888                }
889            });
890
891        self.push_char(')');
892    }
893
894    fn write_string(&mut self, string: &nodes::StringExpression) {
895        let result = utils::write_string(string.get_value());
896        if result.starts_with('[') {
897            self.push_str_and_break_if(&result, utils::break_long_string);
898        } else {
899            self.push_str(&result);
900        }
901    }
902
903    fn write_interpolated_string(
904        &mut self,
905        interpolated_string: &nodes::InterpolatedStringExpression,
906    ) {
907        self.push_char('`');
908
909        for segment in interpolated_string.iter_segments() {
910            match segment {
911                nodes::InterpolationSegment::String(string_segment) => {
912                    self.raw_push_str(&utils::write_interpolated_string_segment(string_segment));
913                }
914                nodes::InterpolationSegment::Value(value) => {
915                    self.raw_push_char('{');
916                    // add space when value segment is a table
917                    let expression = value.get_expression();
918                    if utils::starts_with_table(expression).is_some() {
919                        self.raw_push_char(' ');
920                    }
921                    self.write_expression(expression);
922                    self.push_char('}');
923                }
924            }
925        }
926
927        self.raw_push_char('`');
928    }
929
930    fn write_identifier(&mut self, identifier: &nodes::Identifier) {
931        self.push_str(identifier.get_name());
932    }
933
934    fn write_parenthese(&mut self, parenthese: &nodes::ParentheseExpression) {
935        self.write_expression_in_parentheses(parenthese.inner_expression());
936    }
937
938    fn write_type_cast(&mut self, type_cast: &nodes::TypeCastExpression) {
939        let inner_expression = type_cast.get_expression();
940
941        if nodes::TypeCastExpression::needs_parentheses(inner_expression) {
942            self.write_expression_in_parentheses(inner_expression);
943        } else {
944            self.write_expression(inner_expression);
945        }
946
947        self.push_str("::");
948        self.write_type(type_cast.get_type());
949    }
950
951    fn write_type_name(&mut self, type_name: &nodes::TypeName) {
952        self.write_identifier(type_name.get_type_name());
953        if let Some(parameters) = type_name.get_type_parameters() {
954            self.push_char('<');
955            let last_index = parameters.len().saturating_sub(1);
956            for (index, parameter) in parameters.iter().enumerate() {
957                self.write_type_parameter(parameter);
958                if index != last_index {
959                    self.push_char(',');
960                }
961            }
962
963            self.push_char('>');
964        }
965    }
966
967    fn write_type_field(&mut self, type_field: &nodes::TypeField) {
968        self.write_identifier(type_field.get_namespace());
969        self.push_new_line_if_needed(1);
970        self.raw_push_char('.');
971        self.write_type_name(type_field.get_type_name());
972    }
973
974    fn write_true_type(&mut self, _: &Option<nodes::Token>) {
975        self.push_str("true");
976    }
977
978    fn write_false_type(&mut self, _: &Option<nodes::Token>) {
979        self.push_str("false");
980    }
981
982    fn write_nil_type(&mut self, _: &Option<nodes::Token>) {
983        self.push_str("nil");
984    }
985
986    fn write_string_type(&mut self, string_type: &nodes::StringType) {
987        let result = utils::write_string(string_type.get_value());
988        if result.starts_with('[') {
989            self.push_str_and_break_if(&result, utils::break_long_string);
990        } else {
991            self.push_str(&result);
992        }
993    }
994
995    fn write_array_type(&mut self, array: &nodes::ArrayType) {
996        self.push_char('{');
997        self.write_type(array.get_element_type());
998        self.push_char('}');
999    }
1000
1001    fn write_table_type(&mut self, table_type: &nodes::TableType) {
1002        self.push_char('{');
1003
1004        let last_index = table_type.len().saturating_sub(1);
1005        for (index, property) in table_type.iter_entries().enumerate() {
1006            match property {
1007                nodes::TableEntryType::Property(property) => {
1008                    self.write_identifier(property.get_identifier());
1009                    self.push_char(':');
1010                    self.write_type(property.get_type());
1011                }
1012                nodes::TableEntryType::Literal(property) => {
1013                    self.push_char('[');
1014                    self.write_string_type(property.get_string());
1015                    self.push_char(']');
1016                    self.push_char(':');
1017                    self.write_type(property.get_type());
1018                }
1019                nodes::TableEntryType::Indexer(indexer) => {
1020                    self.push_char('[');
1021
1022                    let key_type = indexer.get_key_type();
1023
1024                    let need_parentheses = matches!(
1025                        key_type,
1026                        nodes::Type::Optional(_)
1027                            | nodes::Type::Intersection(_)
1028                            | nodes::Type::Union(_)
1029                    );
1030
1031                    if need_parentheses {
1032                        self.push_char('(');
1033                        self.write_type(key_type);
1034                        self.push_char(')');
1035                    } else {
1036                        self.write_type(key_type);
1037                    }
1038
1039                    self.push_char(']');
1040                    self.push_char(':');
1041                    self.write_type(indexer.get_value_type());
1042                }
1043            }
1044            if index != last_index {
1045                self.push_char(',');
1046            }
1047        }
1048
1049        self.push_char('}');
1050    }
1051
1052    fn write_expression_type(&mut self, expression_type: &nodes::ExpressionType) {
1053        self.push_str("typeof(");
1054        self.write_expression(expression_type.get_expression());
1055        self.push_char(')');
1056    }
1057
1058    fn write_parenthese_type(&mut self, parenthese_type: &nodes::ParentheseType) {
1059        self.write_type_in_parentheses(parenthese_type.get_inner_type());
1060    }
1061
1062    fn write_function_type(&mut self, function_type: &nodes::FunctionType) {
1063        if let Some(generics) = function_type.get_generic_parameters() {
1064            self.write_function_generics(generics);
1065        }
1066
1067        self.push_char('(');
1068
1069        let last_index = function_type.argument_len().saturating_sub(1);
1070
1071        for (index, argument) in function_type.iter_arguments().enumerate() {
1072            if let Some(name) = argument.get_name() {
1073                self.write_identifier(name);
1074                self.push_char(':');
1075            }
1076            self.write_type(argument.get_type());
1077
1078            if index != last_index {
1079                self.push_char(',');
1080            }
1081        }
1082
1083        if let Some(variadic_argument_type) = function_type.get_variadic_argument_type() {
1084            if function_type.argument_len() > 0 {
1085                self.push_char(',');
1086            }
1087            self.write_variadic_argument_type(variadic_argument_type);
1088        }
1089
1090        self.push_str(")->");
1091        self.write_function_return_type(function_type.get_return_type());
1092    }
1093
1094    fn write_optional_type(&mut self, optional: &nodes::OptionalType) {
1095        let inner_type = optional.get_inner_type();
1096        if nodes::OptionalType::needs_parentheses(inner_type) {
1097            self.write_type_in_parentheses(inner_type);
1098        } else {
1099            self.write_type(inner_type);
1100        }
1101        self.push_char('?');
1102    }
1103
1104    fn write_intersection_type(&mut self, intersection: &nodes::IntersectionType) {
1105        let length = intersection.len();
1106        let last_index = length.saturating_sub(1);
1107        for (i, r#type) in intersection.iter_types().enumerate() {
1108            if i != 0 || intersection.has_leading_token() {
1109                self.push_char('&');
1110            }
1111
1112            let need_parentheses = if i == last_index {
1113                nodes::IntersectionType::last_needs_parentheses(r#type)
1114            } else {
1115                nodes::IntersectionType::intermediate_needs_parentheses(r#type)
1116            };
1117
1118            if need_parentheses {
1119                self.write_type_in_parentheses(r#type);
1120            } else {
1121                self.write_type(r#type);
1122            }
1123        }
1124    }
1125
1126    fn write_union_type(&mut self, union: &nodes::UnionType) {
1127        let length = union.len();
1128        let last_index = length.saturating_sub(1);
1129        for (i, r#type) in union.iter_types().enumerate() {
1130            if i != 0 || union.has_leading_token() {
1131                self.push_char('|');
1132            }
1133
1134            let need_parentheses = if i == last_index {
1135                nodes::UnionType::last_needs_parentheses(r#type)
1136            } else {
1137                nodes::UnionType::intermediate_needs_parentheses(r#type)
1138            };
1139
1140            if need_parentheses {
1141                self.write_type_in_parentheses(r#type);
1142            } else {
1143                self.write_type(r#type);
1144            }
1145        }
1146    }
1147
1148    fn write_type_pack(&mut self, type_pack: &nodes::TypePack) {
1149        self.push_char('(');
1150
1151        let last_index = type_pack.len().saturating_sub(1);
1152
1153        for (index, r#type) in type_pack.into_iter().enumerate() {
1154            self.write_type(r#type);
1155            if index != last_index {
1156                self.push_char(',');
1157            }
1158        }
1159
1160        if let Some(variadic_argument_type) = type_pack.get_variadic_type() {
1161            if !type_pack.is_empty() {
1162                self.push_char(',');
1163            }
1164            self.write_variadic_argument_type(variadic_argument_type);
1165        }
1166
1167        self.push_char(')');
1168    }
1169
1170    fn write_variadic_type_pack(&mut self, variadic_type_pack: &nodes::VariadicTypePack) {
1171        self.push_str("...");
1172        self.write_type(variadic_type_pack.get_type());
1173    }
1174
1175    fn write_generic_type_pack(&mut self, generic_type_pack: &nodes::GenericTypePack) {
1176        self.write_identifier(generic_type_pack.get_name());
1177        self.push_str("...");
1178    }
1179}