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