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 { value, raw: true } => Document::string(format!("r\"{value}\"")),
538            Literal::String { value, raw: false } => Document::string(format!("\"{value}\"")),
539            Literal::Char(c) => Document::string(format!("'{c}'")),
540            Literal::Slice(elements) => self.slice(elements),
541            Literal::FormatString(parts) => self.format_string(parts),
542        }
543    }
544
545    fn slice(&mut self, elements: &'a [Expression]) -> Document<'a> {
546        if elements.is_empty() {
547            return Document::str("[]");
548        }
549
550        let elements_docs: Vec<_> = elements.iter().map(|e| self.expression(e)).collect();
551        let elements_doc = join(elements_docs, strict_break(",", ", "));
552
553        Document::str("[")
554            .append(strict_break("", ""))
555            .append(elements_doc)
556            .nest(INDENT_WIDTH)
557            .append(strict_break(",", ""))
558            .append("]")
559            .group()
560    }
561
562    fn format_string(&mut self, parts: &'a [FormatStringPart]) -> Document<'a> {
563        let mut docs = vec![Document::str("f\"")];
564
565        for part in parts {
566            match part {
567                FormatStringPart::Text(s) => docs.push(Document::string(s.clone())),
568                FormatStringPart::Expression(e) => {
569                    docs.push(Document::str("{"));
570                    docs.push(self.expression(e));
571                    docs.push(Document::str("}"));
572                }
573            }
574        }
575
576        docs.push(Document::str("\""));
577        concat(docs)
578    }
579
580    fn block(&mut self, items: &'a [Expression], span: &Span) -> Document<'a> {
581        let block_end = span.byte_offset + span.byte_length;
582
583        if items.is_empty() {
584            return match self.comments.take_comments_before(block_end) {
585                Some(c) => Document::str("{")
586                    .append(Document::Newline.append(c).nest(INDENT_WIDTH))
587                    .append(Document::Newline)
588                    .append("}")
589                    .force_break(),
590                None => Document::str("{}"),
591            };
592        }
593
594        let mut docs = Vec::new();
595        let mut previous_end: Option<u32> = None;
596
597        for item in items.iter() {
598            let start = item.get_span().byte_offset;
599
600            if previous_end.is_some() {
601                if self.comments.take_empty_lines_before(start) {
602                    docs.push(Document::Newline);
603                    docs.push(Document::Newline);
604                } else {
605                    docs.push(Document::Newline);
606                }
607            }
608
609            let item_doc = self.expression(item);
610            docs.push(item_doc);
611            previous_end = Some(item.get_span().byte_offset + item.get_span().byte_length);
612        }
613
614        if let Some(trailing_comments_doc) = self.comments.take_comments_before(block_end) {
615            docs.push(Document::str(" "));
616            docs.push(trailing_comments_doc);
617        }
618
619        let body = concat(docs);
620
621        Document::str("{")
622            .append(Document::Newline.append(body).nest(INDENT_WIDTH))
623            .append(Document::Newline)
624            .append("}")
625            .force_break()
626    }
627
628    fn let_(
629        &mut self,
630        binding: &'a Binding,
631        value: &'a Expression,
632        mutable: bool,
633        else_block: Option<&'a Expression>,
634    ) -> Document<'a> {
635        let keyword = if mutable { "let mut " } else { "let " };
636
637        let base = Document::str(keyword)
638            .append(self.binding(binding))
639            .append(" = ")
640            .append(self.expression(value));
641
642        if let Some(else_expression) = else_block {
643            base.append(" else ").append(self.as_block(else_expression))
644        } else {
645            base
646        }
647    }
648
649    fn return_(&mut self, expression: &'a Expression) -> Document<'a> {
650        if matches!(expression, Expression::Unit { .. }) {
651            Document::str("return")
652        } else {
653            Document::str("return ").append(self.expression(expression))
654        }
655    }
656
657    fn if_(
658        &mut self,
659        condition: &'a Expression,
660        consequence: &'a Expression,
661        alternative: &'a Expression,
662    ) -> Document<'a> {
663        let if_doc = Document::str("if ")
664            .append(self.expression(condition))
665            .append(" ")
666            .append(self.as_inline_block(consequence));
667
668        match alternative {
669            Expression::Unit { .. } => if_doc,
670            Expression::If { .. } | Expression::IfLet { .. } => {
671                if_doc.append(" else ").append(self.expression(alternative))
672            }
673            _ => if_doc
674                .append(" else ")
675                .append(self.as_inline_block(alternative)),
676        }
677        .group()
678    }
679
680    fn if_let(
681        &mut self,
682        pattern: &'a Pattern,
683        scrutinee: &'a Expression,
684        consequence: &'a Expression,
685        alternative: &'a Expression,
686    ) -> Document<'a> {
687        let if_let_doc = Document::str("if let ")
688            .append(self.pattern(pattern))
689            .append(" = ")
690            .append(self.expression(scrutinee))
691            .append(" ")
692            .append(self.as_inline_block(consequence));
693
694        match alternative {
695            Expression::Unit { .. } => if_let_doc,
696            Expression::If { .. } | Expression::IfLet { .. } => if_let_doc
697                .append(" else ")
698                .append(self.expression(alternative)),
699            _ => if_let_doc
700                .append(" else ")
701                .append(self.as_inline_block(alternative)),
702        }
703        .group()
704    }
705
706    fn as_block(&mut self, expression: &'a Expression) -> Document<'a> {
707        match expression {
708            Expression::Block { items, span, .. } => self.block(items, span),
709            Expression::NoOp => Document::Sequence(vec![]),
710            _ => Document::str("{ ")
711                .append(self.expression(expression))
712                .append(" }"),
713        }
714    }
715
716    /// Like as_block, but allows single-expression blocks to stay inline.
717    /// Used for if/else branches where `{ expression }` should stay on one line
718    /// when the containing group fits, and expand to multi-line when it doesn't.
719    fn as_inline_block(&mut self, expression: &'a Expression) -> Document<'a> {
720        match expression {
721            Expression::Block { items, span, .. } => {
722                if items.len() == 1 && !self.comments.has_comments_in_range(*span) {
723                    let expression = self.expression(&items[0]);
724                    return Document::str("{")
725                        .append(strict_break("", " ").append(expression).nest(INDENT_WIDTH))
726                        .append(strict_break("", " "))
727                        .append("}");
728                }
729                self.block(items, span)
730            }
731            Expression::NoOp => Document::Sequence(vec![]),
732            _ => {
733                let expression = self.expression(expression);
734                Document::str("{")
735                    .append(strict_break("", " ").append(expression).nest(INDENT_WIDTH))
736                    .append(strict_break("", " "))
737                    .append("}")
738            }
739        }
740    }
741
742    fn match_(&mut self, subject: &'a Expression, arms: &'a [MatchArm]) -> Document<'a> {
743        let arms_docs: Vec<_> = arms
744            .iter()
745            .map(|arm| {
746                let start = arm.pattern.get_span().byte_offset;
747                let comments = self.comments.take_comments_before(start);
748                let pattern = self.pattern(&arm.pattern);
749                let expression = self.expression(&arm.expression);
750
751                let pattern_with_guard = if let Some(guard) = &arm.guard {
752                    pattern.append(" if ").append(self.expression(guard))
753                } else {
754                    pattern
755                };
756
757                let arm_doc = pattern_with_guard
758                    .append(" => ")
759                    .append(expression)
760                    .append(",");
761                prepend_comments(arm_doc, comments)
762            })
763            .collect();
764
765        let header = Document::str("match ").append(self.expression(subject));
766        Self::braced_body(header, join(arms_docs, Document::Newline))
767    }
768
769    fn loop_(&mut self, body: &'a Expression) -> Document<'a> {
770        Document::str("loop ").append(self.as_block(body))
771    }
772
773    fn while_(&mut self, condition: &'a Expression, body: &'a Expression) -> Document<'a> {
774        Document::str("while ")
775            .append(self.expression(condition))
776            .append(" ")
777            .append(self.as_block(body))
778    }
779
780    fn while_let(
781        &mut self,
782        pattern: &'a Pattern,
783        scrutinee: &'a Expression,
784        body: &'a Expression,
785    ) -> Document<'a> {
786        Document::str("while let ")
787            .append(self.pattern(pattern))
788            .append(" = ")
789            .append(self.expression(scrutinee))
790            .append(" ")
791            .append(self.as_block(body))
792    }
793
794    fn for_(
795        &mut self,
796        binding: &'a Binding,
797        iterable: &'a Expression,
798        body: &'a Expression,
799    ) -> Document<'a> {
800        Document::str("for ")
801            .append(self.binding(binding))
802            .append(" in ")
803            .append(self.expression(iterable))
804            .append(" ")
805            .append(self.as_block(body))
806    }
807
808    fn binary_operator(
809        &mut self,
810        operator: &BinaryOperator,
811        left_operand: &'a Expression,
812        right_operand: &'a Expression,
813    ) -> Document<'a> {
814        use BinaryOperator::*;
815
816        if matches!(operator, Pipeline) {
817            return self.pipeline(left_operand, right_operand);
818        }
819
820        let operator_string = match operator {
821            Addition => "+",
822            Subtraction => "-",
823            Multiplication => "*",
824            Division => "/",
825            Remainder => "%",
826            LessThan => "<",
827            LessThanOrEqual => "<=",
828            GreaterThan => ">",
829            GreaterThanOrEqual => ">=",
830            Equal => "==",
831            NotEqual => "!=",
832            And => "&&",
833            Or => "||",
834            Pipeline => unreachable!(),
835        };
836
837        self.expression(left_operand)
838            .append(" ")
839            .append(operator_string)
840            .append(strict_break("", " "))
841            .append(self.expression(right_operand))
842            .group()
843    }
844
845    fn pipeline(&mut self, left: &'a Expression, right: &'a Expression) -> Document<'a> {
846        let mut segments = vec![right];
847        let mut current = left;
848
849        while let Expression::Binary {
850            operator: BinaryOperator::Pipeline,
851            left: l,
852            right: r,
853            ..
854        } = current
855        {
856            segments.push(r);
857            current = l;
858        }
859        segments.push(current);
860        segments.reverse();
861
862        if segments.len() == 2 {
863            return self
864                .expression(segments[0])
865                .append(flex_break("", " "))
866                .append("|> ")
867                .append(self.expression(segments[1]))
868                .nest_if_broken(INDENT_WIDTH)
869                .group();
870        }
871
872        let docs: Vec<_> = segments
873            .iter()
874            .enumerate()
875            .map(|(i, seg)| {
876                if i == 0 {
877                    self.expression(seg)
878                } else {
879                    Document::Newline.append("|> ").append(self.expression(seg))
880                }
881            })
882            .collect();
883
884        concat(docs).nest(INDENT_WIDTH)
885    }
886
887    fn unary_operator(
888        &mut self,
889        operator: &UnaryOperator,
890        expression: &'a Expression,
891    ) -> Document<'a> {
892        match operator {
893            UnaryOperator::Negative => Document::str("-").append(self.expression(expression)),
894            UnaryOperator::Not => Document::str("!").append(self.expression(expression)),
895            UnaryOperator::Deref => self.expression(expression).append(".*"),
896        }
897    }
898
899    fn call(
900        &mut self,
901        callee: &'a Expression,
902        args: &'a [Expression],
903        spread: &'a Option<Expression>,
904        type_args: &'a [Annotation],
905    ) -> Document<'a> {
906        if let Expression::DotAccess {
907            expression: inner,
908            member,
909            ..
910        } = callee
911        {
912            let (root, mut chain_segments) = collect_method_chain(inner);
913            chain_segments.push(MethodChainSegment {
914                member,
915                args,
916                spread,
917                type_args,
918            });
919            if chain_segments.len() >= 2 {
920                return self.format_method_chain(root, &chain_segments);
921            }
922        }
923
924        let head = self
925            .expression(callee)
926            .append(Self::format_type_args(type_args));
927        self.format_call_with_head(head, args, spread)
928    }
929
930    fn format_type_args(type_args: &'a [Annotation]) -> Document<'a> {
931        if type_args.is_empty() {
932            Document::Sequence(vec![])
933        } else {
934            let types: Vec<_> = type_args.iter().map(Self::annotation).collect();
935            Document::str("<")
936                .append(join(types, Document::str(", ")))
937                .append(">")
938        }
939    }
940
941    fn format_call_with_head(
942        &mut self,
943        head: Document<'a>,
944        args: &'a [Expression],
945        spread: &'a Option<Expression>,
946    ) -> Document<'a> {
947        if args.is_empty() && spread.is_none() {
948            return head.append("()");
949        }
950
951        if let Some(spread_expr) = spread {
952            let spread_doc = Document::str("..").append(self.expression(spread_expr));
953            if args.is_empty() {
954                return head
955                    .append("(")
956                    .append(spread_doc.group().next_break_fits(true))
957                    .append(")")
958                    .next_break_fits(false)
959                    .group();
960            }
961            let init_docs: Vec<_> = args.iter().map(|a| self.expression(a)).collect();
962            let init_doc = join(init_docs, strict_break(",", ", "));
963            return head
964                .append("(")
965                .append(strict_break("", ""))
966                .append(init_doc)
967                .append(strict_break(",", ", "))
968                .append(spread_doc.group().next_break_fits(true))
969                .nest(INDENT_WIDTH)
970                .append(strict_break(",", ""))
971                .append(")")
972                .next_break_fits(false)
973                .group();
974        }
975
976        let Some((last, init)) = args
977            .split_last()
978            .filter(|(last, _)| is_inlinable_arg(last, args.len()))
979        else {
980            let arg_docs: Vec<_> = args.iter().map(|a| self.expression(a)).collect();
981            let args_doc = join(arg_docs, strict_break(",", ", "));
982
983            return head
984                .append("(")
985                .append(strict_break("", ""))
986                .append(args_doc)
987                .nest(INDENT_WIDTH)
988                .append(strict_break(",", ""))
989                .append(")")
990                .group();
991        };
992
993        let last_doc = self.expression(last).group().next_break_fits(true);
994
995        if init.is_empty() {
996            head.append("(")
997                .append(last_doc)
998                .append(")")
999                .next_break_fits(false)
1000                .group()
1001        } else {
1002            let init_docs: Vec<_> = init.iter().map(|a| self.expression(a)).collect();
1003            let init_doc = join(init_docs, strict_break(",", ", "));
1004
1005            head.append("(")
1006                .append(strict_break("", ""))
1007                .append(init_doc)
1008                .append(strict_break(",", ", "))
1009                .append(last_doc)
1010                .nest(INDENT_WIDTH)
1011                .append(strict_break(",", ""))
1012                .append(")")
1013                .next_break_fits(false)
1014                .group()
1015        }
1016    }
1017
1018    fn format_method_chain(
1019        &mut self,
1020        root: &'a Expression,
1021        segments: &[MethodChainSegment<'a>],
1022    ) -> Document<'a> {
1023        let root_doc = self.expression(root);
1024
1025        let segment_docs: Vec<Document<'a>> = segments
1026            .iter()
1027            .map(|seg| {
1028                let head = Document::str(".")
1029                    .append(seg.member)
1030                    .append(Self::format_type_args(seg.type_args));
1031                strict_break("", "").append(self.format_call_with_head(head, seg.args, seg.spread))
1032            })
1033            .collect();
1034
1035        root_doc
1036            .append(concat(segment_docs).nest_if_broken(INDENT_WIDTH))
1037            .group()
1038    }
1039
1040    fn dot_access(&mut self, expression: &'a Expression, member: &'a str) -> Document<'a> {
1041        self.expression(expression).append(".").append(member)
1042    }
1043
1044    fn indexed_access(
1045        &mut self,
1046        expression: &'a Expression,
1047        index: &'a Expression,
1048    ) -> Document<'a> {
1049        self.expression(expression)
1050            .append("[")
1051            .append(self.expression(index))
1052            .append("]")
1053    }
1054
1055    fn tuple(&mut self, elements: &'a [Expression]) -> Document<'a> {
1056        if elements.is_empty() {
1057            return Document::str("()");
1058        }
1059
1060        let elements_docs: Vec<_> = elements.iter().map(|e| self.expression(e)).collect();
1061        let elements_doc = join(elements_docs, strict_break(",", ", "));
1062
1063        Document::str("(")
1064            .append(strict_break("", ""))
1065            .append(elements_doc)
1066            .nest(INDENT_WIDTH)
1067            .append(strict_break(",", ""))
1068            .append(")")
1069            .group()
1070    }
1071
1072    fn struct_call(
1073        &mut self,
1074        name: &'a str,
1075        fields: &'a [StructFieldAssignment],
1076        spread: &'a Option<Expression>,
1077    ) -> Document<'a> {
1078        let mut field_docs: Vec<_> = fields
1079            .iter()
1080            .map(|f| {
1081                if let Expression::Identifier { value, .. } = &*f.value
1082                    && value == &f.name
1083                {
1084                    return Document::string(f.name.to_string());
1085                }
1086                Document::string(f.name.to_string())
1087                    .append(": ")
1088                    .append(self.expression(&f.value))
1089            })
1090            .collect();
1091
1092        if let Some(spread_expression) = spread {
1093            let start = spread_expression.get_span().byte_offset;
1094            let comments = self.comments.take_comments_before(start);
1095            let spread_doc = Document::str("..").append(self.expression(spread_expression));
1096            field_docs.push(prepend_comments(spread_doc, comments));
1097        }
1098
1099        if field_docs.is_empty() {
1100            return Document::str(name).append(" {}");
1101        }
1102
1103        let fields_doc = join(field_docs, strict_break(",", ", "));
1104
1105        Document::str(name)
1106            .append(" {")
1107            .append(strict_break(" ", " "))
1108            .append(fields_doc)
1109            .nest(INDENT_WIDTH)
1110            .append(strict_break(",", " "))
1111            .append("}")
1112            .group()
1113    }
1114
1115    fn assignment(
1116        &mut self,
1117        target: &'a Expression,
1118        value: &'a Expression,
1119        compound_operator: Option<BinaryOperator>,
1120    ) -> Document<'a> {
1121        if let Some(op) = compound_operator
1122            && let Some(op_str) = match op {
1123                BinaryOperator::Addition => Some("+="),
1124                BinaryOperator::Subtraction => Some("-="),
1125                BinaryOperator::Multiplication => Some("*="),
1126                BinaryOperator::Division => Some("/="),
1127                BinaryOperator::Remainder => Some("%="),
1128                _ => None,
1129            }
1130            && let Expression::Binary { right, .. } = value
1131        {
1132            return self
1133                .expression(target)
1134                .append(" ")
1135                .append(op_str)
1136                .append(" ")
1137                .append(self.expression(right));
1138        }
1139
1140        self.expression(target)
1141            .append(" = ")
1142            .append(self.expression(value))
1143    }
1144
1145    fn lambda(
1146        &mut self,
1147        params: &'a [Binding],
1148        return_annotation: &'a Annotation,
1149        body: &'a Expression,
1150        _span: &'a Span,
1151    ) -> Document<'a> {
1152        let params_docs: Vec<_> = params.iter().map(|p| self.binding(p)).collect();
1153
1154        let params_doc = if params_docs.is_empty() {
1155            Document::str("||")
1156        } else {
1157            Document::str("|")
1158                .append(join(params_docs, Document::str(", ")))
1159                .append("|")
1160        };
1161
1162        let return_doc = if return_annotation.is_unknown() {
1163            Document::Sequence(vec![])
1164        } else {
1165            Document::str(" -> ").append(Self::annotation(return_annotation))
1166        };
1167
1168        let body_doc = self.expression(body);
1169
1170        params_doc.append(return_doc).append(" ").append(body_doc)
1171    }
1172
1173    fn task(&mut self, expression: &'a Expression) -> Document<'a> {
1174        Document::str("task ").append(self.expression(expression))
1175    }
1176
1177    fn defer_(&mut self, expression: &'a Expression) -> Document<'a> {
1178        Document::str("defer ").append(self.expression(expression))
1179    }
1180
1181    fn try_block(&mut self, items: &'a [Expression], span: &Span) -> Document<'a> {
1182        Document::str("try ").append(self.block(items, span))
1183    }
1184
1185    fn recover_block(&mut self, items: &'a [Expression], span: &Span) -> Document<'a> {
1186        Document::str("recover ").append(self.block(items, span))
1187    }
1188
1189    fn range(
1190        &mut self,
1191        start: &'a Option<Box<Expression>>,
1192        end: &'a Option<Box<Expression>>,
1193        inclusive: bool,
1194    ) -> Document<'a> {
1195        let start_doc = match start {
1196            Some(e) => self.expression(e),
1197            None => Document::Sequence(vec![]),
1198        };
1199        let end_doc = match end {
1200            Some(e) => self.expression(e),
1201            None => Document::Sequence(vec![]),
1202        };
1203        let op = if inclusive { "..=" } else { ".." };
1204        start_doc.append(op).append(end_doc)
1205    }
1206
1207    fn cast(&mut self, expression: &'a Expression, target_type: &'a Annotation) -> Document<'a> {
1208        self.expression(expression)
1209            .append(" as ")
1210            .append(Self::annotation(target_type))
1211    }
1212
1213    fn select(&mut self, arms: &'a [SelectArm]) -> Document<'a> {
1214        let arms_docs: Vec<_> = arms.iter().map(|arm| self.select_arm(arm)).collect();
1215        Self::braced_body(Document::str("select"), join(arms_docs, Document::Newline))
1216    }
1217
1218    fn select_arm(&mut self, arm: &'a SelectArm) -> Document<'a> {
1219        match &arm.pattern {
1220            SelectArmPattern::Receive {
1221                binding,
1222                receive_expression,
1223                body,
1224                ..
1225            } => Document::str("let ")
1226                .append(self.pattern(binding))
1227                .append(" = ")
1228                .append(self.expression(receive_expression))
1229                .append(" => ")
1230                .append(self.expression(body))
1231                .append(","),
1232            SelectArmPattern::Send {
1233                send_expression,
1234                body,
1235            } => self
1236                .expression(send_expression)
1237                .append(" => ")
1238                .append(self.expression(body))
1239                .append(","),
1240            SelectArmPattern::MatchReceive {
1241                receive_expression,
1242                arms,
1243            } => {
1244                let arms_docs: Vec<_> = arms
1245                    .iter()
1246                    .map(|a| {
1247                        let pattern = self.pattern(&a.pattern);
1248                        let expression = self.expression(&a.expression);
1249                        let pattern_with_guard = if let Some(guard) = &a.guard {
1250                            pattern.append(" if ").append(self.expression(guard))
1251                        } else {
1252                            pattern
1253                        };
1254                        pattern_with_guard
1255                            .append(" => ")
1256                            .append(expression)
1257                            .append(",")
1258                    })
1259                    .collect();
1260                let header = Document::str("match ").append(self.expression(receive_expression));
1261                Self::braced_body(header, join(arms_docs, Document::Newline)).append(",")
1262            }
1263            SelectArmPattern::WildCard { body } => Document::str("_")
1264                .append(" => ")
1265                .append(self.expression(body))
1266                .append(","),
1267        }
1268    }
1269
1270    fn propagate_(&mut self, expression: &'a Expression) -> Document<'a> {
1271        self.expression(expression).append("?")
1272    }
1273
1274    fn ref_(&mut self, expression: &'a Expression) -> Document<'a> {
1275        Document::str("&").append(self.expression(expression))
1276    }
1277
1278    fn raw_go(text: &'a str) -> Document<'a> {
1279        Document::str("@rawgo(\"")
1280            .append(Document::str(text))
1281            .append("\")")
1282    }
1283
1284    fn struct_definition(
1285        &mut self,
1286        name: &'a str,
1287        generics: &'a [Generic],
1288        fields: &'a [StructFieldDefinition],
1289        span: &Span,
1290        kind: StructKind,
1291    ) -> Document<'a> {
1292        let generics_doc = Self::generics(generics);
1293        let header = Document::str("struct ").append(name).append(generics_doc);
1294        let struct_end = span.byte_offset + span.byte_length;
1295
1296        if kind == StructKind::Tuple {
1297            let type_docs: Vec<_> = fields
1298                .iter()
1299                .map(|f| Self::annotation(&f.annotation))
1300                .collect();
1301            return header
1302                .append("(")
1303                .append(join(type_docs, Document::str(", ")))
1304                .append(")");
1305        }
1306
1307        let with_field_attrs = fields.iter().any(|f| !f.attributes.is_empty());
1308        let with_pub_fields = fields.iter().any(|f| f.visibility.is_public());
1309
1310        if fields.is_empty() {
1311            return self.empty_struct_body(header, struct_end);
1312        }
1313
1314        let (field_entries, with_comments) = self.struct_fields_with_comments(fields, struct_end);
1315
1316        if with_comments || with_field_attrs || with_pub_fields {
1317            let fields_docs: Vec<_> = field_entries
1318                .into_iter()
1319                .map(|(field, comment)| match comment {
1320                    Some(c) => field.append(",").append(" ").append(c),
1321                    None => field.append(","),
1322                })
1323                .collect();
1324            return Self::braced_body(header, join(fields_docs, Document::Newline));
1325        }
1326
1327        let fields_docs: Vec<_> = field_entries.into_iter().map(|(field, _)| field).collect();
1328        Self::flexible_struct_body(header, fields_docs)
1329    }
1330
1331    fn empty_struct_body(&mut self, header: Document<'a>, end: u32) -> Document<'a> {
1332        match self.comments.take_comments_before(end) {
1333            Some(c) => header
1334                .append(" {")
1335                .append(Document::Newline.append(c).nest(INDENT_WIDTH))
1336                .append(Document::Newline)
1337                .append("}")
1338                .force_break(),
1339            None => header.append(" {}"),
1340        }
1341    }
1342
1343    fn struct_fields_with_comments(
1344        &mut self,
1345        fields: &'a [StructFieldDefinition],
1346        struct_end: u32,
1347    ) -> (Vec<(Document<'a>, Option<Document<'a>>)>, bool) {
1348        let mut entries = Vec::new();
1349        let mut with_comments = false;
1350
1351        for (i, field) in fields.iter().enumerate() {
1352            let comment_limit = if i + 1 < fields.len() {
1353                fields[i + 1].name_span.byte_offset
1354            } else {
1355                struct_end
1356            };
1357
1358            let field_attrs = Self::field_attributes(&field.attributes);
1359
1360            let field_definition = if field.visibility.is_public() {
1361                Document::str("pub ")
1362                    .append(Document::string(field.name.to_string()))
1363                    .append(": ")
1364                    .append(Self::annotation(&field.annotation))
1365            } else {
1366                Document::string(field.name.to_string())
1367                    .append(": ")
1368                    .append(Self::annotation(&field.annotation))
1369            };
1370
1371            let field_doc = field_attrs.append(field_definition);
1372
1373            let comment_doc = self.comments.take_comments_before(comment_limit);
1374            with_comments = with_comments || comment_doc.is_some();
1375
1376            entries.push((field_doc, comment_doc));
1377        }
1378
1379        (entries, with_comments)
1380    }
1381
1382    fn field_attributes(attrs: &'a [Attribute]) -> Document<'a> {
1383        if attrs.is_empty() {
1384            return Document::Sequence(vec![]);
1385        }
1386
1387        let attribute_docs: Vec<_> = attrs.iter().map(Self::attribute).collect();
1388        join(attribute_docs, Document::Newline).append(Document::Newline)
1389    }
1390
1391    fn braced_body(header: Document<'a>, body: Document<'a>) -> Document<'a> {
1392        header
1393            .append(" {")
1394            .append(Document::Newline.append(body).nest(INDENT_WIDTH))
1395            .append(Document::Newline)
1396            .append("}")
1397            .force_break()
1398    }
1399
1400    fn flexible_struct_body(header: Document<'a>, items: Vec<Document<'a>>) -> Document<'a> {
1401        let items_doc = join(items, strict_break(",", ", "));
1402        header
1403            .append(" {")
1404            .append(strict_break("", " "))
1405            .append(items_doc)
1406            .nest(INDENT_WIDTH)
1407            .append(strict_break(",", " "))
1408            .append("}")
1409            .group()
1410    }
1411
1412    fn enum_definition(
1413        &mut self,
1414        name: &'a str,
1415        generics: &'a [Generic],
1416        variants: &'a [EnumVariant],
1417    ) -> Document<'a> {
1418        let generics_doc = Self::generics(generics);
1419        let header = Document::str("enum ").append(name).append(generics_doc);
1420
1421        if variants.is_empty() {
1422            return header.append(" {}");
1423        }
1424
1425        let variants_docs: Vec<_> = variants.iter().map(|v| self.enum_variant(v)).collect();
1426        Self::braced_body(header, join(variants_docs, Document::Newline))
1427    }
1428
1429    fn value_enum_definition(
1430        &mut self,
1431        name: &'a str,
1432        underlying_ty: Option<&'a syntax::ast::Annotation>,
1433        variants: &'a [syntax::ast::ValueEnumVariant],
1434    ) -> Document<'a> {
1435        let header = if let Some(ty) = underlying_ty {
1436            Document::str("enum ")
1437                .append(name)
1438                .append(": ")
1439                .append(Self::annotation(ty))
1440        } else {
1441            Document::str("enum ").append(name)
1442        };
1443
1444        if variants.is_empty() {
1445            return header.append(" {}");
1446        }
1447
1448        let variants_docs: Vec<_> = variants
1449            .iter()
1450            .map(|v| self.value_enum_variant(v))
1451            .collect();
1452
1453        Self::braced_body(header, join(variants_docs, Document::Newline))
1454    }
1455
1456    fn enum_variant(&mut self, variant: &'a EnumVariant) -> Document<'a> {
1457        let name = Document::string(variant.name.to_string());
1458
1459        match &variant.fields {
1460            VariantFields::Unit => name.append(","),
1461            VariantFields::Tuple(fields) => {
1462                let field_docs: Vec<_> = fields
1463                    .iter()
1464                    .map(|f| Self::annotation(&f.annotation))
1465                    .collect();
1466                name.append("(")
1467                    .append(join(field_docs, Document::str(", ")))
1468                    .append("),")
1469            }
1470            VariantFields::Struct(fields) => {
1471                let field_docs: Vec<_> = fields
1472                    .iter()
1473                    .map(|f| {
1474                        Document::string(f.name.to_string())
1475                            .append(": ")
1476                            .append(Self::annotation(&f.annotation))
1477                    })
1478                    .collect();
1479                name.append(" { ")
1480                    .append(join(field_docs, Document::str(", ")))
1481                    .append(" },")
1482            }
1483        }
1484    }
1485
1486    fn value_enum_variant(&mut self, variant: &'a syntax::ast::ValueEnumVariant) -> Document<'a> {
1487        let name = Document::string(variant.name.to_string());
1488        let value_doc = self.literal(&variant.value);
1489        name.append(" = ").append(value_doc).append(",")
1490    }
1491
1492    fn type_alias(
1493        name: &'a str,
1494        generics: &'a [Generic],
1495        annotation: &'a Annotation,
1496    ) -> Document<'a> {
1497        let generics_doc = Self::generics(generics);
1498
1499        let base = Document::str("type ").append(name).append(generics_doc);
1500
1501        if annotation.is_opaque() {
1502            base
1503        } else {
1504            base.append(" = ").append(Self::annotation(annotation))
1505        }
1506    }
1507
1508    fn interface(
1509        &mut self,
1510        name: &'a str,
1511        generics: &'a [Generic],
1512        parents: &'a [ParentInterface],
1513        methods: &'a [Expression],
1514    ) -> Document<'a> {
1515        let generics_doc = Self::generics(generics);
1516
1517        let mut body_docs = Vec::new();
1518
1519        for parent in parents {
1520            body_docs.push(Document::str("impl ").append(Self::annotation(&parent.annotation)));
1521        }
1522
1523        for method in methods {
1524            body_docs.push(self.interface_method(method));
1525        }
1526
1527        let header = Document::str("interface ")
1528            .append(name)
1529            .append(generics_doc);
1530
1531        if body_docs.is_empty() {
1532            return header.append(" {}");
1533        }
1534
1535        Self::braced_body(header, join(body_docs, Document::Newline))
1536    }
1537
1538    fn interface_method(&mut self, method: &'a Expression) -> Document<'a> {
1539        match method {
1540            Expression::Function {
1541                name,
1542                generics,
1543                params,
1544                return_annotation,
1545                attributes,
1546                ..
1547            } => {
1548                let attrs_doc = Self::attributes(attributes);
1549                let generics_doc = Self::generics(generics);
1550
1551                let params_docs: Vec<_> = params.iter().map(|p| self.binding(p)).collect();
1552                let params_doc = Self::wrap_params(params_docs);
1553
1554                let return_doc = if return_annotation.is_unknown() {
1555                    Document::Sequence(vec![])
1556                } else {
1557                    Document::str(" -> ").append(Self::annotation(return_annotation))
1558                };
1559
1560                attrs_doc
1561                    .append(Document::str("fn "))
1562                    .append(Document::string(name.to_string()))
1563                    .append(generics_doc)
1564                    .append(params_doc)
1565                    .append(return_doc)
1566            }
1567            _ => Document::Sequence(vec![]),
1568        }
1569    }
1570
1571    fn impl_block(
1572        &mut self,
1573        annotation: &'a Annotation,
1574        generics: &'a [Generic],
1575        methods: &'a [Expression],
1576        impl_end: u32,
1577    ) -> Document<'a> {
1578        let generics_doc = Self::generics(generics);
1579        let header = Document::str("impl")
1580            .append(generics_doc)
1581            .append(" ")
1582            .append(Self::annotation(annotation));
1583
1584        if methods.is_empty() {
1585            return header.append(" {}");
1586        }
1587
1588        let mut docs = Vec::with_capacity(methods.len() * 5);
1589
1590        for (i, m) in methods.iter().enumerate() {
1591            let start = m.get_span().byte_offset;
1592
1593            if i > 0 {
1594                docs.push(Document::Newline);
1595                docs.push(Document::Newline);
1596            }
1597
1598            if let Some(comment_doc) = self.comments.take_comments_before(start) {
1599                docs.push(comment_doc.force_break());
1600                docs.push(Document::Newline);
1601            }
1602
1603            docs.push(self.definition(m));
1604        }
1605
1606        if let Some(trailing) = self.comments.take_comments_before(impl_end) {
1607            docs.push(Document::Newline);
1608            docs.push(Document::Newline);
1609            docs.push(trailing.force_break());
1610        }
1611
1612        Self::braced_body(header, concat(docs))
1613    }
1614
1615    fn const_definition(
1616        &mut self,
1617        name: &'a str,
1618        annotation: Option<&'a Annotation>,
1619        value: &'a Expression,
1620    ) -> Document<'a> {
1621        let type_doc = match annotation {
1622            Some(ann) => Document::str(": ").append(Self::annotation(ann)),
1623            None => Document::Sequence(vec![]),
1624        };
1625
1626        Document::str("const ")
1627            .append(name)
1628            .append(type_doc)
1629            .append(" = ")
1630            .append(self.expression(value))
1631    }
1632
1633    fn pattern(&mut self, pat: &'a Pattern) -> Document<'a> {
1634        match pat {
1635            Pattern::Literal { literal, .. } => self.literal(literal),
1636            Pattern::Unit { .. } => Document::str("()"),
1637            Pattern::WildCard { .. } => Document::str("_"),
1638            Pattern::Identifier { identifier, .. } => Document::string(identifier.to_string()),
1639
1640            Pattern::EnumVariant {
1641                identifier,
1642                fields,
1643                rest,
1644                ..
1645            } => {
1646                if fields.is_empty() && !rest {
1647                    Document::string(identifier.to_string())
1648                } else {
1649                    let mut field_docs: Vec<_> = fields
1650                        .iter()
1651                        .map(|f| {
1652                            let start = f.get_span().byte_offset;
1653                            let comments = self.comments.take_comments_before(start);
1654                            prepend_comments(self.pattern(f), comments)
1655                        })
1656                        .collect();
1657                    if *rest {
1658                        field_docs.push(Document::str(".."));
1659                    }
1660                    Document::string(identifier.to_string())
1661                        .append("(")
1662                        .append(strict_break("", ""))
1663                        .append(join(field_docs, strict_break(",", ", ")))
1664                        .nest(INDENT_WIDTH)
1665                        .append(strict_break(",", ""))
1666                        .append(")")
1667                        .group()
1668                }
1669            }
1670
1671            Pattern::Struct {
1672                identifier,
1673                fields,
1674                rest,
1675                ..
1676            } => {
1677                if fields.is_empty() && !rest {
1678                    Document::string(identifier.to_string()).append(" {}")
1679                } else {
1680                    let mut field_docs: Vec<_> = fields
1681                        .iter()
1682                        .map(|f| {
1683                            let start = f.value.get_span().byte_offset;
1684                            let comments = self.comments.take_comments_before(start);
1685                            prepend_comments(self.struct_field_pattern(f), comments)
1686                        })
1687                        .collect();
1688                    if *rest {
1689                        field_docs.push(Document::str(".."));
1690                    }
1691                    Document::string(identifier.to_string())
1692                        .append(" {")
1693                        .append(strict_break(" ", " "))
1694                        .append(join(field_docs, strict_break(",", ", ")))
1695                        .nest(INDENT_WIDTH)
1696                        .append(strict_break(",", " "))
1697                        .append("}")
1698                        .group()
1699                }
1700            }
1701
1702            Pattern::Tuple { elements, .. } => {
1703                let elements_docs: Vec<_> = elements
1704                    .iter()
1705                    .map(|e| {
1706                        let start = e.get_span().byte_offset;
1707                        let comments = self.comments.take_comments_before(start);
1708                        prepend_comments(self.pattern(e), comments)
1709                    })
1710                    .collect();
1711                Document::str("(")
1712                    .append(strict_break("", ""))
1713                    .append(join(elements_docs, strict_break(",", ", ")))
1714                    .nest(INDENT_WIDTH)
1715                    .append(strict_break(",", ""))
1716                    .append(")")
1717                    .group()
1718            }
1719
1720            Pattern::Slice { prefix, rest, .. } => {
1721                let mut all_docs: Vec<Document<'a>> = Vec::new();
1722
1723                for pattern in prefix {
1724                    let start = pattern.get_span().byte_offset;
1725                    let comments = self.comments.take_comments_before(start);
1726                    all_docs.push(prepend_comments(self.pattern(pattern), comments));
1727                }
1728
1729                match rest {
1730                    RestPattern::Absent => {}
1731                    RestPattern::Discard(_) => {
1732                        all_docs.push(Document::str(".."));
1733                    }
1734                    RestPattern::Bind { name, .. } => {
1735                        all_docs
1736                            .push(Document::str("..").append(Document::string(name.to_string())));
1737                    }
1738                }
1739
1740                Document::str("[")
1741                    .append(strict_break("", ""))
1742                    .append(join(all_docs, strict_break(",", ", ")))
1743                    .nest(INDENT_WIDTH)
1744                    .append(strict_break(",", ""))
1745                    .append("]")
1746                    .group()
1747            }
1748
1749            Pattern::Or { patterns, .. } => {
1750                let pattern_docs: Vec<_> = patterns.iter().map(|p| self.pattern(p)).collect();
1751                join(pattern_docs, Document::str(" | "))
1752            }
1753
1754            Pattern::AsBinding { pattern, name, .. } => self
1755                .pattern(pattern)
1756                .append(" as ")
1757                .append(Document::string(name.to_string())),
1758        }
1759    }
1760
1761    fn struct_field_pattern(&mut self, field: &'a StructFieldPattern) -> Document<'a> {
1762        if let Pattern::Identifier { identifier, .. } = &field.value
1763            && identifier == &field.name
1764        {
1765            return Document::string(field.name.to_string());
1766        }
1767
1768        Document::string(field.name.to_string())
1769            .append(": ")
1770            .append(self.pattern(&field.value))
1771    }
1772
1773    fn binding(&mut self, binding: &'a Binding) -> Document<'a> {
1774        let pattern_doc = if binding.mutable {
1775            Document::str("mut ").append(self.pattern(&binding.pattern))
1776        } else {
1777            self.pattern(&binding.pattern)
1778        };
1779
1780        match &binding.annotation {
1781            Some(annotation) => pattern_doc
1782                .append(": ")
1783                .append(Self::annotation(annotation)),
1784            None => pattern_doc,
1785        }
1786    }
1787
1788    fn annotation(annotation: &'a Annotation) -> Document<'a> {
1789        match annotation {
1790            Annotation::Constructor { name, params, .. } => {
1791                if params.is_empty() {
1792                    if name == "Unit" {
1793                        Document::str("()")
1794                    } else {
1795                        Document::string(name.to_string())
1796                    }
1797                } else {
1798                    let param_docs: Vec<_> = params.iter().map(Self::annotation).collect();
1799                    Document::string(name.to_string())
1800                        .append("<")
1801                        .append(join(param_docs, Document::str(", ")))
1802                        .append(">")
1803                }
1804            }
1805            Annotation::Function {
1806                params,
1807                return_type,
1808                ..
1809            } => {
1810                let param_docs: Vec<_> = params.iter().map(Self::annotation).collect();
1811                Document::str("fn(")
1812                    .append(join(param_docs, Document::str(", ")))
1813                    .append(") -> ")
1814                    .append(Self::annotation(return_type))
1815            }
1816            Annotation::Unknown => Document::str("_"),
1817            Annotation::Tuple { elements, .. } => {
1818                let elem_docs: Vec<_> = elements.iter().map(Self::annotation).collect();
1819                Document::str("(")
1820                    .append(join(elem_docs, Document::str(", ")))
1821                    .append(")")
1822            }
1823            Annotation::Opaque { .. } => Document::Sequence(vec![]),
1824        }
1825    }
1826
1827    fn generics(generics: &'a [Generic]) -> Document<'a> {
1828        if generics.is_empty() {
1829            return Document::Sequence(vec![]);
1830        }
1831
1832        let generics_docs: Vec<_> = generics
1833            .iter()
1834            .map(|g| {
1835                if g.bounds.is_empty() {
1836                    Document::string(g.name.to_string())
1837                } else {
1838                    let bounds: Vec<_> = g.bounds.iter().map(Self::annotation).collect();
1839                    Document::string(g.name.to_string())
1840                        .append(": ")
1841                        .append(join(bounds, Document::str(" + ")))
1842                }
1843            })
1844            .collect();
1845
1846        Document::str("<")
1847            .append(join(generics_docs, Document::str(", ")))
1848            .append(">")
1849    }
1850
1851    fn attribute(attribute: &'a Attribute) -> Document<'a> {
1852        let name = Document::string(attribute.name.clone());
1853
1854        if attribute.args.is_empty() {
1855            Document::str("#[").append(name).append("]")
1856        } else {
1857            let args_docs: Vec<_> = attribute.args.iter().map(Self::attribute_arg).collect();
1858            Document::str("#[")
1859                .append(name)
1860                .append("(")
1861                .append(join(args_docs, Document::str(", ")))
1862                .append(")]")
1863        }
1864    }
1865
1866    fn attribute_arg(arg: &'a AttributeArg) -> Document<'a> {
1867        match arg {
1868            AttributeArg::Flag(name) => Document::string(name.clone()),
1869            AttributeArg::NegatedFlag(name) => {
1870                Document::str("!").append(Document::string(name.clone()))
1871            }
1872            AttributeArg::String(s) => Document::string(format!("\"{}\"", s)),
1873            AttributeArg::Raw(s) => Document::string(format!("`{}`", s)),
1874        }
1875    }
1876
1877    fn attributes(attrs: &'a [Attribute]) -> Document<'a> {
1878        if attrs.is_empty() {
1879            return Document::Sequence(vec![]);
1880        }
1881
1882        let attribute_docs: Vec<_> = attrs.iter().map(Self::attribute).collect();
1883        join(attribute_docs, Document::Newline).append(Document::Newline)
1884    }
1885}
1886
1887struct MethodChainSegment<'a> {
1888    member: &'a str,
1889    args: &'a [Expression],
1890    spread: &'a Option<Expression>,
1891    type_args: &'a [Annotation],
1892}
1893
1894fn collect_method_chain(expression: &Expression) -> (&Expression, Vec<MethodChainSegment<'_>>) {
1895    let mut segments = Vec::new();
1896    let mut current = expression;
1897
1898    while let Expression::Call {
1899        expression,
1900        args,
1901        spread,
1902        type_args,
1903        ..
1904    } = current
1905    {
1906        let Expression::DotAccess {
1907            expression: inner,
1908            member,
1909            ..
1910        } = expression.as_ref()
1911        else {
1912            break;
1913        };
1914        segments.push(MethodChainSegment {
1915            member,
1916            args,
1917            spread,
1918            type_args,
1919        });
1920        current = inner;
1921    }
1922
1923    segments.reverse();
1924    (current, segments)
1925}
1926
1927fn is_inlinable_arg(expression: &Expression, arity: usize) -> bool {
1928    matches!(
1929        expression,
1930        Expression::Lambda { .. }
1931            | Expression::Block { .. }
1932            | Expression::Match { .. }
1933            | Expression::Tuple { .. }
1934            | Expression::Literal {
1935                literal: Literal::Slice(_),
1936                ..
1937            }
1938    ) || matches!(expression, Expression::Call { .. } if arity == 1)
1939}