Skip to main content

lisette_format/
formatter.rs

1use crate::INDENT_WIDTH;
2use crate::comments::{Comments, prepend_comments};
3use crate::lindig::{Document, concat, flex_break, join, strict_break};
4use syntax::ast::{
5    Annotation, Attribute, AttributeArg, BinaryOperator, Binding, EnumVariant, Expression,
6    FormatStringPart, Generic, ImportAlias, Literal, MatchArm, ParentInterface, Pattern,
7    RestPattern, SelectArm, SelectArmPattern, Span, StructFieldAssignment, StructFieldDefinition,
8    StructFieldPattern, StructKind, UnaryOperator, VariantFields, Visibility,
9};
10
11pub struct Formatter<'a> {
12    comments: Comments<'a>,
13}
14
15impl<'a> Formatter<'a> {
16    pub fn new(comments: Comments<'a>) -> Self {
17        Self { comments }
18    }
19
20    pub fn module(&mut self, top_level_items: &'a [Expression]) -> Document<'a> {
21        let (imports, rest): (Vec<_>, Vec<_>) = top_level_items
22            .iter()
23            .partition(|e| matches!(e, Expression::ModuleImport { .. }));
24
25        let mut docs = Vec::new();
26
27        if !imports.is_empty() {
28            docs.push(self.sort_imports(&imports));
29        }
30
31        for (i, item) in rest.iter().enumerate() {
32            let start = item.get_span().byte_offset;
33
34            if let Some(comment_doc) = self.comments.take_comments_before(start) {
35                if !docs.is_empty() {
36                    docs.push(Document::Newline);
37                    docs.push(Document::Newline);
38                }
39                docs.push(comment_doc.force_break());
40                docs.push(Document::Newline);
41            } else if !docs.is_empty() || i > 0 {
42                docs.push(Document::Newline);
43                docs.push(Document::Newline);
44            }
45
46            docs.push(self.definition(item));
47        }
48
49        if let Some(comment_doc) = self.comments.take_trailing_comments() {
50            if !docs.is_empty() {
51                docs.push(Document::Newline);
52                docs.push(Document::Newline);
53            }
54            docs.push(comment_doc);
55        }
56
57        if !docs.is_empty() {
58            docs.push(Document::Newline);
59        }
60
61        concat(docs)
62    }
63
64    fn sort_imports(&mut self, imports: &[&'a Expression]) -> Document<'a> {
65        if imports.is_empty() {
66            return Document::Sequence(vec![]);
67        }
68
69        let mut leading_comments: Option<Document<'a>> = None;
70        let mut leading_has_blank_line = false;
71        let mut go_imports: Vec<&'a Expression> = Vec::new();
72        let mut local_imports: Vec<&'a Expression> = Vec::new();
73
74        for (i, import) in imports.iter().enumerate() {
75            let start = import.get_span().byte_offset;
76            let has_blank_line = self.comments.take_empty_lines_before(start);
77
78            let comments = self.comments.take_comments_before(start);
79            if i == 0 && comments.is_some() {
80                leading_comments = comments;
81                leading_has_blank_line = has_blank_line;
82            }
83
84            if let Expression::ModuleImport { name, .. } = import {
85                if name.starts_with("go:") {
86                    go_imports.push(import);
87                } else {
88                    local_imports.push(import);
89                }
90            }
91        }
92
93        fn import_sort_key(imp: &&Expression) -> (String, String) {
94            if let Expression::ModuleImport { name, alias, .. } = imp {
95                let sort_path = match alias {
96                    Some(ImportAlias::Named(a, _)) => a.to_string(),
97                    Some(ImportAlias::Blank(_)) => "_".to_string(),
98                    None => {
99                        let path = name.split_once(':').map(|(_, p)| p).unwrap_or(name);
100                        path.to_string()
101                    }
102                };
103                (sort_path, name.to_string())
104            } else {
105                (String::new(), String::new())
106            }
107        }
108
109        go_imports.sort_by_key(import_sort_key);
110        local_imports.sort_by_key(import_sort_key);
111
112        let mut group_docs: Vec<Document<'a>> = Vec::new();
113
114        if !go_imports.is_empty() {
115            let docs: Vec<_> = go_imports.iter().map(|imp| self.definition(imp)).collect();
116            group_docs.push(join(docs, Document::Newline));
117        }
118
119        if !local_imports.is_empty() {
120            let docs: Vec<_> = local_imports
121                .iter()
122                .map(|imp| self.definition(imp))
123                .collect();
124            group_docs.push(join(docs, Document::Newline));
125        }
126
127        let imports_doc = join(group_docs, concat([Document::Newline, Document::Newline]));
128
129        match leading_comments {
130            Some(c) => {
131                let separator = if leading_has_blank_line {
132                    concat([Document::Newline, Document::Newline])
133                } else {
134                    Document::Newline
135                };
136                c.force_break().append(separator).append(imports_doc)
137            }
138            None => imports_doc,
139        }
140    }
141
142    fn definition(&mut self, expression: &'a Expression) -> Document<'a> {
143        let start = expression.get_span().byte_offset;
144        let doc_comments_doc = self.comments.take_doc_comments_before(start);
145
146        let (attrs, vis, inner) = match expression {
147            Expression::Function {
148                name,
149                generics,
150                params,
151                return_annotation,
152                body,
153                visibility,
154                attributes,
155                ..
156            } => (
157                Self::attributes(attributes),
158                *visibility,
159                self.function(name, generics, params, return_annotation, body),
160            ),
161
162            Expression::Struct {
163                name,
164                generics,
165                fields,
166                kind,
167                visibility,
168                attributes,
169                span,
170                ..
171            } => (
172                Self::attributes(attributes),
173                *visibility,
174                self.struct_definition(name, generics, fields, span, *kind),
175            ),
176
177            Expression::Enum {
178                name,
179                generics,
180                variants,
181                visibility,
182                ..
183            } => (
184                Document::Sequence(vec![]),
185                *visibility,
186                self.enum_definition(name, generics, variants),
187            ),
188
189            Expression::ValueEnum {
190                name,
191                underlying_ty,
192                variants,
193                visibility,
194                ..
195            } => (
196                Document::Sequence(vec![]),
197                *visibility,
198                self.value_enum_definition(name, underlying_ty.as_ref(), variants),
199            ),
200
201            Expression::TypeAlias {
202                name,
203                generics,
204                annotation,
205                visibility,
206                ..
207            } => (
208                Document::Sequence(vec![]),
209                *visibility,
210                Self::type_alias(name, generics, annotation),
211            ),
212
213            Expression::Interface {
214                name,
215                generics,
216                parents,
217                method_signatures,
218                visibility,
219                ..
220            } => (
221                Document::Sequence(vec![]),
222                *visibility,
223                self.interface(name, generics, parents, method_signatures),
224            ),
225
226            Expression::ImplBlock {
227                annotation,
228                generics,
229                methods,
230                span,
231                ..
232            } => (
233                Document::Sequence(vec![]),
234                Visibility::Private,
235                self.impl_block(annotation, generics, methods, span.end()),
236            ),
237
238            Expression::Const {
239                identifier,
240                annotation,
241                expression,
242                visibility,
243                ..
244            } => (
245                Document::Sequence(vec![]),
246                *visibility,
247                self.const_definition(identifier, annotation.as_ref(), expression),
248            ),
249
250            Expression::VariableDeclaration {
251                name,
252                annotation,
253                visibility,
254                ..
255            } => (
256                Document::Sequence(vec![]),
257                *visibility,
258                Document::str("var ")
259                    .append(Document::string(name.to_string()))
260                    .append(": ")
261                    .append(Self::annotation(annotation)),
262            ),
263
264            Expression::ModuleImport { name, alias, .. } => {
265                let alias_doc = match alias {
266                    Some(ImportAlias::Named(a, _)) => Document::string(a.to_string()).append(" "),
267                    Some(ImportAlias::Blank(_)) => Document::str("_ "),
268                    None => Document::str(""),
269                };
270
271                (
272                    Document::Sequence(vec![]),
273                    Visibility::Private,
274                    Document::str("import ")
275                        .append(alias_doc)
276                        .append("\"")
277                        .append(Document::string(name.to_string()))
278                        .append("\""),
279                )
280            }
281
282            _ => (
283                Document::Sequence(vec![]),
284                Visibility::Private,
285                self.expression(expression),
286            ),
287        };
288
289        let vis_inner = match Self::visibility(vis) {
290            Some(pub_doc) => pub_doc.append(inner),
291            None => inner,
292        };
293        let definition_doc = attrs.append(vis_inner);
294
295        match doc_comments_doc {
296            Some(doc) => doc.append(Document::Newline).append(definition_doc),
297            None => definition_doc,
298        }
299    }
300
301    fn visibility(vis: Visibility) -> Option<Document<'a>> {
302        match vis {
303            Visibility::Public => Some(Document::str("pub ")),
304            Visibility::Private => None,
305        }
306    }
307
308    fn function(
309        &mut self,
310        name: &'a str,
311        generics: &'a [Generic],
312        params: &'a [Binding],
313        return_annotation: &'a Annotation,
314        body: &'a Expression,
315    ) -> Document<'a> {
316        let generics_doc = Self::generics(generics);
317
318        let params_docs: Vec<_> = params.iter().map(|p| self.binding(p)).collect();
319
320        let params_doc = Self::wrap_params(params_docs);
321
322        let return_doc = if return_annotation.is_unknown() {
323            Document::Sequence(vec![])
324        } else {
325            Document::str(" -> ").append(Self::annotation(return_annotation))
326        };
327
328        let signature = Document::str("fn ")
329            .append(Document::string(name.to_string()))
330            .append(generics_doc)
331            .append(params_doc)
332            .append(return_doc)
333            .group();
334
335        if matches!(body, Expression::NoOp) {
336            signature
337        } else {
338            signature.append(" ").append(self.as_block(body))
339        }
340    }
341
342    fn wrap_params(params_docs: Vec<Document<'a>>) -> Document<'a> {
343        if params_docs.is_empty() {
344            return Document::str("()");
345        }
346
347        let params_doc = join(params_docs, strict_break(",", ", "));
348
349        Document::str("(")
350            .append(strict_break("", ""))
351            .append(params_doc)
352            .nest(INDENT_WIDTH)
353            .append(strict_break(",", ""))
354            .append(")")
355            .group()
356    }
357
358    pub fn expression(&mut self, expression: &'a Expression) -> Document<'a> {
359        let start = expression.get_span().byte_offset;
360        let comments = self.comments.take_comments_before(start);
361
362        let doc = match expression {
363            Expression::Literal { literal, .. } => self.literal(literal),
364            Expression::Identifier { value, .. } => Document::string(value.to_string()),
365            Expression::Unit { .. } => Document::str("()"),
366            Expression::Break { value, .. } => {
367                if let Some(val) = value {
368                    Document::str("break ").append(self.expression(val))
369                } else {
370                    Document::str("break")
371                }
372            }
373            Expression::Continue { .. } => Document::str("continue"),
374            Expression::NoOp => Document::Sequence(vec![]),
375
376            Expression::Paren { expression, .. } => Document::str("(")
377                .append(self.expression(expression))
378                .append(")"),
379
380            Expression::Block { items, span, .. } => self.block(items, span),
381
382            Expression::Let {
383                binding,
384                value,
385                mutable,
386                else_block,
387                ..
388            } => self.let_(binding, value, *mutable, else_block.as_deref()),
389
390            Expression::Return { expression, .. } => self.return_(expression),
391
392            Expression::If {
393                condition,
394                consequence,
395                alternative,
396                ..
397            } => self.if_(condition, consequence, alternative),
398
399            Expression::IfLet {
400                pattern,
401                scrutinee,
402                consequence,
403                alternative,
404                ..
405            } => self.if_let(pattern, scrutinee, consequence, alternative),
406
407            Expression::Match { subject, arms, .. } => self.match_(subject, arms),
408
409            Expression::Binary {
410                operator,
411                left,
412                right,
413                ..
414            } => self.binary_operator(operator, left, right),
415
416            Expression::Unary {
417                operator,
418                expression,
419                ..
420            } => self.unary_operator(operator, expression),
421
422            Expression::Call {
423                expression,
424                args,
425                spread,
426                type_args,
427                ..
428            } => self.call(expression, args, spread, type_args),
429
430            Expression::DotAccess {
431                expression, member, ..
432            } => self.dot_access(expression, member),
433
434            Expression::IndexedAccess {
435                expression, index, ..
436            } => self.indexed_access(expression, index),
437
438            Expression::Tuple { elements, .. } => self.tuple(elements),
439
440            Expression::StructCall {
441                name,
442                field_assignments,
443                spread,
444                ..
445            } => self.struct_call(name, field_assignments, spread),
446
447            Expression::Assignment {
448                target,
449                value,
450                compound_operator,
451                ..
452            } => self.assignment(target, value, *compound_operator),
453
454            Expression::Loop { body, .. } => self.loop_(body),
455
456            Expression::While {
457                condition, body, ..
458            } => self.while_(condition, body),
459
460            Expression::WhileLet {
461                pattern,
462                scrutinee,
463                body,
464                ..
465            } => self.while_let(pattern, scrutinee, body),
466
467            Expression::For {
468                binding,
469                iterable,
470                body,
471                ..
472            } => self.for_(binding, iterable, body),
473
474            Expression::Task { expression, .. } => self.task(expression),
475            Expression::Defer { expression, .. } => self.defer_(expression),
476            Expression::Select { arms, .. } => self.select(arms),
477            Expression::Propagate { expression, .. } => self.propagate_(expression),
478            Expression::Reference { expression, .. } => self.ref_(expression),
479            Expression::RawGo { text } => Self::raw_go(text),
480
481            Expression::TryBlock { items, span, .. } => self.try_block(items, span),
482            Expression::RecoverBlock { items, span, .. } => self.recover_block(items, span),
483            Expression::Range {
484                start,
485                end,
486                inclusive,
487                ..
488            } => self.range(start, end, *inclusive),
489            Expression::Cast {
490                expression,
491                target_type,
492                ..
493            } => self.cast(expression, target_type),
494
495            Expression::Lambda {
496                params,
497                return_annotation,
498                body,
499                span,
500                ..
501            } => self.lambda(params, return_annotation, body, span),
502
503            _ => self.definition(expression),
504        };
505
506        prepend_comments(doc, comments)
507    }
508
509    fn literal(&mut self, literal: &'a Literal) -> Document<'a> {
510        match literal {
511            Literal::Integer { value, text } => {
512                if let Some(original) = text {
513                    Document::string(original.clone())
514                } else {
515                    Document::string(value.to_string())
516                }
517            }
518            Literal::Float { value, text } => match text {
519                Some(t) => Document::string(t.clone()),
520                None => {
521                    let s = value.to_string();
522                    if s.contains('.') || s.contains('e') || s.contains('E') {
523                        Document::string(s)
524                    } else {
525                        Document::string(format!("{}.0", s))
526                    }
527                }
528            },
529            Literal::Imaginary(coef) => {
530                if *coef == coef.trunc() && coef.abs() < 1e15 {
531                    Document::string(format!("{}i", *coef as i64))
532                } else {
533                    Document::string(format!("{}i", coef))
534                }
535            }
536            Literal::Boolean(b) => Document::str(if *b { "true" } else { "false" }),
537            Literal::String(s) => Document::string(format!("\"{s}\"")),
538            Literal::Char(c) => Document::string(format!("'{c}'")),
539            Literal::Slice(elements) => self.slice(elements),
540            Literal::FormatString(parts) => self.format_string(parts),
541        }
542    }
543
544    fn slice(&mut self, elements: &'a [Expression]) -> Document<'a> {
545        if elements.is_empty() {
546            return Document::str("[]");
547        }
548
549        let elements_docs: Vec<_> = elements.iter().map(|e| self.expression(e)).collect();
550        let elements_doc = join(elements_docs, strict_break(",", ", "));
551
552        Document::str("[")
553            .append(strict_break("", ""))
554            .append(elements_doc)
555            .nest(INDENT_WIDTH)
556            .append(strict_break(",", ""))
557            .append("]")
558            .group()
559    }
560
561    fn format_string(&mut self, parts: &'a [FormatStringPart]) -> Document<'a> {
562        let mut docs = vec![Document::str("f\"")];
563
564        for part in parts {
565            match part {
566                FormatStringPart::Text(s) => docs.push(Document::string(s.clone())),
567                FormatStringPart::Expression(e) => {
568                    docs.push(Document::str("{"));
569                    docs.push(self.expression(e));
570                    docs.push(Document::str("}"));
571                }
572            }
573        }
574
575        docs.push(Document::str("\""));
576        concat(docs)
577    }
578
579    fn block(&mut self, items: &'a [Expression], span: &Span) -> Document<'a> {
580        let block_end = span.byte_offset + span.byte_length;
581
582        if items.is_empty() {
583            return match self.comments.take_comments_before(block_end) {
584                Some(c) => Document::str("{")
585                    .append(Document::Newline.append(c).nest(INDENT_WIDTH))
586                    .append(Document::Newline)
587                    .append("}")
588                    .force_break(),
589                None => Document::str("{}"),
590            };
591        }
592
593        let mut docs = Vec::new();
594        let mut previous_end: Option<u32> = None;
595
596        for item in items.iter() {
597            let start = item.get_span().byte_offset;
598
599            if previous_end.is_some() {
600                if self.comments.take_empty_lines_before(start) {
601                    docs.push(Document::Newline);
602                    docs.push(Document::Newline);
603                } else {
604                    docs.push(Document::Newline);
605                }
606            }
607
608            let item_doc = self.expression(item);
609            docs.push(item_doc);
610            previous_end = Some(item.get_span().byte_offset + item.get_span().byte_length);
611        }
612
613        if let Some(trailing_comments_doc) = self.comments.take_comments_before(block_end) {
614            docs.push(Document::str(" "));
615            docs.push(trailing_comments_doc);
616        }
617
618        let body = concat(docs);
619
620        Document::str("{")
621            .append(Document::Newline.append(body).nest(INDENT_WIDTH))
622            .append(Document::Newline)
623            .append("}")
624            .force_break()
625    }
626
627    fn let_(
628        &mut self,
629        binding: &'a Binding,
630        value: &'a Expression,
631        mutable: bool,
632        else_block: Option<&'a Expression>,
633    ) -> Document<'a> {
634        let keyword = if mutable { "let mut " } else { "let " };
635
636        let base = Document::str(keyword)
637            .append(self.binding(binding))
638            .append(" = ")
639            .append(self.expression(value));
640
641        if let Some(else_expression) = else_block {
642            base.append(" else ").append(self.as_block(else_expression))
643        } else {
644            base
645        }
646    }
647
648    fn return_(&mut self, expression: &'a Expression) -> Document<'a> {
649        if matches!(expression, Expression::Unit { .. }) {
650            Document::str("return")
651        } else {
652            Document::str("return ").append(self.expression(expression))
653        }
654    }
655
656    fn if_(
657        &mut self,
658        condition: &'a Expression,
659        consequence: &'a Expression,
660        alternative: &'a Expression,
661    ) -> Document<'a> {
662        let if_doc = Document::str("if ")
663            .append(self.expression(condition))
664            .append(" ")
665            .append(self.as_inline_block(consequence));
666
667        match alternative {
668            Expression::Unit { .. } => if_doc,
669            Expression::If { .. } | Expression::IfLet { .. } => {
670                if_doc.append(" else ").append(self.expression(alternative))
671            }
672            _ => if_doc
673                .append(" else ")
674                .append(self.as_inline_block(alternative)),
675        }
676        .group()
677    }
678
679    fn if_let(
680        &mut self,
681        pattern: &'a Pattern,
682        scrutinee: &'a Expression,
683        consequence: &'a Expression,
684        alternative: &'a Expression,
685    ) -> Document<'a> {
686        let if_let_doc = Document::str("if let ")
687            .append(self.pattern(pattern))
688            .append(" = ")
689            .append(self.expression(scrutinee))
690            .append(" ")
691            .append(self.as_inline_block(consequence));
692
693        match alternative {
694            Expression::Unit { .. } => if_let_doc,
695            Expression::If { .. } | Expression::IfLet { .. } => if_let_doc
696                .append(" else ")
697                .append(self.expression(alternative)),
698            _ => if_let_doc
699                .append(" else ")
700                .append(self.as_inline_block(alternative)),
701        }
702        .group()
703    }
704
705    fn as_block(&mut self, expression: &'a Expression) -> Document<'a> {
706        match expression {
707            Expression::Block { items, span, .. } => self.block(items, span),
708            Expression::NoOp => Document::Sequence(vec![]),
709            _ => Document::str("{ ")
710                .append(self.expression(expression))
711                .append(" }"),
712        }
713    }
714
715    /// Like as_block, but allows single-expression blocks to stay inline.
716    /// Used for if/else branches where `{ expression }` should stay on one line
717    /// when the containing group fits, and expand to multi-line when it doesn't.
718    fn as_inline_block(&mut self, expression: &'a Expression) -> Document<'a> {
719        match expression {
720            Expression::Block { items, span, .. } => {
721                if items.len() == 1 && !self.comments.has_comments_in_range(*span) {
722                    let expression = self.expression(&items[0]);
723                    return Document::str("{")
724                        .append(strict_break("", " ").append(expression).nest(INDENT_WIDTH))
725                        .append(strict_break("", " "))
726                        .append("}");
727                }
728                self.block(items, span)
729            }
730            Expression::NoOp => Document::Sequence(vec![]),
731            _ => {
732                let expression = self.expression(expression);
733                Document::str("{")
734                    .append(strict_break("", " ").append(expression).nest(INDENT_WIDTH))
735                    .append(strict_break("", " "))
736                    .append("}")
737            }
738        }
739    }
740
741    fn match_(&mut self, subject: &'a Expression, arms: &'a [MatchArm]) -> Document<'a> {
742        let arms_docs: Vec<_> = arms
743            .iter()
744            .map(|arm| {
745                let start = arm.pattern.get_span().byte_offset;
746                let comments = self.comments.take_comments_before(start);
747                let pattern = self.pattern(&arm.pattern);
748                let expression = self.expression(&arm.expression);
749
750                let pattern_with_guard = if let Some(guard) = &arm.guard {
751                    pattern.append(" if ").append(self.expression(guard))
752                } else {
753                    pattern
754                };
755
756                let arm_doc = pattern_with_guard
757                    .append(" => ")
758                    .append(expression)
759                    .append(",");
760                prepend_comments(arm_doc, comments)
761            })
762            .collect();
763
764        let header = Document::str("match ").append(self.expression(subject));
765        Self::braced_body(header, join(arms_docs, Document::Newline))
766    }
767
768    fn loop_(&mut self, body: &'a Expression) -> Document<'a> {
769        Document::str("loop ").append(self.as_block(body))
770    }
771
772    fn while_(&mut self, condition: &'a Expression, body: &'a Expression) -> Document<'a> {
773        Document::str("while ")
774            .append(self.expression(condition))
775            .append(" ")
776            .append(self.as_block(body))
777    }
778
779    fn while_let(
780        &mut self,
781        pattern: &'a Pattern,
782        scrutinee: &'a Expression,
783        body: &'a Expression,
784    ) -> Document<'a> {
785        Document::str("while let ")
786            .append(self.pattern(pattern))
787            .append(" = ")
788            .append(self.expression(scrutinee))
789            .append(" ")
790            .append(self.as_block(body))
791    }
792
793    fn for_(
794        &mut self,
795        binding: &'a Binding,
796        iterable: &'a Expression,
797        body: &'a Expression,
798    ) -> Document<'a> {
799        Document::str("for ")
800            .append(self.binding(binding))
801            .append(" in ")
802            .append(self.expression(iterable))
803            .append(" ")
804            .append(self.as_block(body))
805    }
806
807    fn binary_operator(
808        &mut self,
809        operator: &BinaryOperator,
810        left_operand: &'a Expression,
811        right_operand: &'a Expression,
812    ) -> Document<'a> {
813        use BinaryOperator::*;
814
815        if matches!(operator, Pipeline) {
816            return self.pipeline(left_operand, right_operand);
817        }
818
819        let operator_string = match operator {
820            Addition => "+",
821            Subtraction => "-",
822            Multiplication => "*",
823            Division => "/",
824            Remainder => "%",
825            LessThan => "<",
826            LessThanOrEqual => "<=",
827            GreaterThan => ">",
828            GreaterThanOrEqual => ">=",
829            Equal => "==",
830            NotEqual => "!=",
831            And => "&&",
832            Or => "||",
833            Pipeline => unreachable!(),
834        };
835
836        self.expression(left_operand)
837            .append(" ")
838            .append(operator_string)
839            .append(strict_break("", " "))
840            .append(self.expression(right_operand))
841            .group()
842    }
843
844    fn pipeline(&mut self, left: &'a Expression, right: &'a Expression) -> Document<'a> {
845        let mut segments = vec![right];
846        let mut current = left;
847
848        while let Expression::Binary {
849            operator: BinaryOperator::Pipeline,
850            left: l,
851            right: r,
852            ..
853        } = current
854        {
855            segments.push(r);
856            current = l;
857        }
858        segments.push(current);
859        segments.reverse();
860
861        if segments.len() == 2 {
862            return self
863                .expression(segments[0])
864                .append(flex_break("", " "))
865                .append("|> ")
866                .append(self.expression(segments[1]))
867                .nest_if_broken(INDENT_WIDTH)
868                .group();
869        }
870
871        let docs: Vec<_> = segments
872            .iter()
873            .enumerate()
874            .map(|(i, seg)| {
875                if i == 0 {
876                    self.expression(seg)
877                } else {
878                    Document::Newline.append("|> ").append(self.expression(seg))
879                }
880            })
881            .collect();
882
883        concat(docs).nest(INDENT_WIDTH)
884    }
885
886    fn unary_operator(
887        &mut self,
888        operator: &UnaryOperator,
889        expression: &'a Expression,
890    ) -> Document<'a> {
891        match operator {
892            UnaryOperator::Negative => Document::str("-").append(self.expression(expression)),
893            UnaryOperator::Not => Document::str("!").append(self.expression(expression)),
894            UnaryOperator::Deref => self.expression(expression).append(".*"),
895        }
896    }
897
898    fn call(
899        &mut self,
900        callee: &'a Expression,
901        args: &'a [Expression],
902        spread: &'a Option<Expression>,
903        type_args: &'a [Annotation],
904    ) -> Document<'a> {
905        if let Expression::DotAccess {
906            expression: inner,
907            member,
908            ..
909        } = callee
910        {
911            let (root, mut chain_segments) = collect_method_chain(inner);
912            chain_segments.push(MethodChainSegment {
913                member,
914                args,
915                spread,
916                type_args,
917            });
918            if chain_segments.len() >= 2 {
919                return self.format_method_chain(root, &chain_segments);
920            }
921        }
922
923        let head = self
924            .expression(callee)
925            .append(Self::format_type_args(type_args));
926        self.format_call_with_head(head, args, spread)
927    }
928
929    fn format_type_args(type_args: &'a [Annotation]) -> Document<'a> {
930        if type_args.is_empty() {
931            Document::Sequence(vec![])
932        } else {
933            let types: Vec<_> = type_args.iter().map(Self::annotation).collect();
934            Document::str("<")
935                .append(join(types, Document::str(", ")))
936                .append(">")
937        }
938    }
939
940    fn format_call_with_head(
941        &mut self,
942        head: Document<'a>,
943        args: &'a [Expression],
944        spread: &'a Option<Expression>,
945    ) -> Document<'a> {
946        if args.is_empty() && spread.is_none() {
947            return head.append("()");
948        }
949
950        if let Some(spread_expr) = spread {
951            let spread_doc = Document::str("..").append(self.expression(spread_expr));
952            if args.is_empty() {
953                return head
954                    .append("(")
955                    .append(spread_doc.group().next_break_fits(true))
956                    .append(")")
957                    .next_break_fits(false)
958                    .group();
959            }
960            let init_docs: Vec<_> = args.iter().map(|a| self.expression(a)).collect();
961            let init_doc = join(init_docs, strict_break(",", ", "));
962            return head
963                .append("(")
964                .append(strict_break("", ""))
965                .append(init_doc)
966                .append(strict_break(",", ", "))
967                .append(spread_doc.group().next_break_fits(true))
968                .nest(INDENT_WIDTH)
969                .append(strict_break(",", ""))
970                .append(")")
971                .next_break_fits(false)
972                .group();
973        }
974
975        let Some((last, init)) = args
976            .split_last()
977            .filter(|(last, _)| is_inlinable_arg(last, args.len()))
978        else {
979            let arg_docs: Vec<_> = args.iter().map(|a| self.expression(a)).collect();
980            let args_doc = join(arg_docs, strict_break(",", ", "));
981
982            return head
983                .append("(")
984                .append(strict_break("", ""))
985                .append(args_doc)
986                .nest(INDENT_WIDTH)
987                .append(strict_break(",", ""))
988                .append(")")
989                .group();
990        };
991
992        let last_doc = self.expression(last).group().next_break_fits(true);
993
994        if init.is_empty() {
995            head.append("(")
996                .append(last_doc)
997                .append(")")
998                .next_break_fits(false)
999                .group()
1000        } else {
1001            let init_docs: Vec<_> = init.iter().map(|a| self.expression(a)).collect();
1002            let init_doc = join(init_docs, strict_break(",", ", "));
1003
1004            head.append("(")
1005                .append(strict_break("", ""))
1006                .append(init_doc)
1007                .append(strict_break(",", ", "))
1008                .append(last_doc)
1009                .nest(INDENT_WIDTH)
1010                .append(strict_break(",", ""))
1011                .append(")")
1012                .next_break_fits(false)
1013                .group()
1014        }
1015    }
1016
1017    fn format_method_chain(
1018        &mut self,
1019        root: &'a Expression,
1020        segments: &[MethodChainSegment<'a>],
1021    ) -> Document<'a> {
1022        let root_doc = self.expression(root);
1023
1024        let segment_docs: Vec<Document<'a>> = segments
1025            .iter()
1026            .map(|seg| {
1027                let head = Document::str(".")
1028                    .append(seg.member)
1029                    .append(Self::format_type_args(seg.type_args));
1030                strict_break("", "").append(self.format_call_with_head(head, seg.args, seg.spread))
1031            })
1032            .collect();
1033
1034        root_doc
1035            .append(concat(segment_docs).nest_if_broken(INDENT_WIDTH))
1036            .group()
1037    }
1038
1039    fn dot_access(&mut self, expression: &'a Expression, member: &'a str) -> Document<'a> {
1040        self.expression(expression).append(".").append(member)
1041    }
1042
1043    fn indexed_access(
1044        &mut self,
1045        expression: &'a Expression,
1046        index: &'a Expression,
1047    ) -> Document<'a> {
1048        self.expression(expression)
1049            .append("[")
1050            .append(self.expression(index))
1051            .append("]")
1052    }
1053
1054    fn tuple(&mut self, elements: &'a [Expression]) -> Document<'a> {
1055        if elements.is_empty() {
1056            return Document::str("()");
1057        }
1058
1059        let elements_docs: Vec<_> = elements.iter().map(|e| self.expression(e)).collect();
1060        let elements_doc = join(elements_docs, strict_break(",", ", "));
1061
1062        Document::str("(")
1063            .append(strict_break("", ""))
1064            .append(elements_doc)
1065            .nest(INDENT_WIDTH)
1066            .append(strict_break(",", ""))
1067            .append(")")
1068            .group()
1069    }
1070
1071    fn struct_call(
1072        &mut self,
1073        name: &'a str,
1074        fields: &'a [StructFieldAssignment],
1075        spread: &'a Option<Expression>,
1076    ) -> Document<'a> {
1077        let mut field_docs: Vec<_> = fields
1078            .iter()
1079            .map(|f| {
1080                if let Expression::Identifier { value, .. } = &*f.value
1081                    && value == &f.name
1082                {
1083                    return Document::string(f.name.to_string());
1084                }
1085                Document::string(f.name.to_string())
1086                    .append(": ")
1087                    .append(self.expression(&f.value))
1088            })
1089            .collect();
1090
1091        if let Some(spread_expression) = spread {
1092            let start = spread_expression.get_span().byte_offset;
1093            let comments = self.comments.take_comments_before(start);
1094            let spread_doc = Document::str("..").append(self.expression(spread_expression));
1095            field_docs.push(prepend_comments(spread_doc, comments));
1096        }
1097
1098        if field_docs.is_empty() {
1099            return Document::str(name).append(" {}");
1100        }
1101
1102        let fields_doc = join(field_docs, strict_break(",", ", "));
1103
1104        Document::str(name)
1105            .append(" {")
1106            .append(strict_break(" ", " "))
1107            .append(fields_doc)
1108            .nest(INDENT_WIDTH)
1109            .append(strict_break(",", " "))
1110            .append("}")
1111            .group()
1112    }
1113
1114    fn assignment(
1115        &mut self,
1116        target: &'a Expression,
1117        value: &'a Expression,
1118        compound_operator: Option<BinaryOperator>,
1119    ) -> Document<'a> {
1120        if let Some(op) = compound_operator
1121            && let Some(op_str) = match op {
1122                BinaryOperator::Addition => Some("+="),
1123                BinaryOperator::Subtraction => Some("-="),
1124                BinaryOperator::Multiplication => Some("*="),
1125                BinaryOperator::Division => Some("/="),
1126                BinaryOperator::Remainder => Some("%="),
1127                _ => None,
1128            }
1129            && let Expression::Binary { right, .. } = value
1130        {
1131            return self
1132                .expression(target)
1133                .append(" ")
1134                .append(op_str)
1135                .append(" ")
1136                .append(self.expression(right));
1137        }
1138
1139        self.expression(target)
1140            .append(" = ")
1141            .append(self.expression(value))
1142    }
1143
1144    fn lambda(
1145        &mut self,
1146        params: &'a [Binding],
1147        return_annotation: &'a Annotation,
1148        body: &'a Expression,
1149        _span: &'a Span,
1150    ) -> Document<'a> {
1151        let params_docs: Vec<_> = params.iter().map(|p| self.binding(p)).collect();
1152
1153        let params_doc = if params_docs.is_empty() {
1154            Document::str("||")
1155        } else {
1156            Document::str("|")
1157                .append(join(params_docs, Document::str(", ")))
1158                .append("|")
1159        };
1160
1161        let return_doc = if return_annotation.is_unknown() {
1162            Document::Sequence(vec![])
1163        } else {
1164            Document::str(" -> ").append(Self::annotation(return_annotation))
1165        };
1166
1167        let body_doc = self.expression(body);
1168
1169        params_doc.append(return_doc).append(" ").append(body_doc)
1170    }
1171
1172    fn task(&mut self, expression: &'a Expression) -> Document<'a> {
1173        Document::str("task ").append(self.expression(expression))
1174    }
1175
1176    fn defer_(&mut self, expression: &'a Expression) -> Document<'a> {
1177        Document::str("defer ").append(self.expression(expression))
1178    }
1179
1180    fn try_block(&mut self, items: &'a [Expression], span: &Span) -> Document<'a> {
1181        Document::str("try ").append(self.block(items, span))
1182    }
1183
1184    fn recover_block(&mut self, items: &'a [Expression], span: &Span) -> Document<'a> {
1185        Document::str("recover ").append(self.block(items, span))
1186    }
1187
1188    fn range(
1189        &mut self,
1190        start: &'a Option<Box<Expression>>,
1191        end: &'a Option<Box<Expression>>,
1192        inclusive: bool,
1193    ) -> Document<'a> {
1194        let start_doc = match start {
1195            Some(e) => self.expression(e),
1196            None => Document::Sequence(vec![]),
1197        };
1198        let end_doc = match end {
1199            Some(e) => self.expression(e),
1200            None => Document::Sequence(vec![]),
1201        };
1202        let op = if inclusive { "..=" } else { ".." };
1203        start_doc.append(op).append(end_doc)
1204    }
1205
1206    fn cast(&mut self, expression: &'a Expression, target_type: &'a Annotation) -> Document<'a> {
1207        self.expression(expression)
1208            .append(" as ")
1209            .append(Self::annotation(target_type))
1210    }
1211
1212    fn select(&mut self, arms: &'a [SelectArm]) -> Document<'a> {
1213        let arms_docs: Vec<_> = arms.iter().map(|arm| self.select_arm(arm)).collect();
1214        Self::braced_body(Document::str("select"), join(arms_docs, Document::Newline))
1215    }
1216
1217    fn select_arm(&mut self, arm: &'a SelectArm) -> Document<'a> {
1218        match &arm.pattern {
1219            SelectArmPattern::Receive {
1220                binding,
1221                receive_expression,
1222                body,
1223                ..
1224            } => Document::str("let ")
1225                .append(self.pattern(binding))
1226                .append(" = ")
1227                .append(self.expression(receive_expression))
1228                .append(" => ")
1229                .append(self.expression(body))
1230                .append(","),
1231            SelectArmPattern::Send {
1232                send_expression,
1233                body,
1234            } => self
1235                .expression(send_expression)
1236                .append(" => ")
1237                .append(self.expression(body))
1238                .append(","),
1239            SelectArmPattern::MatchReceive {
1240                receive_expression,
1241                arms,
1242            } => {
1243                let arms_docs: Vec<_> = arms
1244                    .iter()
1245                    .map(|a| {
1246                        let pattern = self.pattern(&a.pattern);
1247                        let expression = self.expression(&a.expression);
1248                        let pattern_with_guard = if let Some(guard) = &a.guard {
1249                            pattern.append(" if ").append(self.expression(guard))
1250                        } else {
1251                            pattern
1252                        };
1253                        pattern_with_guard
1254                            .append(" => ")
1255                            .append(expression)
1256                            .append(",")
1257                    })
1258                    .collect();
1259                let header = Document::str("match ").append(self.expression(receive_expression));
1260                Self::braced_body(header, join(arms_docs, Document::Newline)).append(",")
1261            }
1262            SelectArmPattern::WildCard { body } => Document::str("_")
1263                .append(" => ")
1264                .append(self.expression(body))
1265                .append(","),
1266        }
1267    }
1268
1269    fn propagate_(&mut self, expression: &'a Expression) -> Document<'a> {
1270        self.expression(expression).append("?")
1271    }
1272
1273    fn ref_(&mut self, expression: &'a Expression) -> Document<'a> {
1274        Document::str("&").append(self.expression(expression))
1275    }
1276
1277    fn raw_go(text: &'a str) -> Document<'a> {
1278        Document::str("@rawgo(\"")
1279            .append(Document::str(text))
1280            .append("\")")
1281    }
1282
1283    fn struct_definition(
1284        &mut self,
1285        name: &'a str,
1286        generics: &'a [Generic],
1287        fields: &'a [StructFieldDefinition],
1288        span: &Span,
1289        kind: StructKind,
1290    ) -> Document<'a> {
1291        let generics_doc = Self::generics(generics);
1292        let header = Document::str("struct ").append(name).append(generics_doc);
1293        let struct_end = span.byte_offset + span.byte_length;
1294
1295        if kind == StructKind::Tuple {
1296            let type_docs: Vec<_> = fields
1297                .iter()
1298                .map(|f| Self::annotation(&f.annotation))
1299                .collect();
1300            return header
1301                .append("(")
1302                .append(join(type_docs, Document::str(", ")))
1303                .append(")");
1304        }
1305
1306        let with_field_attrs = fields.iter().any(|f| !f.attributes.is_empty());
1307        let with_pub_fields = fields.iter().any(|f| f.visibility.is_public());
1308
1309        if fields.is_empty() {
1310            return self.empty_struct_body(header, struct_end);
1311        }
1312
1313        let (field_entries, with_comments) = self.struct_fields_with_comments(fields, struct_end);
1314
1315        if with_comments || with_field_attrs || with_pub_fields {
1316            let fields_docs: Vec<_> = field_entries
1317                .into_iter()
1318                .map(|(field, comment)| match comment {
1319                    Some(c) => field.append(",").append(" ").append(c),
1320                    None => field.append(","),
1321                })
1322                .collect();
1323            return Self::braced_body(header, join(fields_docs, Document::Newline));
1324        }
1325
1326        let fields_docs: Vec<_> = field_entries.into_iter().map(|(field, _)| field).collect();
1327        Self::flexible_struct_body(header, fields_docs)
1328    }
1329
1330    fn empty_struct_body(&mut self, header: Document<'a>, end: u32) -> Document<'a> {
1331        match self.comments.take_comments_before(end) {
1332            Some(c) => header
1333                .append(" {")
1334                .append(Document::Newline.append(c).nest(INDENT_WIDTH))
1335                .append(Document::Newline)
1336                .append("}")
1337                .force_break(),
1338            None => header.append(" {}"),
1339        }
1340    }
1341
1342    fn struct_fields_with_comments(
1343        &mut self,
1344        fields: &'a [StructFieldDefinition],
1345        struct_end: u32,
1346    ) -> (Vec<(Document<'a>, Option<Document<'a>>)>, bool) {
1347        let mut entries = Vec::new();
1348        let mut with_comments = false;
1349
1350        for (i, field) in fields.iter().enumerate() {
1351            let comment_limit = if i + 1 < fields.len() {
1352                fields[i + 1].name_span.byte_offset
1353            } else {
1354                struct_end
1355            };
1356
1357            let field_attrs = Self::field_attributes(&field.attributes);
1358
1359            let field_definition = if field.visibility.is_public() {
1360                Document::str("pub ")
1361                    .append(Document::string(field.name.to_string()))
1362                    .append(": ")
1363                    .append(Self::annotation(&field.annotation))
1364            } else {
1365                Document::string(field.name.to_string())
1366                    .append(": ")
1367                    .append(Self::annotation(&field.annotation))
1368            };
1369
1370            let field_doc = field_attrs.append(field_definition);
1371
1372            let comment_doc = self.comments.take_comments_before(comment_limit);
1373            with_comments = with_comments || comment_doc.is_some();
1374
1375            entries.push((field_doc, comment_doc));
1376        }
1377
1378        (entries, with_comments)
1379    }
1380
1381    fn field_attributes(attrs: &'a [Attribute]) -> Document<'a> {
1382        if attrs.is_empty() {
1383            return Document::Sequence(vec![]);
1384        }
1385
1386        let attribute_docs: Vec<_> = attrs.iter().map(Self::attribute).collect();
1387        join(attribute_docs, Document::Newline).append(Document::Newline)
1388    }
1389
1390    fn braced_body(header: Document<'a>, body: Document<'a>) -> Document<'a> {
1391        header
1392            .append(" {")
1393            .append(Document::Newline.append(body).nest(INDENT_WIDTH))
1394            .append(Document::Newline)
1395            .append("}")
1396            .force_break()
1397    }
1398
1399    fn flexible_struct_body(header: Document<'a>, items: Vec<Document<'a>>) -> Document<'a> {
1400        let items_doc = join(items, strict_break(",", ", "));
1401        header
1402            .append(" {")
1403            .append(strict_break("", " "))
1404            .append(items_doc)
1405            .nest(INDENT_WIDTH)
1406            .append(strict_break(",", " "))
1407            .append("}")
1408            .group()
1409    }
1410
1411    fn enum_definition(
1412        &mut self,
1413        name: &'a str,
1414        generics: &'a [Generic],
1415        variants: &'a [EnumVariant],
1416    ) -> Document<'a> {
1417        let generics_doc = Self::generics(generics);
1418        let header = Document::str("enum ").append(name).append(generics_doc);
1419
1420        if variants.is_empty() {
1421            return header.append(" {}");
1422        }
1423
1424        let variants_docs: Vec<_> = variants.iter().map(|v| self.enum_variant(v)).collect();
1425        Self::braced_body(header, join(variants_docs, Document::Newline))
1426    }
1427
1428    fn value_enum_definition(
1429        &mut self,
1430        name: &'a str,
1431        underlying_ty: Option<&'a syntax::ast::Annotation>,
1432        variants: &'a [syntax::ast::ValueEnumVariant],
1433    ) -> Document<'a> {
1434        let header = if let Some(ty) = underlying_ty {
1435            Document::str("enum ")
1436                .append(name)
1437                .append(": ")
1438                .append(Self::annotation(ty))
1439        } else {
1440            Document::str("enum ").append(name)
1441        };
1442
1443        if variants.is_empty() {
1444            return header.append(" {}");
1445        }
1446
1447        let variants_docs: Vec<_> = variants
1448            .iter()
1449            .map(|v| self.value_enum_variant(v))
1450            .collect();
1451
1452        Self::braced_body(header, join(variants_docs, Document::Newline))
1453    }
1454
1455    fn enum_variant(&mut self, variant: &'a EnumVariant) -> Document<'a> {
1456        let name = Document::string(variant.name.to_string());
1457
1458        match &variant.fields {
1459            VariantFields::Unit => name.append(","),
1460            VariantFields::Tuple(fields) => {
1461                let field_docs: Vec<_> = fields
1462                    .iter()
1463                    .map(|f| Self::annotation(&f.annotation))
1464                    .collect();
1465                name.append("(")
1466                    .append(join(field_docs, Document::str(", ")))
1467                    .append("),")
1468            }
1469            VariantFields::Struct(fields) => {
1470                let field_docs: Vec<_> = fields
1471                    .iter()
1472                    .map(|f| {
1473                        Document::string(f.name.to_string())
1474                            .append(": ")
1475                            .append(Self::annotation(&f.annotation))
1476                    })
1477                    .collect();
1478                name.append(" { ")
1479                    .append(join(field_docs, Document::str(", ")))
1480                    .append(" },")
1481            }
1482        }
1483    }
1484
1485    fn value_enum_variant(&mut self, variant: &'a syntax::ast::ValueEnumVariant) -> Document<'a> {
1486        let name = Document::string(variant.name.to_string());
1487        let value_doc = self.literal(&variant.value);
1488        name.append(" = ").append(value_doc).append(",")
1489    }
1490
1491    fn type_alias(
1492        name: &'a str,
1493        generics: &'a [Generic],
1494        annotation: &'a Annotation,
1495    ) -> Document<'a> {
1496        let generics_doc = Self::generics(generics);
1497
1498        let base = Document::str("type ").append(name).append(generics_doc);
1499
1500        if annotation.is_opaque() {
1501            base
1502        } else {
1503            base.append(" = ").append(Self::annotation(annotation))
1504        }
1505    }
1506
1507    fn interface(
1508        &mut self,
1509        name: &'a str,
1510        generics: &'a [Generic],
1511        parents: &'a [ParentInterface],
1512        methods: &'a [Expression],
1513    ) -> Document<'a> {
1514        let generics_doc = Self::generics(generics);
1515
1516        let mut body_docs = Vec::new();
1517
1518        for parent in parents {
1519            body_docs.push(Document::str("impl ").append(Self::annotation(&parent.annotation)));
1520        }
1521
1522        for method in methods {
1523            body_docs.push(self.interface_method(method));
1524        }
1525
1526        let header = Document::str("interface ")
1527            .append(name)
1528            .append(generics_doc);
1529
1530        if body_docs.is_empty() {
1531            return header.append(" {}");
1532        }
1533
1534        Self::braced_body(header, join(body_docs, Document::Newline))
1535    }
1536
1537    fn interface_method(&mut self, method: &'a Expression) -> Document<'a> {
1538        match method {
1539            Expression::Function {
1540                name,
1541                generics,
1542                params,
1543                return_annotation,
1544                attributes,
1545                ..
1546            } => {
1547                let attrs_doc = Self::attributes(attributes);
1548                let generics_doc = Self::generics(generics);
1549
1550                let params_docs: Vec<_> = params.iter().map(|p| self.binding(p)).collect();
1551                let params_doc = Self::wrap_params(params_docs);
1552
1553                let return_doc = if return_annotation.is_unknown() {
1554                    Document::Sequence(vec![])
1555                } else {
1556                    Document::str(" -> ").append(Self::annotation(return_annotation))
1557                };
1558
1559                attrs_doc
1560                    .append(Document::str("fn "))
1561                    .append(Document::string(name.to_string()))
1562                    .append(generics_doc)
1563                    .append(params_doc)
1564                    .append(return_doc)
1565            }
1566            _ => Document::Sequence(vec![]),
1567        }
1568    }
1569
1570    fn impl_block(
1571        &mut self,
1572        annotation: &'a Annotation,
1573        generics: &'a [Generic],
1574        methods: &'a [Expression],
1575        impl_end: u32,
1576    ) -> Document<'a> {
1577        let generics_doc = Self::generics(generics);
1578        let header = Document::str("impl")
1579            .append(generics_doc)
1580            .append(" ")
1581            .append(Self::annotation(annotation));
1582
1583        if methods.is_empty() {
1584            return header.append(" {}");
1585        }
1586
1587        let mut docs = Vec::with_capacity(methods.len() * 5);
1588
1589        for (i, m) in methods.iter().enumerate() {
1590            let start = m.get_span().byte_offset;
1591
1592            if i > 0 {
1593                docs.push(Document::Newline);
1594                docs.push(Document::Newline);
1595            }
1596
1597            if let Some(comment_doc) = self.comments.take_comments_before(start) {
1598                docs.push(comment_doc.force_break());
1599                docs.push(Document::Newline);
1600            }
1601
1602            docs.push(self.definition(m));
1603        }
1604
1605        if let Some(trailing) = self.comments.take_comments_before(impl_end) {
1606            docs.push(Document::Newline);
1607            docs.push(Document::Newline);
1608            docs.push(trailing.force_break());
1609        }
1610
1611        Self::braced_body(header, concat(docs))
1612    }
1613
1614    fn const_definition(
1615        &mut self,
1616        name: &'a str,
1617        annotation: Option<&'a Annotation>,
1618        value: &'a Expression,
1619    ) -> Document<'a> {
1620        let type_doc = match annotation {
1621            Some(ann) => Document::str(": ").append(Self::annotation(ann)),
1622            None => Document::Sequence(vec![]),
1623        };
1624
1625        Document::str("const ")
1626            .append(name)
1627            .append(type_doc)
1628            .append(" = ")
1629            .append(self.expression(value))
1630    }
1631
1632    fn pattern(&mut self, pat: &'a Pattern) -> Document<'a> {
1633        match pat {
1634            Pattern::Literal { literal, .. } => self.literal(literal),
1635            Pattern::Unit { .. } => Document::str("()"),
1636            Pattern::WildCard { .. } => Document::str("_"),
1637            Pattern::Identifier { identifier, .. } => Document::string(identifier.to_string()),
1638
1639            Pattern::EnumVariant {
1640                identifier,
1641                fields,
1642                rest,
1643                ..
1644            } => {
1645                if fields.is_empty() && !rest {
1646                    Document::string(identifier.to_string())
1647                } else {
1648                    let mut field_docs: Vec<_> = fields
1649                        .iter()
1650                        .map(|f| {
1651                            let start = f.get_span().byte_offset;
1652                            let comments = self.comments.take_comments_before(start);
1653                            prepend_comments(self.pattern(f), comments)
1654                        })
1655                        .collect();
1656                    if *rest {
1657                        field_docs.push(Document::str(".."));
1658                    }
1659                    Document::string(identifier.to_string())
1660                        .append("(")
1661                        .append(strict_break("", ""))
1662                        .append(join(field_docs, strict_break(",", ", ")))
1663                        .nest(INDENT_WIDTH)
1664                        .append(strict_break(",", ""))
1665                        .append(")")
1666                        .group()
1667                }
1668            }
1669
1670            Pattern::Struct {
1671                identifier,
1672                fields,
1673                rest,
1674                ..
1675            } => {
1676                if fields.is_empty() && !rest {
1677                    Document::string(identifier.to_string()).append(" {}")
1678                } else {
1679                    let mut field_docs: Vec<_> = fields
1680                        .iter()
1681                        .map(|f| {
1682                            let start = f.value.get_span().byte_offset;
1683                            let comments = self.comments.take_comments_before(start);
1684                            prepend_comments(self.struct_field_pattern(f), comments)
1685                        })
1686                        .collect();
1687                    if *rest {
1688                        field_docs.push(Document::str(".."));
1689                    }
1690                    Document::string(identifier.to_string())
1691                        .append(" {")
1692                        .append(strict_break(" ", " "))
1693                        .append(join(field_docs, strict_break(",", ", ")))
1694                        .nest(INDENT_WIDTH)
1695                        .append(strict_break(",", " "))
1696                        .append("}")
1697                        .group()
1698                }
1699            }
1700
1701            Pattern::Tuple { elements, .. } => {
1702                let elements_docs: Vec<_> = elements
1703                    .iter()
1704                    .map(|e| {
1705                        let start = e.get_span().byte_offset;
1706                        let comments = self.comments.take_comments_before(start);
1707                        prepend_comments(self.pattern(e), comments)
1708                    })
1709                    .collect();
1710                Document::str("(")
1711                    .append(strict_break("", ""))
1712                    .append(join(elements_docs, strict_break(",", ", ")))
1713                    .nest(INDENT_WIDTH)
1714                    .append(strict_break(",", ""))
1715                    .append(")")
1716                    .group()
1717            }
1718
1719            Pattern::Slice { prefix, rest, .. } => {
1720                let mut all_docs: Vec<Document<'a>> = Vec::new();
1721
1722                for pattern in prefix {
1723                    let start = pattern.get_span().byte_offset;
1724                    let comments = self.comments.take_comments_before(start);
1725                    all_docs.push(prepend_comments(self.pattern(pattern), comments));
1726                }
1727
1728                match rest {
1729                    RestPattern::Absent => {}
1730                    RestPattern::Discard(_) => {
1731                        all_docs.push(Document::str(".."));
1732                    }
1733                    RestPattern::Bind { name, .. } => {
1734                        all_docs
1735                            .push(Document::str("..").append(Document::string(name.to_string())));
1736                    }
1737                }
1738
1739                Document::str("[")
1740                    .append(strict_break("", ""))
1741                    .append(join(all_docs, strict_break(",", ", ")))
1742                    .nest(INDENT_WIDTH)
1743                    .append(strict_break(",", ""))
1744                    .append("]")
1745                    .group()
1746            }
1747
1748            Pattern::Or { patterns, .. } => {
1749                let pattern_docs: Vec<_> = patterns.iter().map(|p| self.pattern(p)).collect();
1750                join(pattern_docs, Document::str(" | "))
1751            }
1752
1753            Pattern::AsBinding { pattern, name, .. } => self
1754                .pattern(pattern)
1755                .append(" as ")
1756                .append(Document::string(name.to_string())),
1757        }
1758    }
1759
1760    fn struct_field_pattern(&mut self, field: &'a StructFieldPattern) -> Document<'a> {
1761        if let Pattern::Identifier { identifier, .. } = &field.value
1762            && identifier == &field.name
1763        {
1764            return Document::string(field.name.to_string());
1765        }
1766
1767        Document::string(field.name.to_string())
1768            .append(": ")
1769            .append(self.pattern(&field.value))
1770    }
1771
1772    fn binding(&mut self, binding: &'a Binding) -> Document<'a> {
1773        let pattern_doc = if binding.mutable {
1774            Document::str("mut ").append(self.pattern(&binding.pattern))
1775        } else {
1776            self.pattern(&binding.pattern)
1777        };
1778
1779        match &binding.annotation {
1780            Some(annotation) => pattern_doc
1781                .append(": ")
1782                .append(Self::annotation(annotation)),
1783            None => pattern_doc,
1784        }
1785    }
1786
1787    fn annotation(annotation: &'a Annotation) -> Document<'a> {
1788        match annotation {
1789            Annotation::Constructor { name, params, .. } => {
1790                if params.is_empty() {
1791                    if name == "Unit" {
1792                        Document::str("()")
1793                    } else {
1794                        Document::string(name.to_string())
1795                    }
1796                } else {
1797                    let param_docs: Vec<_> = params.iter().map(Self::annotation).collect();
1798                    Document::string(name.to_string())
1799                        .append("<")
1800                        .append(join(param_docs, Document::str(", ")))
1801                        .append(">")
1802                }
1803            }
1804            Annotation::Function {
1805                params,
1806                return_type,
1807                ..
1808            } => {
1809                let param_docs: Vec<_> = params.iter().map(Self::annotation).collect();
1810                Document::str("fn(")
1811                    .append(join(param_docs, Document::str(", ")))
1812                    .append(") -> ")
1813                    .append(Self::annotation(return_type))
1814            }
1815            Annotation::Unknown => Document::str("_"),
1816            Annotation::Tuple { elements, .. } => {
1817                let elem_docs: Vec<_> = elements.iter().map(Self::annotation).collect();
1818                Document::str("(")
1819                    .append(join(elem_docs, Document::str(", ")))
1820                    .append(")")
1821            }
1822            Annotation::Opaque { .. } => Document::Sequence(vec![]),
1823        }
1824    }
1825
1826    fn generics(generics: &'a [Generic]) -> Document<'a> {
1827        if generics.is_empty() {
1828            return Document::Sequence(vec![]);
1829        }
1830
1831        let generics_docs: Vec<_> = generics
1832            .iter()
1833            .map(|g| {
1834                if g.bounds.is_empty() {
1835                    Document::string(g.name.to_string())
1836                } else {
1837                    let bounds: Vec<_> = g.bounds.iter().map(Self::annotation).collect();
1838                    Document::string(g.name.to_string())
1839                        .append(": ")
1840                        .append(join(bounds, Document::str(" + ")))
1841                }
1842            })
1843            .collect();
1844
1845        Document::str("<")
1846            .append(join(generics_docs, Document::str(", ")))
1847            .append(">")
1848    }
1849
1850    fn attribute(attribute: &'a Attribute) -> Document<'a> {
1851        let name = Document::string(attribute.name.clone());
1852
1853        if attribute.args.is_empty() {
1854            Document::str("#[").append(name).append("]")
1855        } else {
1856            let args_docs: Vec<_> = attribute.args.iter().map(Self::attribute_arg).collect();
1857            Document::str("#[")
1858                .append(name)
1859                .append("(")
1860                .append(join(args_docs, Document::str(", ")))
1861                .append(")]")
1862        }
1863    }
1864
1865    fn attribute_arg(arg: &'a AttributeArg) -> Document<'a> {
1866        match arg {
1867            AttributeArg::Flag(name) => Document::string(name.clone()),
1868            AttributeArg::NegatedFlag(name) => {
1869                Document::str("!").append(Document::string(name.clone()))
1870            }
1871            AttributeArg::String(s) => Document::string(format!("\"{}\"", s)),
1872            AttributeArg::Raw(s) => Document::string(format!("`{}`", s)),
1873        }
1874    }
1875
1876    fn attributes(attrs: &'a [Attribute]) -> Document<'a> {
1877        if attrs.is_empty() {
1878            return Document::Sequence(vec![]);
1879        }
1880
1881        let attribute_docs: Vec<_> = attrs.iter().map(Self::attribute).collect();
1882        join(attribute_docs, Document::Newline).append(Document::Newline)
1883    }
1884}
1885
1886struct MethodChainSegment<'a> {
1887    member: &'a str,
1888    args: &'a [Expression],
1889    spread: &'a Option<Expression>,
1890    type_args: &'a [Annotation],
1891}
1892
1893fn collect_method_chain(expression: &Expression) -> (&Expression, Vec<MethodChainSegment<'_>>) {
1894    let mut segments = Vec::new();
1895    let mut current = expression;
1896
1897    while let Expression::Call {
1898        expression,
1899        args,
1900        spread,
1901        type_args,
1902        ..
1903    } = current
1904    {
1905        let Expression::DotAccess {
1906            expression: inner,
1907            member,
1908            ..
1909        } = expression.as_ref()
1910        else {
1911            break;
1912        };
1913        segments.push(MethodChainSegment {
1914            member,
1915            args,
1916            spread,
1917            type_args,
1918        });
1919        current = inner;
1920    }
1921
1922    segments.reverse();
1923    (current, segments)
1924}
1925
1926fn is_inlinable_arg(expression: &Expression, arity: usize) -> bool {
1927    matches!(
1928        expression,
1929        Expression::Lambda { .. }
1930            | Expression::Block { .. }
1931            | Expression::Match { .. }
1932            | Expression::Tuple { .. }
1933            | Expression::Literal {
1934                literal: Literal::Slice(_),
1935                ..
1936            }
1937    ) || matches!(expression, Expression::Call { .. } if arity == 1)
1938}