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