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