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