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 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}