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