Skip to main content

darklua_core/generator/
readable.rs

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