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        let docs: Vec<_> = segments
862            .iter()
863            .enumerate()
864            .map(|(i, seg)| {
865                if i == 0 {
866                    self.expression(seg)
867                } else {
868                    flex_break("", " ")
869                        .append("|> ")
870                        .append(self.expression(seg))
871                }
872            })
873            .collect();
874
875        concat(docs).nest_if_broken(INDENT_WIDTH).group()
876    }
877
878    fn unary_operator(
879        &mut self,
880        operator: &UnaryOperator,
881        expression: &'a Expression,
882    ) -> Document<'a> {
883        match operator {
884            UnaryOperator::Negative => Document::str("-").append(self.expression(expression)),
885            UnaryOperator::Not => Document::str("!").append(self.expression(expression)),
886            UnaryOperator::Deref => self.expression(expression).append(".*"),
887        }
888    }
889
890    fn call(
891        &mut self,
892        callee: &'a Expression,
893        args: &'a [Expression],
894        spread: &'a Option<Expression>,
895        type_args: &'a [Annotation],
896    ) -> Document<'a> {
897        if let Expression::DotAccess {
898            expression: inner,
899            member,
900            ..
901        } = callee
902        {
903            let (root, mut chain_segments) = collect_method_chain(inner);
904            chain_segments.push(MethodChainSegment {
905                member,
906                args,
907                spread,
908                type_args,
909            });
910            if chain_segments.len() >= 2 {
911                return self.format_method_chain(root, &chain_segments);
912            }
913        }
914
915        let head = self
916            .expression(callee)
917            .append(Self::format_type_args(type_args));
918        self.format_call_with_head(head, args, spread)
919    }
920
921    fn format_type_args(type_args: &'a [Annotation]) -> Document<'a> {
922        if type_args.is_empty() {
923            Document::Sequence(vec![])
924        } else {
925            let types: Vec<_> = type_args.iter().map(Self::annotation).collect();
926            Document::str("<")
927                .append(join(types, Document::str(", ")))
928                .append(">")
929        }
930    }
931
932    fn format_call_with_head(
933        &mut self,
934        head: Document<'a>,
935        args: &'a [Expression],
936        spread: &'a Option<Expression>,
937    ) -> Document<'a> {
938        if args.is_empty() && spread.is_none() {
939            return head.append("()");
940        }
941
942        if let Some(spread_expr) = spread {
943            let spread_doc = Document::str("..").append(self.expression(spread_expr));
944            if args.is_empty() {
945                return head
946                    .append("(")
947                    .append(spread_doc.group().next_break_fits(true))
948                    .append(")")
949                    .next_break_fits(false)
950                    .group();
951            }
952            let init_docs: Vec<_> = args.iter().map(|a| self.expression(a)).collect();
953            let init_doc = join(init_docs, strict_break(",", ", "));
954            return head
955                .append("(")
956                .append(strict_break("", ""))
957                .append(init_doc)
958                .append(strict_break(",", ", "))
959                .append(spread_doc.group().next_break_fits(true))
960                .nest(INDENT_WIDTH)
961                .append(strict_break(",", ""))
962                .append(")")
963                .next_break_fits(false)
964                .group();
965        }
966
967        let Some((last, init)) = args
968            .split_last()
969            .filter(|(last, _)| is_inlinable_arg(last, args.len()))
970        else {
971            let arg_docs: Vec<_> = args.iter().map(|a| self.expression(a)).collect();
972            let args_doc = join(arg_docs, strict_break(",", ", "));
973
974            return head
975                .append("(")
976                .append(strict_break("", ""))
977                .append(args_doc)
978                .nest(INDENT_WIDTH)
979                .append(strict_break(",", ""))
980                .append(")")
981                .group();
982        };
983
984        let last_doc = self.expression(last).group().next_break_fits(true);
985
986        if init.is_empty() {
987            head.append("(")
988                .append(last_doc)
989                .append(")")
990                .next_break_fits(false)
991                .group()
992        } else {
993            let init_docs: Vec<_> = init.iter().map(|a| self.expression(a)).collect();
994            let init_doc = join(init_docs, strict_break(",", ", "));
995
996            head.append("(")
997                .append(strict_break("", ""))
998                .append(init_doc)
999                .append(strict_break(",", ", "))
1000                .append(last_doc)
1001                .nest(INDENT_WIDTH)
1002                .append(strict_break(",", ""))
1003                .append(")")
1004                .next_break_fits(false)
1005                .group()
1006        }
1007    }
1008
1009    fn format_method_chain(
1010        &mut self,
1011        root: &'a Expression,
1012        segments: &[MethodChainSegment<'a>],
1013    ) -> Document<'a> {
1014        let root_doc = self.expression(root);
1015
1016        let segment_docs: Vec<Document<'a>> = segments
1017            .iter()
1018            .map(|seg| {
1019                let head = Document::str(".")
1020                    .append(seg.member)
1021                    .append(Self::format_type_args(seg.type_args));
1022                strict_break("", "").append(self.format_call_with_head(head, seg.args, seg.spread))
1023            })
1024            .collect();
1025
1026        root_doc
1027            .append(concat(segment_docs).nest_if_broken(INDENT_WIDTH))
1028            .group()
1029    }
1030
1031    fn dot_access(&mut self, expression: &'a Expression, member: &'a str) -> Document<'a> {
1032        self.expression(expression).append(".").append(member)
1033    }
1034
1035    fn indexed_access(
1036        &mut self,
1037        expression: &'a Expression,
1038        index: &'a Expression,
1039    ) -> Document<'a> {
1040        self.expression(expression)
1041            .append("[")
1042            .append(self.expression(index))
1043            .append("]")
1044    }
1045
1046    fn tuple(&mut self, elements: &'a [Expression]) -> Document<'a> {
1047        if elements.is_empty() {
1048            return Document::str("()");
1049        }
1050
1051        let elements_docs: Vec<_> = elements.iter().map(|e| self.expression(e)).collect();
1052        let elements_doc = join(elements_docs, strict_break(",", ", "));
1053
1054        Document::str("(")
1055            .append(strict_break("", ""))
1056            .append(elements_doc)
1057            .nest(INDENT_WIDTH)
1058            .append(strict_break(",", ""))
1059            .append(")")
1060            .group()
1061    }
1062
1063    fn struct_call(
1064        &mut self,
1065        name: &'a str,
1066        fields: &'a [StructFieldAssignment],
1067        spread: &'a Option<Expression>,
1068    ) -> Document<'a> {
1069        let mut field_docs: Vec<_> = fields
1070            .iter()
1071            .map(|f| {
1072                if let Expression::Identifier { value, .. } = &*f.value
1073                    && value == &f.name
1074                {
1075                    return Document::string(f.name.to_string());
1076                }
1077                Document::string(f.name.to_string())
1078                    .append(": ")
1079                    .append(self.expression(&f.value))
1080            })
1081            .collect();
1082
1083        if let Some(spread_expression) = spread {
1084            let start = spread_expression.get_span().byte_offset;
1085            let comments = self.comments.take_comments_before(start);
1086            let spread_doc = Document::str("..").append(self.expression(spread_expression));
1087            field_docs.push(prepend_comments(spread_doc, comments));
1088        }
1089
1090        if field_docs.is_empty() {
1091            return Document::str(name).append(" {}");
1092        }
1093
1094        let fields_doc = join(field_docs, strict_break(",", ", "));
1095
1096        Document::str(name)
1097            .append(" {")
1098            .append(strict_break(" ", " "))
1099            .append(fields_doc)
1100            .nest(INDENT_WIDTH)
1101            .append(strict_break(",", " "))
1102            .append("}")
1103            .group()
1104    }
1105
1106    fn assignment(
1107        &mut self,
1108        target: &'a Expression,
1109        value: &'a Expression,
1110        compound_operator: Option<BinaryOperator>,
1111    ) -> Document<'a> {
1112        if let Some(op) = compound_operator
1113            && let Some(op_str) = match op {
1114                BinaryOperator::Addition => Some("+="),
1115                BinaryOperator::Subtraction => Some("-="),
1116                BinaryOperator::Multiplication => Some("*="),
1117                BinaryOperator::Division => Some("/="),
1118                BinaryOperator::Remainder => Some("%="),
1119                _ => None,
1120            }
1121            && let Expression::Binary { right, .. } = value
1122        {
1123            return self
1124                .expression(target)
1125                .append(" ")
1126                .append(op_str)
1127                .append(" ")
1128                .append(self.expression(right));
1129        }
1130
1131        self.expression(target)
1132            .append(" = ")
1133            .append(self.expression(value))
1134    }
1135
1136    fn lambda(
1137        &mut self,
1138        params: &'a [Binding],
1139        return_annotation: &'a Annotation,
1140        body: &'a Expression,
1141        _span: &'a Span,
1142    ) -> Document<'a> {
1143        let params_docs: Vec<_> = params.iter().map(|p| self.binding(p)).collect();
1144
1145        let params_doc = if params_docs.is_empty() {
1146            Document::str("||")
1147        } else {
1148            Document::str("|")
1149                .append(join(params_docs, Document::str(", ")))
1150                .append("|")
1151        };
1152
1153        let return_doc = if return_annotation.is_unknown() {
1154            Document::Sequence(vec![])
1155        } else {
1156            Document::str(" -> ").append(Self::annotation(return_annotation))
1157        };
1158
1159        let body_doc = self.expression(body);
1160
1161        params_doc.append(return_doc).append(" ").append(body_doc)
1162    }
1163
1164    fn task(&mut self, expression: &'a Expression) -> Document<'a> {
1165        Document::str("task ").append(self.expression(expression))
1166    }
1167
1168    fn defer_(&mut self, expression: &'a Expression) -> Document<'a> {
1169        Document::str("defer ").append(self.expression(expression))
1170    }
1171
1172    fn try_block(&mut self, items: &'a [Expression], span: &Span) -> Document<'a> {
1173        Document::str("try ").append(self.block(items, span))
1174    }
1175
1176    fn recover_block(&mut self, items: &'a [Expression], span: &Span) -> Document<'a> {
1177        Document::str("recover ").append(self.block(items, span))
1178    }
1179
1180    fn range(
1181        &mut self,
1182        start: &'a Option<Box<Expression>>,
1183        end: &'a Option<Box<Expression>>,
1184        inclusive: bool,
1185    ) -> Document<'a> {
1186        let start_doc = match start {
1187            Some(e) => self.expression(e),
1188            None => Document::Sequence(vec![]),
1189        };
1190        let end_doc = match end {
1191            Some(e) => self.expression(e),
1192            None => Document::Sequence(vec![]),
1193        };
1194        let op = if inclusive { "..=" } else { ".." };
1195        start_doc.append(op).append(end_doc)
1196    }
1197
1198    fn cast(&mut self, expression: &'a Expression, target_type: &'a Annotation) -> Document<'a> {
1199        self.expression(expression)
1200            .append(" as ")
1201            .append(Self::annotation(target_type))
1202    }
1203
1204    fn select(&mut self, arms: &'a [SelectArm]) -> Document<'a> {
1205        let arms_docs: Vec<_> = arms.iter().map(|arm| self.select_arm(arm)).collect();
1206        Self::braced_body(Document::str("select"), join(arms_docs, Document::Newline))
1207    }
1208
1209    fn select_arm(&mut self, arm: &'a SelectArm) -> Document<'a> {
1210        match &arm.pattern {
1211            SelectArmPattern::Receive {
1212                binding,
1213                receive_expression,
1214                body,
1215                ..
1216            } => Document::str("let ")
1217                .append(self.pattern(binding))
1218                .append(" = ")
1219                .append(self.expression(receive_expression))
1220                .append(" => ")
1221                .append(self.expression(body))
1222                .append(","),
1223            SelectArmPattern::Send {
1224                send_expression,
1225                body,
1226            } => self
1227                .expression(send_expression)
1228                .append(" => ")
1229                .append(self.expression(body))
1230                .append(","),
1231            SelectArmPattern::MatchReceive {
1232                receive_expression,
1233                arms,
1234            } => {
1235                let arms_docs: Vec<_> = arms
1236                    .iter()
1237                    .map(|a| {
1238                        let pattern = self.pattern(&a.pattern);
1239                        let expression = self.expression(&a.expression);
1240                        let pattern_with_guard = if let Some(guard) = &a.guard {
1241                            pattern.append(" if ").append(self.expression(guard))
1242                        } else {
1243                            pattern
1244                        };
1245                        pattern_with_guard
1246                            .append(" => ")
1247                            .append(expression)
1248                            .append(",")
1249                    })
1250                    .collect();
1251                let header = Document::str("match ").append(self.expression(receive_expression));
1252                Self::braced_body(header, join(arms_docs, Document::Newline)).append(",")
1253            }
1254            SelectArmPattern::WildCard { body } => Document::str("_")
1255                .append(" => ")
1256                .append(self.expression(body))
1257                .append(","),
1258        }
1259    }
1260
1261    fn propagate_(&mut self, expression: &'a Expression) -> Document<'a> {
1262        self.expression(expression).append("?")
1263    }
1264
1265    fn ref_(&mut self, expression: &'a Expression) -> Document<'a> {
1266        Document::str("&").append(self.expression(expression))
1267    }
1268
1269    fn raw_go(text: &'a str) -> Document<'a> {
1270        Document::str("@rawgo(\"")
1271            .append(Document::str(text))
1272            .append("\")")
1273    }
1274
1275    fn struct_definition(
1276        &mut self,
1277        name: &'a str,
1278        generics: &'a [Generic],
1279        fields: &'a [StructFieldDefinition],
1280        span: &Span,
1281        kind: StructKind,
1282    ) -> Document<'a> {
1283        let generics_doc = Self::generics(generics);
1284        let header = Document::str("struct ").append(name).append(generics_doc);
1285        let struct_end = span.byte_offset + span.byte_length;
1286
1287        if kind == StructKind::Tuple {
1288            let type_docs: Vec<_> = fields
1289                .iter()
1290                .map(|f| Self::annotation(&f.annotation))
1291                .collect();
1292            return header
1293                .append("(")
1294                .append(join(type_docs, Document::str(", ")))
1295                .append(")");
1296        }
1297
1298        let with_field_attrs = fields.iter().any(|f| !f.attributes.is_empty());
1299        let with_pub_fields = fields.iter().any(|f| f.visibility.is_public());
1300
1301        if fields.is_empty() {
1302            return self.empty_struct_body(header, struct_end);
1303        }
1304
1305        let (field_entries, with_comments) = self.struct_fields_with_comments(fields, struct_end);
1306
1307        if with_comments || with_field_attrs || with_pub_fields {
1308            let fields_docs: Vec<_> = field_entries
1309                .into_iter()
1310                .map(|(field, comment)| match comment {
1311                    Some(c) => field.append(",").append(" ").append(c),
1312                    None => field.append(","),
1313                })
1314                .collect();
1315            return Self::braced_body(header, join(fields_docs, Document::Newline));
1316        }
1317
1318        let fields_docs: Vec<_> = field_entries.into_iter().map(|(field, _)| field).collect();
1319        Self::flexible_struct_body(header, fields_docs)
1320    }
1321
1322    fn empty_struct_body(&mut self, header: Document<'a>, end: u32) -> Document<'a> {
1323        match self.comments.take_comments_before(end) {
1324            Some(c) => header
1325                .append(" {")
1326                .append(Document::Newline.append(c).nest(INDENT_WIDTH))
1327                .append(Document::Newline)
1328                .append("}")
1329                .force_break(),
1330            None => header.append(" {}"),
1331        }
1332    }
1333
1334    fn struct_fields_with_comments(
1335        &mut self,
1336        fields: &'a [StructFieldDefinition],
1337        struct_end: u32,
1338    ) -> (Vec<(Document<'a>, Option<Document<'a>>)>, bool) {
1339        let mut entries = Vec::new();
1340        let mut with_comments = false;
1341
1342        for (i, field) in fields.iter().enumerate() {
1343            let comment_limit = if i + 1 < fields.len() {
1344                fields[i + 1].name_span.byte_offset
1345            } else {
1346                struct_end
1347            };
1348
1349            let field_attrs = Self::field_attributes(&field.attributes);
1350
1351            let field_definition = if field.visibility.is_public() {
1352                Document::str("pub ")
1353                    .append(Document::string(field.name.to_string()))
1354                    .append(": ")
1355                    .append(Self::annotation(&field.annotation))
1356            } else {
1357                Document::string(field.name.to_string())
1358                    .append(": ")
1359                    .append(Self::annotation(&field.annotation))
1360            };
1361
1362            let field_doc = field_attrs.append(field_definition);
1363
1364            let comment_doc = self.comments.take_comments_before(comment_limit);
1365            with_comments = with_comments || comment_doc.is_some();
1366
1367            entries.push((field_doc, comment_doc));
1368        }
1369
1370        (entries, with_comments)
1371    }
1372
1373    fn field_attributes(attrs: &'a [Attribute]) -> Document<'a> {
1374        if attrs.is_empty() {
1375            return Document::Sequence(vec![]);
1376        }
1377
1378        let attribute_docs: Vec<_> = attrs.iter().map(Self::attribute).collect();
1379        join(attribute_docs, Document::Newline).append(Document::Newline)
1380    }
1381
1382    fn braced_body(header: Document<'a>, body: Document<'a>) -> Document<'a> {
1383        header
1384            .append(" {")
1385            .append(Document::Newline.append(body).nest(INDENT_WIDTH))
1386            .append(Document::Newline)
1387            .append("}")
1388            .force_break()
1389    }
1390
1391    fn flexible_struct_body(header: Document<'a>, items: Vec<Document<'a>>) -> Document<'a> {
1392        let items_doc = join(items, strict_break(",", ", "));
1393        header
1394            .append(" {")
1395            .append(strict_break("", " "))
1396            .append(items_doc)
1397            .nest(INDENT_WIDTH)
1398            .append(strict_break(",", " "))
1399            .append("}")
1400            .group()
1401    }
1402
1403    fn enum_definition(
1404        &mut self,
1405        name: &'a str,
1406        generics: &'a [Generic],
1407        variants: &'a [EnumVariant],
1408    ) -> Document<'a> {
1409        let generics_doc = Self::generics(generics);
1410        let header = Document::str("enum ").append(name).append(generics_doc);
1411
1412        if variants.is_empty() {
1413            return header.append(" {}");
1414        }
1415
1416        let variants_docs: Vec<_> = variants.iter().map(|v| self.enum_variant(v)).collect();
1417        Self::braced_body(header, join(variants_docs, Document::Newline))
1418    }
1419
1420    fn value_enum_definition(
1421        &mut self,
1422        name: &'a str,
1423        underlying_ty: Option<&'a syntax::ast::Annotation>,
1424        variants: &'a [syntax::ast::ValueEnumVariant],
1425    ) -> Document<'a> {
1426        let header = if let Some(ty) = underlying_ty {
1427            Document::str("enum ")
1428                .append(name)
1429                .append(": ")
1430                .append(Self::annotation(ty))
1431        } else {
1432            Document::str("enum ").append(name)
1433        };
1434
1435        if variants.is_empty() {
1436            return header.append(" {}");
1437        }
1438
1439        let variants_docs: Vec<_> = variants
1440            .iter()
1441            .map(|v| self.value_enum_variant(v))
1442            .collect();
1443
1444        Self::braced_body(header, join(variants_docs, Document::Newline))
1445    }
1446
1447    fn enum_variant(&mut self, variant: &'a EnumVariant) -> Document<'a> {
1448        let name = Document::string(variant.name.to_string());
1449
1450        match &variant.fields {
1451            VariantFields::Unit => name.append(","),
1452            VariantFields::Tuple(fields) => {
1453                let field_docs: Vec<_> = fields
1454                    .iter()
1455                    .map(|f| Self::annotation(&f.annotation))
1456                    .collect();
1457                name.append("(")
1458                    .append(join(field_docs, Document::str(", ")))
1459                    .append("),")
1460            }
1461            VariantFields::Struct(fields) => {
1462                let field_docs: Vec<_> = fields
1463                    .iter()
1464                    .map(|f| {
1465                        Document::string(f.name.to_string())
1466                            .append(": ")
1467                            .append(Self::annotation(&f.annotation))
1468                    })
1469                    .collect();
1470                name.append(" { ")
1471                    .append(join(field_docs, Document::str(", ")))
1472                    .append(" },")
1473            }
1474        }
1475    }
1476
1477    fn value_enum_variant(&mut self, variant: &'a syntax::ast::ValueEnumVariant) -> Document<'a> {
1478        let name = Document::string(variant.name.to_string());
1479        let value_doc = self.literal(&variant.value);
1480        name.append(" = ").append(value_doc).append(",")
1481    }
1482
1483    fn type_alias(
1484        name: &'a str,
1485        generics: &'a [Generic],
1486        annotation: &'a Annotation,
1487    ) -> Document<'a> {
1488        let generics_doc = Self::generics(generics);
1489
1490        let base = Document::str("type ").append(name).append(generics_doc);
1491
1492        if annotation.is_opaque() {
1493            base
1494        } else {
1495            base.append(" = ").append(Self::annotation(annotation))
1496        }
1497    }
1498
1499    fn interface(
1500        &mut self,
1501        name: &'a str,
1502        generics: &'a [Generic],
1503        parents: &'a [ParentInterface],
1504        methods: &'a [Expression],
1505    ) -> Document<'a> {
1506        let generics_doc = Self::generics(generics);
1507
1508        let mut body_docs = Vec::new();
1509
1510        for parent in parents {
1511            body_docs.push(Document::str("impl ").append(Self::annotation(&parent.annotation)));
1512        }
1513
1514        for method in methods {
1515            body_docs.push(self.interface_method(method));
1516        }
1517
1518        let header = Document::str("interface ")
1519            .append(name)
1520            .append(generics_doc);
1521
1522        if body_docs.is_empty() {
1523            return header.append(" {}");
1524        }
1525
1526        Self::braced_body(header, join(body_docs, Document::Newline))
1527    }
1528
1529    fn interface_method(&mut self, method: &'a Expression) -> Document<'a> {
1530        match method {
1531            Expression::Function {
1532                name,
1533                generics,
1534                params,
1535                return_annotation,
1536                attributes,
1537                ..
1538            } => {
1539                let attrs_doc = Self::attributes(attributes);
1540                let generics_doc = Self::generics(generics);
1541
1542                let params_docs: Vec<_> = params.iter().map(|p| self.binding(p)).collect();
1543                let params_doc = Self::wrap_params(params_docs);
1544
1545                let return_doc = if return_annotation.is_unknown() {
1546                    Document::Sequence(vec![])
1547                } else {
1548                    Document::str(" -> ").append(Self::annotation(return_annotation))
1549                };
1550
1551                attrs_doc
1552                    .append(Document::str("fn "))
1553                    .append(Document::string(name.to_string()))
1554                    .append(generics_doc)
1555                    .append(params_doc)
1556                    .append(return_doc)
1557            }
1558            _ => Document::Sequence(vec![]),
1559        }
1560    }
1561
1562    fn impl_block(
1563        &mut self,
1564        annotation: &'a Annotation,
1565        generics: &'a [Generic],
1566        methods: &'a [Expression],
1567        impl_end: u32,
1568    ) -> Document<'a> {
1569        let generics_doc = Self::generics(generics);
1570        let header = Document::str("impl")
1571            .append(generics_doc)
1572            .append(" ")
1573            .append(Self::annotation(annotation));
1574
1575        if methods.is_empty() {
1576            return header.append(" {}");
1577        }
1578
1579        let mut docs = Vec::with_capacity(methods.len() * 5);
1580
1581        for (i, m) in methods.iter().enumerate() {
1582            let start = m.get_span().byte_offset;
1583
1584            if i > 0 {
1585                docs.push(Document::Newline);
1586                docs.push(Document::Newline);
1587            }
1588
1589            if let Some(comment_doc) = self.comments.take_comments_before(start) {
1590                docs.push(comment_doc.force_break());
1591                docs.push(Document::Newline);
1592            }
1593
1594            docs.push(self.definition(m));
1595        }
1596
1597        if let Some(trailing) = self.comments.take_comments_before(impl_end) {
1598            docs.push(Document::Newline);
1599            docs.push(Document::Newline);
1600            docs.push(trailing.force_break());
1601        }
1602
1603        Self::braced_body(header, concat(docs))
1604    }
1605
1606    fn const_definition(
1607        &mut self,
1608        name: &'a str,
1609        annotation: Option<&'a Annotation>,
1610        value: &'a Expression,
1611    ) -> Document<'a> {
1612        let type_doc = match annotation {
1613            Some(ann) => Document::str(": ").append(Self::annotation(ann)),
1614            None => Document::Sequence(vec![]),
1615        };
1616
1617        Document::str("const ")
1618            .append(name)
1619            .append(type_doc)
1620            .append(" = ")
1621            .append(self.expression(value))
1622    }
1623
1624    fn pattern(&mut self, pat: &'a Pattern) -> Document<'a> {
1625        match pat {
1626            Pattern::Literal { literal, .. } => self.literal(literal),
1627            Pattern::Unit { .. } => Document::str("()"),
1628            Pattern::WildCard { .. } => Document::str("_"),
1629            Pattern::Identifier { identifier, .. } => Document::string(identifier.to_string()),
1630
1631            Pattern::EnumVariant {
1632                identifier,
1633                fields,
1634                rest,
1635                ..
1636            } => {
1637                if fields.is_empty() && !rest {
1638                    Document::string(identifier.to_string())
1639                } else {
1640                    let mut field_docs: Vec<_> = fields
1641                        .iter()
1642                        .map(|f| {
1643                            let start = f.get_span().byte_offset;
1644                            let comments = self.comments.take_comments_before(start);
1645                            prepend_comments(self.pattern(f), comments)
1646                        })
1647                        .collect();
1648                    if *rest {
1649                        field_docs.push(Document::str(".."));
1650                    }
1651                    Document::string(identifier.to_string())
1652                        .append("(")
1653                        .append(strict_break("", ""))
1654                        .append(join(field_docs, strict_break(",", ", ")))
1655                        .nest(INDENT_WIDTH)
1656                        .append(strict_break(",", ""))
1657                        .append(")")
1658                        .group()
1659                }
1660            }
1661
1662            Pattern::Struct {
1663                identifier,
1664                fields,
1665                rest,
1666                ..
1667            } => {
1668                if fields.is_empty() && !rest {
1669                    Document::string(identifier.to_string()).append(" {}")
1670                } else {
1671                    let mut field_docs: Vec<_> = fields
1672                        .iter()
1673                        .map(|f| {
1674                            let start = f.value.get_span().byte_offset;
1675                            let comments = self.comments.take_comments_before(start);
1676                            prepend_comments(self.struct_field_pattern(f), comments)
1677                        })
1678                        .collect();
1679                    if *rest {
1680                        field_docs.push(Document::str(".."));
1681                    }
1682                    Document::string(identifier.to_string())
1683                        .append(" {")
1684                        .append(strict_break(" ", " "))
1685                        .append(join(field_docs, strict_break(",", ", ")))
1686                        .nest(INDENT_WIDTH)
1687                        .append(strict_break(",", " "))
1688                        .append("}")
1689                        .group()
1690                }
1691            }
1692
1693            Pattern::Tuple { elements, .. } => {
1694                let elements_docs: Vec<_> = elements
1695                    .iter()
1696                    .map(|e| {
1697                        let start = e.get_span().byte_offset;
1698                        let comments = self.comments.take_comments_before(start);
1699                        prepend_comments(self.pattern(e), comments)
1700                    })
1701                    .collect();
1702                Document::str("(")
1703                    .append(strict_break("", ""))
1704                    .append(join(elements_docs, strict_break(",", ", ")))
1705                    .nest(INDENT_WIDTH)
1706                    .append(strict_break(",", ""))
1707                    .append(")")
1708                    .group()
1709            }
1710
1711            Pattern::Slice { prefix, rest, .. } => {
1712                let mut all_docs: Vec<Document<'a>> = Vec::new();
1713
1714                for pattern in prefix {
1715                    let start = pattern.get_span().byte_offset;
1716                    let comments = self.comments.take_comments_before(start);
1717                    all_docs.push(prepend_comments(self.pattern(pattern), comments));
1718                }
1719
1720                match rest {
1721                    RestPattern::Absent => {}
1722                    RestPattern::Discard(_) => {
1723                        all_docs.push(Document::str(".."));
1724                    }
1725                    RestPattern::Bind { name, .. } => {
1726                        all_docs
1727                            .push(Document::str("..").append(Document::string(name.to_string())));
1728                    }
1729                }
1730
1731                Document::str("[")
1732                    .append(strict_break("", ""))
1733                    .append(join(all_docs, strict_break(",", ", ")))
1734                    .nest(INDENT_WIDTH)
1735                    .append(strict_break(",", ""))
1736                    .append("]")
1737                    .group()
1738            }
1739
1740            Pattern::Or { patterns, .. } => {
1741                let pattern_docs: Vec<_> = patterns.iter().map(|p| self.pattern(p)).collect();
1742                join(pattern_docs, Document::str(" | "))
1743            }
1744        }
1745    }
1746
1747    fn struct_field_pattern(&mut self, field: &'a StructFieldPattern) -> Document<'a> {
1748        if let Pattern::Identifier { identifier, .. } = &field.value
1749            && identifier == &field.name
1750        {
1751            return Document::string(field.name.to_string());
1752        }
1753
1754        Document::string(field.name.to_string())
1755            .append(": ")
1756            .append(self.pattern(&field.value))
1757    }
1758
1759    fn binding(&mut self, binding: &'a Binding) -> Document<'a> {
1760        let pattern_doc = if binding.mutable {
1761            Document::str("mut ").append(self.pattern(&binding.pattern))
1762        } else {
1763            self.pattern(&binding.pattern)
1764        };
1765
1766        match &binding.annotation {
1767            Some(annotation) => pattern_doc
1768                .append(": ")
1769                .append(Self::annotation(annotation)),
1770            None => pattern_doc,
1771        }
1772    }
1773
1774    fn annotation(annotation: &'a Annotation) -> Document<'a> {
1775        match annotation {
1776            Annotation::Constructor { name, params, .. } => {
1777                if params.is_empty() {
1778                    if name == "Unit" {
1779                        Document::str("()")
1780                    } else {
1781                        Document::string(name.to_string())
1782                    }
1783                } else {
1784                    let param_docs: Vec<_> = params.iter().map(Self::annotation).collect();
1785                    Document::string(name.to_string())
1786                        .append("<")
1787                        .append(join(param_docs, Document::str(", ")))
1788                        .append(">")
1789                }
1790            }
1791            Annotation::Function {
1792                params,
1793                return_type,
1794                ..
1795            } => {
1796                let param_docs: Vec<_> = params.iter().map(Self::annotation).collect();
1797                Document::str("fn(")
1798                    .append(join(param_docs, Document::str(", ")))
1799                    .append(") -> ")
1800                    .append(Self::annotation(return_type))
1801            }
1802            Annotation::Unknown => Document::str("_"),
1803            Annotation::Tuple { elements, .. } => {
1804                let elem_docs: Vec<_> = elements.iter().map(Self::annotation).collect();
1805                Document::str("(")
1806                    .append(join(elem_docs, Document::str(", ")))
1807                    .append(")")
1808            }
1809            Annotation::Opaque { .. } => Document::Sequence(vec![]),
1810        }
1811    }
1812
1813    fn generics(generics: &'a [Generic]) -> Document<'a> {
1814        if generics.is_empty() {
1815            return Document::Sequence(vec![]);
1816        }
1817
1818        let generics_docs: Vec<_> = generics
1819            .iter()
1820            .map(|g| {
1821                if g.bounds.is_empty() {
1822                    Document::string(g.name.to_string())
1823                } else {
1824                    let bounds: Vec<_> = g.bounds.iter().map(Self::annotation).collect();
1825                    Document::string(g.name.to_string())
1826                        .append(": ")
1827                        .append(join(bounds, Document::str(" + ")))
1828                }
1829            })
1830            .collect();
1831
1832        Document::str("<")
1833            .append(join(generics_docs, Document::str(", ")))
1834            .append(">")
1835    }
1836
1837    fn attribute(attribute: &'a Attribute) -> Document<'a> {
1838        let name = Document::string(attribute.name.clone());
1839
1840        if attribute.args.is_empty() {
1841            Document::str("#[").append(name).append("]")
1842        } else {
1843            let args_docs: Vec<_> = attribute.args.iter().map(Self::attribute_arg).collect();
1844            Document::str("#[")
1845                .append(name)
1846                .append("(")
1847                .append(join(args_docs, Document::str(", ")))
1848                .append(")]")
1849        }
1850    }
1851
1852    fn attribute_arg(arg: &'a AttributeArg) -> Document<'a> {
1853        match arg {
1854            AttributeArg::Flag(name) => Document::string(name.clone()),
1855            AttributeArg::NegatedFlag(name) => {
1856                Document::str("!").append(Document::string(name.clone()))
1857            }
1858            AttributeArg::String(s) => Document::string(format!("\"{}\"", s)),
1859            AttributeArg::Raw(s) => Document::string(format!("`{}`", s)),
1860        }
1861    }
1862
1863    fn attributes(attrs: &'a [Attribute]) -> Document<'a> {
1864        if attrs.is_empty() {
1865            return Document::Sequence(vec![]);
1866        }
1867
1868        let attribute_docs: Vec<_> = attrs.iter().map(Self::attribute).collect();
1869        join(attribute_docs, Document::Newline).append(Document::Newline)
1870    }
1871}
1872
1873struct MethodChainSegment<'a> {
1874    member: &'a str,
1875    args: &'a [Expression],
1876    spread: &'a Option<Expression>,
1877    type_args: &'a [Annotation],
1878}
1879
1880fn collect_method_chain(expression: &Expression) -> (&Expression, Vec<MethodChainSegment<'_>>) {
1881    let mut segments = Vec::new();
1882    let mut current = expression;
1883
1884    while let Expression::Call {
1885        expression,
1886        args,
1887        spread,
1888        type_args,
1889        ..
1890    } = current
1891    {
1892        let Expression::DotAccess {
1893            expression: inner,
1894            member,
1895            ..
1896        } = expression.as_ref()
1897        else {
1898            break;
1899        };
1900        segments.push(MethodChainSegment {
1901            member,
1902            args,
1903            spread,
1904            type_args,
1905        });
1906        current = inner;
1907    }
1908
1909    segments.reverse();
1910    (current, segments)
1911}
1912
1913fn is_inlinable_arg(expression: &Expression, arity: usize) -> bool {
1914    matches!(
1915        expression,
1916        Expression::Lambda { .. }
1917            | Expression::Block { .. }
1918            | Expression::Match { .. }
1919            | Expression::Tuple { .. }
1920            | Expression::Literal {
1921                literal: Literal::Slice(_),
1922                ..
1923            }
1924    ) || matches!(expression, Expression::Call { .. } if arity == 1)
1925}