1use crate::frontend::ast::{Expr, ExprKind};
4use crate::quality::formatter_config::FormatterConfig;
5use anyhow::Result;
6
7pub struct Formatter {
8 config: FormatterConfig,
9 source: Option<String>,
10}
11
12impl Formatter {
13 pub fn new() -> Self {
24 Self::with_config(FormatterConfig::default())
25 }
26
27 pub fn with_config(config: FormatterConfig) -> Self {
39 Self {
40 config,
41 source: None,
42 }
43 }
44
45 pub fn set_source(&mut self, source: impl Into<String>) {
56 self.source = Some(source.into());
57 }
58 pub fn format(&self, ast: &Expr) -> Result<String> {
68 if self.should_ignore(ast) {
70 if let Some(original) = self.get_original_text(ast) {
71 return Ok(original);
72 }
73 }
74
75 if let ExprKind::Block(exprs) = &ast.kind {
77 let mut result = String::new();
78 for (i, expr) in exprs.iter().enumerate() {
79 if i > 0 {
80 result.push('\n');
81 }
82 result.push_str(&self.format_expr(expr, 0));
83 }
84 Ok(result)
85 } else {
86 Ok(self.format_expr(ast, 0))
88 }
89 }
90 fn format_type(&self, ty_kind: &crate::frontend::ast::TypeKind) -> String {
91 use crate::frontend::ast::TypeKind;
92
93 match ty_kind {
94 TypeKind::Named(name) => name.clone(),
95 TypeKind::Generic { base, params } => {
96 let params_str = params.iter().map(|t| self.format_type(&t.kind)).collect::<Vec<_>>().join(", ");
97 format!("{base}<{params_str}>")
98 }
99 TypeKind::Function { params, ret } => {
100 let params_str = params.iter().map(|t| self.format_type(&t.kind)).collect::<Vec<_>>().join(", ");
101 format!("({}) -> {}", params_str, self.format_type(&ret.kind))
102 }
103 TypeKind::Tuple(types) => {
104 format!("({})", types.iter().map(|t| self.format_type(&t.kind)).collect::<Vec<_>>().join(", "))
105 }
106 TypeKind::Array { elem_type, size } => {
107 format!("[{}; {}]", self.format_type(&elem_type.kind), size)
108 }
109 _ => format!("{ty_kind:?}"),
110 }
111 }
112 fn should_ignore(&self, expr: &Expr) -> bool {
114 expr.leading_comments.iter().any(|comment| {
115 use crate::frontend::ast::CommentKind;
116 match &comment.kind {
117 CommentKind::Line(text) => {
118 let trimmed = text.trim();
119 trimmed == "ruchy-fmt-ignore"
120 || trimmed == "ruchy-fmt-ignore-next"
121 }
122 _ => false,
123 }
124 })
125 }
126
127 fn get_original_text(&self, expr: &Expr) -> Option<String> {
129 self.source.as_ref().map(|src| {
130 let start = if expr.leading_comments.is_empty() {
132 expr.span.start
133 } else {
134 expr.leading_comments[0].span.start
135 };
136
137 let mut end = self.find_rightmost_span_end(expr);
139
140 let bytes = src.as_bytes();
144
145 let mut brace_depth = 0;
147 let mut in_expression = false;
148
149 let mut scan_pos = start;
152 while scan_pos < bytes.len() {
154 while scan_pos < bytes.len() && (bytes[scan_pos] == b' ' || bytes[scan_pos] == b'\t') {
156 scan_pos += 1;
157 }
158 if scan_pos + 1 < bytes.len() && bytes[scan_pos] == b'/' && bytes[scan_pos + 1] == b'/' {
160 while scan_pos < bytes.len() && bytes[scan_pos] != b'\n' {
162 scan_pos += 1;
163 }
164 if scan_pos < bytes.len() {
165 scan_pos += 1; }
167 } else {
168 break;
169 }
170 }
171 while scan_pos < bytes.len() && (bytes[scan_pos] == b' ' || bytes[scan_pos] == b'\t' || bytes[scan_pos] == b'\n') {
173 scan_pos += 1;
174 }
175 if scan_pos < bytes.len() && bytes[scan_pos] == b'{' {
177 brace_depth = 1;
178 in_expression = true;
179 scan_pos += 1;
180 }
181
182 if in_expression {
183 while scan_pos < bytes.len() && brace_depth > 0 {
185 if bytes[scan_pos] == b'{' {
186 brace_depth += 1;
187 } else if bytes[scan_pos] == b'}' {
188 brace_depth -= 1;
189 if brace_depth == 0 {
190 end = scan_pos + 1;
192 break;
193 }
194 }
195 scan_pos += 1;
196 }
197 } else {
198 while end < bytes.len() {
200 if bytes[end] == b'\n' {
201 break;
202 }
203 end += 1;
204 }
205 }
206
207 let start = start.min(src.len());
208 let end = end.min(src.len());
209 src[start..end].to_string()
210 })
211 }
212
213 fn find_rightmost_span_end(&self, expr: &Expr) -> usize {
215 use ExprKind::{Let, Binary, Function, Block};
216 let mut max_end = expr.span.end;
217
218 match &expr.kind {
219 Let { value, body, .. } => {
220 max_end = max_end.max(self.find_rightmost_span_end(value));
221 max_end = max_end.max(self.find_rightmost_span_end(body));
222 }
223 Binary { left, right, .. } => {
224 max_end = max_end.max(self.find_rightmost_span_end(left));
225 max_end = max_end.max(self.find_rightmost_span_end(right));
226 }
227 Function { body, .. } => {
228 max_end = max_end.max(self.find_rightmost_span_end(body));
230 }
231 Block(exprs) => {
232 if let Some(last) = exprs.last() {
234 max_end = max_end.max(self.find_rightmost_span_end(last));
235 }
236 }
237 _ => {
238 }
241 }
242
243 max_end
244 }
245
246 fn format_expr(&self, expr: &Expr, indent: usize) -> String {
247 if self.should_ignore(expr) {
249 if let Some(original) = self.get_original_text(expr) {
251 return original;
252 }
253 }
255
256 let indent_str = if self.config.use_tabs {
257 "\t".repeat(indent)
258 } else {
259 " ".repeat(indent * self.config.indent_width)
260 };
261
262 let mut result = String::new();
264 for comment in &expr.leading_comments {
265 result.push_str(&self.format_comment(comment, indent));
266 result.push('\n');
267 }
268
269 let expr_str = match &expr.kind {
271 ExprKind::Literal(lit) => match lit {
272 crate::frontend::ast::Literal::Integer(n, _) => n.to_string(),
273 crate::frontend::ast::Literal::Float(f) => f.to_string(),
274 crate::frontend::ast::Literal::String(s) => {
275 format!("\"{}\"", s.replace('"', "\\\""))
276 }
277 crate::frontend::ast::Literal::Bool(b) => b.to_string(),
278 crate::frontend::ast::Literal::Char(c) => format!("'{c}'"),
279 crate::frontend::ast::Literal::Byte(b) => format!("b'{}'", *b as char),
280 crate::frontend::ast::Literal::Unit => "()".to_string(),
281 crate::frontend::ast::Literal::Null => "null".to_string(),
282 },
283 ExprKind::Identifier(name) => name.clone(),
284 ExprKind::Let {
285 name, value, body, ..
286 } => {
287 let is_sequential_statement = matches!(
292 body.kind,
293 ExprKind::Literal(crate::frontend::ast::Literal::Unit)
294 | ExprKind::Block(_)
295 | ExprKind::Call { .. }
296 | ExprKind::MethodCall { .. }
297 | ExprKind::Let { .. } );
299
300 if is_sequential_statement {
301 let mut result = format!("let {} = {}", name, self.format_expr(value, indent));
303
304 if let ExprKind::Block(body_exprs) = &body.kind {
307 let indent_str = if self.config.use_tabs {
308 "\t".repeat(indent)
309 } else {
310 " ".repeat(indent * self.config.indent_width)
311 };
312 for expr in body_exprs {
313 result.push('\n');
314 result.push_str(&indent_str);
315 result.push_str(&self.format_expr(expr, indent));
316 }
317 } else if !matches!(body.kind, ExprKind::Literal(crate::frontend::ast::Literal::Unit)) {
318 let indent_str = if self.config.use_tabs {
322 "\t".repeat(indent)
323 } else {
324 " ".repeat(indent * self.config.indent_width)
325 };
326 result.push('\n');
327 result.push_str(&indent_str);
328 result.push_str(&self.format_expr(body, indent));
329 }
330 result
333 } else {
334 format!(
337 "let {} = {} in {}",
338 name,
339 self.format_expr(value, indent),
340 self.format_expr(body, indent)
341 )
342 }
343 }
344 ExprKind::Binary { left, op, right } => {
345 format!(
347 "{} {} {}",
348 self.format_expr(left, indent),
349 op, self.format_expr(right, indent)
351 )
352 }
353 ExprKind::Block(exprs) => {
354 let mut result = String::from("{\n");
355 let inner_indent_str = if self.config.use_tabs {
356 "\t".repeat(indent + 1)
357 } else {
358 " ".repeat((indent + 1) * self.config.indent_width)
359 };
360 for expr in exprs {
361 result.push_str(&format!(
362 "{}{}\n",
363 inner_indent_str,
364 self.format_expr(expr, indent + 1)
365 ));
366 }
367 result.push_str(&format!("{indent_str}}}"));
368 result
369 }
370 ExprKind::Function {
371 name,
372 params,
373 return_type,
374 body,
375 ..
376 } => {
377 let mut result = format!("fun {name}");
378 result.push('(');
380 for (i, param) in params.iter().enumerate() {
381 if i > 0 {
382 result.push_str(", ");
383 }
384 if let crate::frontend::ast::Pattern::Identifier(param_name) = ¶m.pattern {
385 result.push_str(param_name);
386 if let crate::frontend::ast::TypeKind::Named(type_name) = ¶m.ty.kind {
388 if type_name != "Any" {
389 result.push_str(": ");
390 result.push_str(type_name);
391 }
392 } else {
393 result.push_str(": ");
394 result.push_str(&self.format_type(¶m.ty.kind));
395 }
396 }
397 }
398 result.push(')');
399 if let Some(ret_ty) = return_type {
401 result.push_str(" -> ");
402 result.push_str(&self.format_type(&ret_ty.kind));
403 }
404 result.push(' ');
405 result.push_str(&self.format_expr(body.as_ref(), indent));
406 result
407 }
408 ExprKind::If {
409 condition,
410 then_branch,
411 else_branch,
412 } => {
413 let mut result = "if ".to_string();
414 result.push_str(&self.format_expr(condition, indent));
415 result.push(' ');
416 result.push_str(&self.format_expr(then_branch, indent));
417 if let Some(else_expr) = else_branch {
418 result.push_str(" else ");
419 result.push_str(&self.format_expr(else_expr, indent));
420 }
421 result
422 }
423 ExprKind::Call { func, args } => {
424 let mut result = self.format_expr(func, indent);
425 result.push('(');
426 for (i, arg) in args.iter().enumerate() {
427 if i > 0 {
428 result.push_str(", ");
429 }
430 result.push_str(&self.format_expr(arg, indent));
431 }
432 result.push(')');
433 result
434 }
435 ExprKind::MethodCall {
436 receiver,
437 method,
438 args,
439 ..
440 } => {
441 let mut result = self.format_expr(receiver, indent);
442 result.push('.');
443 result.push_str(method);
444 result.push('(');
445 for (i, arg) in args.iter().enumerate() {
446 if i > 0 {
447 result.push_str(", ");
448 }
449 result.push_str(&self.format_expr(arg, indent));
450 }
451 result.push(')');
452 result
453 }
454 ExprKind::For {
455 var,
456 pattern,
457 iter,
458 body,
459 ..
460 } => {
461 let mut result = "for ".to_string();
462 if let Some(pat) = pattern {
463 if let crate::frontend::ast::Pattern::Identifier(name) = pat {
464 result.push_str(name);
465 } else {
466 result.push_str(&format!("{pat:?}"));
467 }
468 } else {
469 result.push_str(var);
470 }
471 result.push_str(" in ");
472 result.push_str(&self.format_expr(iter, indent));
473 result.push(' ');
474 result.push_str(&self.format_expr(body, indent));
475 result
476 }
477 ExprKind::IndexAccess { object, index } => {
479 format!(
480 "{}[{}]",
481 self.format_expr(object, indent),
482 self.format_expr(index, indent)
483 )
484 }
485 ExprKind::Assign { target, value } => {
487 format!(
488 "{} = {}",
489 self.format_expr(target, indent),
490 self.format_expr(value, indent)
491 )
492 }
493 ExprKind::Return { value } => {
495 if let Some(val) = value {
496 format!("return {}", self.format_expr(val, indent))
497 } else {
498 "return".to_string()
499 }
500 }
501 ExprKind::FieldAccess { object, field } => {
503 format!("{}.{}", self.format_expr(object, indent), field)
504 }
505 ExprKind::While { condition, body, .. } => {
507 format!(
508 "while {} {}",
509 self.format_expr(condition, indent),
510 self.format_expr(body, indent)
511 )
512 }
513 ExprKind::Break { value, .. } => {
515 if let Some(val) = value {
516 format!("break {}", self.format_expr(val, indent))
517 } else {
518 "break".to_string()
519 }
520 }
521 ExprKind::Continue { .. } => "continue".to_string(),
523 ExprKind::Range { start, end, inclusive } => {
525 let op = if *inclusive { "..=" } else { ".." };
526 format!(
527 "{}{}{}",
528 self.format_expr(start, indent),
529 op,
530 self.format_expr(end, indent)
531 )
532 }
533 ExprKind::Unary { op, operand } => {
535 format!("{}{}", op, self.format_expr(operand, indent))
536 }
537 ExprKind::List(items) => {
539 let formatted_items: Vec<String> = items
540 .iter()
541 .map(|item| self.format_expr(item, indent))
542 .collect();
543 format!("[{}]", formatted_items.join(", "))
544 }
545 ExprKind::Tuple(items) => {
547 let formatted_items: Vec<String> = items
548 .iter()
549 .map(|item| self.format_expr(item, indent))
550 .collect();
551 format!("({})", formatted_items.join(", "))
552 }
553 ExprKind::Match { expr, arms } => {
555 let mut result = format!("match {} {{\n", self.format_expr(expr, indent));
556 for arm in arms {
557 let pattern_str = format!("{:?}", arm.pattern); result.push_str(&format!(
559 "{} {} => {},\n",
560 " ".repeat(indent * self.config.indent_width),
561 pattern_str,
562 self.format_expr(&arm.body, indent + 1)
563 ));
564 }
565 result.push_str(&format!("{}}}", " ".repeat(indent * self.config.indent_width)));
566 result
567 }
568 ExprKind::CompoundAssign { target, op, value } => {
570 format!(
571 "{} {}= {}",
572 self.format_expr(target, indent),
573 op,
574 self.format_expr(value, indent)
575 )
576 }
577 ExprKind::Lambda { params, body } => {
579 let params_str = params
580 .iter()
581 .map(|p| self.format_pattern(&p.pattern))
582 .collect::<Vec<_>>()
583 .join(", ");
584 format!("|{}| {}", params_str, self.format_expr(body, indent))
585 }
586 ExprKind::ObjectLiteral { fields } => {
587 if fields.is_empty() {
588 "{}".to_string()
589 } else {
590 let fields_str = fields
591 .iter()
592 .map(|f| match f {
593 crate::frontend::ast::ObjectField::KeyValue { key, value } => {
594 format!("{}: {}", key, self.format_expr(value, indent))
595 }
596 crate::frontend::ast::ObjectField::Spread { expr } => {
597 format!("...{}", self.format_expr(expr, indent))
598 }
599 })
600 .collect::<Vec<_>>()
601 .join(", ");
602 format!("{{ {fields_str} }}")
603 }
604 }
605 ExprKind::StructLiteral { name, fields, base } => {
606 let fields_str = fields
607 .iter()
608 .map(|(key, val)| format!("{}: {}", key, self.format_expr(val, indent)))
609 .collect::<Vec<_>>()
610 .join(", ");
611
612 if let Some(base_expr) = base {
613 format!("{} {{ {}, ..{} }}", name, fields_str, self.format_expr(base_expr, indent))
614 } else {
615 format!("{name} {{ {fields_str} }}")
616 }
617 }
618 ExprKind::Ternary { condition, true_expr, false_expr } => {
619 format!(
620 "{} ? {} : {}",
621 self.format_expr(condition, indent),
622 self.format_expr(true_expr, indent),
623 self.format_expr(false_expr, indent)
624 )
625 }
626 ExprKind::Throw { expr } => {
627 format!("throw {}", self.format_expr(expr, indent))
628 }
629 ExprKind::TryCatch { try_block, catch_clauses, finally_block } => {
630 let mut result = format!("try {}", self.format_expr(try_block, indent));
631
632 for catch_clause in catch_clauses {
633 result.push_str(&format!(
634 " catch ({}) {}",
635 self.format_pattern(&catch_clause.pattern),
636 self.format_expr(&catch_clause.body, indent)
637 ));
638 }
639
640 if let Some(finally) = finally_block {
641 result.push_str(&format!(" finally {}", self.format_expr(finally, indent)));
642 }
643
644 result
645 }
646 ExprKind::Await { expr } => {
647 format!("await {}", self.format_expr(expr, indent))
648 }
649 ExprKind::AsyncBlock { body } => {
650 format!("async {}", self.format_expr(body, indent))
651 }
652 ExprKind::TypeCast { expr, target_type } => {
653 format!("{} as {}", self.format_expr(expr, indent), target_type)
654 }
655
656 ExprKind::ArrayInit { value, size } => {
658 format!("[{}; {}]", self.format_expr(value, indent), self.format_expr(size, indent))
659 }
660 ExprKind::Ok { value } => {
661 format!("Ok({})", self.format_expr(value, indent))
662 }
663 ExprKind::Err { error } => {
664 format!("Err({})", self.format_expr(error, indent))
665 }
666 ExprKind::Some { value } => {
667 format!("Some({})", self.format_expr(value, indent))
668 }
669 ExprKind::None => "None".to_string(),
670 ExprKind::Try { expr } => {
671 format!("{}?", self.format_expr(expr, indent))
672 }
673 ExprKind::Spawn { actor } => {
674 format!("spawn {}", self.format_expr(actor, indent))
675 }
676 ExprKind::AsyncLambda { params, body } => {
677 let params_str = params.join(", ");
678 format!("async |{}| {}", params_str, self.format_expr(body, indent))
679 }
680 ExprKind::IfLet { pattern, expr, then_branch, else_branch } => {
681 let mut result = format!(
682 "if let {} = {} {}",
683 self.format_pattern(pattern),
684 self.format_expr(expr, indent),
685 self.format_expr(then_branch, indent)
686 );
687 if let Some(else_expr) = else_branch {
688 result.push_str(&format!(" else {}", self.format_expr(else_expr, indent)));
689 }
690 result
691 }
692 ExprKind::OptionalFieldAccess { object, field } => {
693 format!("{}?.{}", self.format_expr(object, indent), field)
694 }
695 ExprKind::Slice { object, start, end } => {
696 let start_str = start.as_ref().map_or(String::new(), |e| self.format_expr(e, indent));
697 let end_str = end.as_ref().map_or(String::new(), |e| self.format_expr(e, indent));
698 format!("{}[{}..{}]", self.format_expr(object, indent), start_str, end_str)
699 }
700
701 ExprKind::Struct { name, type_params, fields, is_pub, .. } => {
703 let pub_str = if *is_pub { "pub " } else { "" };
704 let type_params_str = if type_params.is_empty() {
705 String::new()
706 } else {
707 format!("<{}>", type_params.join(", "))
708 };
709 let fields_str = fields
710 .iter()
711 .map(|f| format!("{}: {}", f.name, self.format_type(&f.ty.kind)))
712 .collect::<Vec<_>>()
713 .join(", ");
714 format!("{pub_str}struct {name}{type_params_str} {{ {fields_str} }}")
715 }
716 ExprKind::TupleStruct { name, type_params, fields, is_pub, .. } => {
717 let pub_str = if *is_pub { "pub " } else { "" };
718 let type_params_str = if type_params.is_empty() {
719 String::new()
720 } else {
721 format!("<{}>", type_params.join(", "))
722 };
723 let fields_str = fields
724 .iter()
725 .map(|ty| self.format_type(&ty.kind))
726 .collect::<Vec<_>>()
727 .join(", ");
728 format!("{pub_str}struct {name}{type_params_str}({fields_str})")
729 }
730 ExprKind::Enum { name, type_params, variants, is_pub } => {
731 let pub_str = if *is_pub { "pub " } else { "" };
732 let type_params_str = if type_params.is_empty() {
733 String::new()
734 } else {
735 format!("<{}>", type_params.join(", "))
736 };
737 let variants_str = variants
738 .iter()
739 .map(|v| self.format_enum_variant(v))
740 .collect::<Vec<_>>()
741 .join(", ");
742 format!("{pub_str}enum {name}{type_params_str} {{ {variants_str} }}")
743 }
744 ExprKind::Trait { name, type_params, methods, is_pub, .. } => {
745 let pub_str = if *is_pub { "pub " } else { "" };
746 let type_params_str = if type_params.is_empty() {
747 String::new()
748 } else {
749 format!("<{}>", type_params.join(", "))
750 };
751 let methods_str = methods
752 .iter()
753 .map(|m| self.format_trait_method(m))
754 .collect::<Vec<_>>()
755 .join(" ");
756 format!("{pub_str}trait {name}{type_params_str} {{ {methods_str} }}")
757 }
758 ExprKind::Impl { type_params, trait_name, for_type, methods, .. } => {
759 let type_params_str = if type_params.is_empty() {
760 String::new()
761 } else {
762 format!("<{}>", type_params.join(", "))
763 };
764 let trait_part = trait_name.as_ref().map_or(String::new(), |t| format!("{t} for "));
765 let methods_str = methods
766 .iter()
767 .map(|m| self.format_impl_method(m))
768 .collect::<Vec<_>>()
769 .join(" ");
770 format!("impl{type_params_str} {trait_part}{for_type} {{ {methods_str} }}")
771 }
772 ExprKind::Class { name, type_params, fields, .. } => {
773 let type_params_str = if type_params.is_empty() {
774 String::new()
775 } else {
776 format!("<{}>", type_params.join(", "))
777 };
778 let fields_str = fields
779 .iter()
780 .map(|f| format!("{}: {}", f.name, self.format_type(&f.ty.kind)))
781 .collect::<Vec<_>>()
782 .join(", ");
783 format!("class {name}{type_params_str} {{ {fields_str} }}")
784 }
785 ExprKind::Module { name, body } => {
786 format!("mod {} {}", name, self.format_expr(body, indent))
787 }
788 ExprKind::Import { module, items } => {
789 if let Some(item_list) = items {
790 format!("import {}::{{{}}}", module, item_list.join(", "))
791 } else {
792 format!("import {module}")
793 }
794 }
795 ExprKind::Export { expr, is_default } => {
796 if *is_default {
797 format!("export default {}", self.format_expr(expr, indent))
798 } else {
799 format!("export {}", self.format_expr(expr, indent))
800 }
801 }
802 ExprKind::LetPattern { pattern, value, body, .. } => {
803 format!(
804 "let {} = {} in {}",
805 self.format_pattern(pattern),
806 self.format_expr(value, indent),
807 self.format_expr(body, indent)
808 )
809 }
810 ExprKind::WhileLet { pattern, expr, body, .. } => {
811 format!(
812 "while let {} = {} {}",
813 self.format_pattern(pattern),
814 self.format_expr(expr, indent),
815 self.format_expr(body, indent)
816 )
817 }
818 ExprKind::StringInterpolation { parts } => {
819 let parts_str = parts
820 .iter()
821 .map(|part| match part {
822 crate::frontend::ast::StringPart::Text(s) => s.clone(),
823 crate::frontend::ast::StringPart::Expr(e) => {
824 format!("{{{}}}", self.format_expr(e, indent))
825 }
826 crate::frontend::ast::StringPart::ExprWithFormat { expr, format_spec } => {
827 format!("{{{}:{}}}", self.format_expr(expr, indent), format_spec)
828 }
829 })
830 .collect::<String>();
831 format!("f\"{parts_str}\"")
832 }
833 ExprKind::Actor { name, state, handlers } => {
834 let state_str = state
835 .iter()
836 .map(|f| format!("{}: {}", f.name, self.format_type(&f.ty.kind)))
837 .collect::<Vec<_>>()
838 .join(", ");
839 let handlers_str = handlers
840 .iter()
841 .map(|h| format!("handle {}", h.message_type))
842 .collect::<Vec<_>>()
843 .join(" ");
844 format!("actor {name} {{ {state_str} {handlers_str} }}")
845 }
846 ExprKind::Send { actor, message } => {
847 format!("send({}, {})", self.format_expr(actor, indent), self.format_expr(message, indent))
848 }
849 ExprKind::Loop { body, .. } => {
851 format!("loop {{\n{}\n{}}}", self.format_expr(body, indent + 1), " ".repeat(indent * self.config.indent_width))
852 }
853 ExprKind::Pipeline { expr, stages } => {
854 let mut result = self.format_expr(expr, indent);
856 for stage in stages {
857 result.push_str(" |> ");
858 result.push_str(&self.format_expr(&stage.op, indent));
859 }
860 result
861 }
862 ExprKind::PreIncrement { target } => {
864 format!("++{}", self.format_expr(target, indent))
865 }
866 ExprKind::PostIncrement { target } => {
867 format!("{}++", self.format_expr(target, indent))
868 }
869 ExprKind::PreDecrement { target } => {
870 format!("--{}", self.format_expr(target, indent))
871 }
872 ExprKind::PostDecrement { target } => {
873 format!("{}--", self.format_expr(target, indent))
874 }
875 ExprKind::ActorSend { actor, message } => {
876 format!("{} <- {}", self.format_expr(actor, indent), self.format_expr(message, indent))
877 }
878 ExprKind::ActorQuery { actor, message } => {
879 format!("{} <? {}", self.format_expr(actor, indent), self.format_expr(message, indent))
880 }
881 ExprKind::Ask { actor, message, .. } => {
882 format!("ask {} {}", self.format_expr(actor, indent), self.format_expr(message, indent))
884 }
885 ExprKind::ListComprehension { element, clauses } => {
886 let clauses_str = clauses
887 .iter()
888 .map(|clause| {
889 let cond = clause
890 .condition
891 .as_ref()
892 .map(|c| format!(" if {}", self.format_expr(c, indent)))
893 .unwrap_or_default();
894 format!("{} in {}{}", clause.variable, self.format_expr(&clause.iterable, indent), cond)
895 })
896 .collect::<Vec<_>>()
897 .join(", ");
898 format!("[{} for {}]", self.format_expr(element, indent), clauses_str)
899 }
900 ExprKind::DictComprehension { key, value, clauses } => {
901 let clauses_str = clauses
902 .iter()
903 .map(|clause| {
904 let cond = clause
905 .condition
906 .as_ref()
907 .map(|c| format!(" if {}", self.format_expr(c, indent)))
908 .unwrap_or_default();
909 format!("{} in {}{}", clause.variable, self.format_expr(&clause.iterable, indent), cond)
910 })
911 .collect::<Vec<_>>()
912 .join(", ");
913 format!("{{{}: {} for {}}}", self.format_expr(key, indent), self.format_expr(value, indent), clauses_str)
914 }
915 ExprKind::SetComprehension { element, clauses } => {
916 let clauses_str = clauses
917 .iter()
918 .map(|clause| {
919 let cond = clause
920 .condition
921 .as_ref()
922 .map(|c| format!(" if {}", self.format_expr(c, indent)))
923 .unwrap_or_default();
924 format!("{} in {}{}", clause.variable, self.format_expr(&clause.iterable, indent), cond)
925 })
926 .collect::<Vec<_>>()
927 .join(", ");
928 format!("{{{} for {}}}", self.format_expr(element, indent), clauses_str)
929 }
930 ExprKind::ImportAll { module, .. } => {
931 format!("import {module}::*")
932 }
933 ExprKind::ImportDefault { module, name } => {
934 format!("import default {name} from {module}")
935 }
936 ExprKind::ExportList { names } => {
937 format!("export {{ {} }}", names.join(", "))
938 }
939 ExprKind::ExportDefault { expr } => {
940 format!("export default {}", self.format_expr(expr, indent))
941 }
942 ExprKind::Command { program, args, .. } => {
943 let full_cmd = if args.is_empty() {
945 program.clone()
946 } else {
947 format!("{} {}", program, args.join(" "))
948 };
949 format!("`{full_cmd}`")
950 }
951 ExprKind::QualifiedName { module, name } => {
953 format!("{module}::{name}")
954 }
955 ExprKind::TypeAlias { name, target_type } => {
956 format!("type {} = {}", name, self.format_type(&target_type.kind))
957 }
958 ExprKind::Spread { expr } => {
959 format!("...{}", self.format_expr(expr, indent))
960 }
961 ExprKind::OptionalMethodCall { receiver, method, args } => {
962 let args_str = args
963 .iter()
964 .map(|arg| self.format_expr(arg, indent))
965 .collect::<Vec<_>>()
966 .join(", ");
967 format!(
968 "{}?.{}({})",
969 self.format_expr(receiver, indent),
970 method,
971 args_str
972 )
973 }
974 ExprKind::Extension { target_type, methods } => {
975 let indent_str = " ".repeat(indent * self.config.indent_width);
976 let methods_str = methods
977 .iter()
978 .map(|method| {
979 let params_str = method
980 .params
981 .iter()
982 .map(|p| self.format_pattern(&p.pattern))
983 .collect::<Vec<_>>()
984 .join(", ");
985 format!(
986 "{} fun {}({}) {{ }}",
987 indent_str,
988 method.name,
989 params_str
990 )
991 })
992 .collect::<Vec<_>>()
993 .join("\n");
994 format!(
995 "extension {target_type} {{\n{methods_str}\n{indent_str}}}"
996 )
997 }
998 ExprKind::ReExport { items, module } => {
999 format!("export {{ {} }} from {}", items.join(", "), module)
1000 }
1001 ExprKind::Macro { name, args } => {
1002 let args_str = args
1003 .iter()
1004 .map(|arg| self.format_expr(arg, indent))
1005 .collect::<Vec<_>>()
1006 .join(", ");
1007 format!("macro {name}({args_str}) {{ }}")
1008 }
1009 ExprKind::MacroInvocation { name, args } => {
1010 let args_str = args
1011 .iter()
1012 .map(|arg| self.format_expr(arg, indent))
1013 .collect::<Vec<_>>()
1014 .join(", ");
1015 format!("{name}!({args_str})")
1016 }
1017 ExprKind::DataFrame { columns } => {
1018 let columns_str = columns
1019 .iter()
1020 .map(|col| {
1021 let values_str = col.values
1022 .iter()
1023 .map(|v| self.format_expr(v, indent))
1024 .collect::<Vec<_>>()
1025 .join(", ");
1026 format!("\"{}\" => [{}]", col.name, values_str)
1027 })
1028 .collect::<Vec<_>>()
1029 .join(", ");
1030 format!("df![{columns_str}]")
1031 }
1032 ExprKind::DataFrameOperation { source, operation } => {
1033 format!(
1035 "{}.{:?}",
1036 self.format_expr(source, indent),
1037 operation
1038 )
1039 }
1040 ExprKind::Set(_) => {
1041 format!("/* UNIMPLEMENTED: {:?} */", expr.kind)
1044 }
1045 };
1046
1047 result.push_str(&expr_str);
1049
1050 if let Some(trailing) = &expr.trailing_comment {
1052 result.push(' ');
1053 result.push_str(&self.format_comment(trailing, 0)); }
1055
1056 result
1057 }
1058
1059 fn format_comment(&self, comment: &crate::frontend::ast::Comment, indent: usize) -> String {
1061 let indent_str = if self.config.use_tabs {
1062 "\t".repeat(indent)
1063 } else {
1064 " ".repeat(indent * self.config.indent_width)
1065 };
1066
1067 match &comment.kind {
1068 crate::frontend::ast::CommentKind::Line(text) => {
1069 format!("{indent_str}//{text}")
1071 }
1072 crate::frontend::ast::CommentKind::Doc(text) => {
1073 format!("{indent_str}///{text}")
1075 }
1076 crate::frontend::ast::CommentKind::Block(text) => {
1077 format!("{indent_str}/*{text}*/")
1079 }
1080 }
1081 }
1082
1083 fn format_pattern(&self, pattern: &crate::frontend::ast::Pattern) -> String {
1085 use crate::frontend::ast::Pattern;
1086
1087 match pattern {
1088 Pattern::Wildcard => "_".to_string(),
1089 Pattern::Literal(lit) => self.format_literal(lit),
1090 Pattern::Identifier(name) => name.clone(),
1091 Pattern::QualifiedName(parts) => parts.join("::"),
1092 Pattern::Tuple(patterns) => {
1093 let inner = patterns
1094 .iter()
1095 .map(|p| self.format_pattern(p))
1096 .collect::<Vec<_>>()
1097 .join(", ");
1098 format!("({inner})")
1099 }
1100 Pattern::List(patterns) => {
1101 let inner = patterns
1102 .iter()
1103 .map(|p| self.format_pattern(p))
1104 .collect::<Vec<_>>()
1105 .join(", ");
1106 format!("[{inner}]")
1107 }
1108 Pattern::Struct { name, fields, has_rest } => {
1109 let fields_str = fields
1110 .iter()
1111 .map(|f| self.format_struct_pattern_field(f))
1112 .collect::<Vec<_>>()
1113 .join(", ");
1114 if *has_rest {
1115 format!("{name} {{ {fields_str}, .. }}")
1116 } else {
1117 format!("{name} {{ {fields_str} }}")
1118 }
1119 }
1120 Pattern::TupleVariant { path, patterns } => {
1121 let path_str = path.join("::");
1122 let patterns_str = patterns
1123 .iter()
1124 .map(|p| self.format_pattern(p))
1125 .collect::<Vec<_>>()
1126 .join(", ");
1127 format!("{path_str}({patterns_str})")
1128 }
1129 Pattern::Range { start, end, inclusive } => {
1130 let op = if *inclusive { "..=" } else { ".." };
1131 format!("{}{}{}", self.format_pattern(start), op, self.format_pattern(end))
1132 }
1133 Pattern::Or(patterns) => {
1134 patterns
1135 .iter()
1136 .map(|p| self.format_pattern(p))
1137 .collect::<Vec<_>>()
1138 .join(" | ")
1139 }
1140 Pattern::Rest => "..".to_string(),
1141 Pattern::RestNamed(name) => format!("..{name}"),
1142 Pattern::AtBinding { name, pattern } => {
1143 format!("{} @ {}", name, self.format_pattern(pattern))
1144 }
1145 Pattern::WithDefault { pattern, default } => {
1146 format!("{} = {}", self.format_pattern(pattern), self.format_expr(default, 0))
1147 }
1148 Pattern::Mut(pattern) => {
1149 format!("mut {}", self.format_pattern(pattern))
1150 }
1151 Pattern::Ok(pattern) => {
1152 format!("Ok({})", self.format_pattern(pattern))
1153 }
1154 Pattern::Err(pattern) => {
1155 format!("Err({})", self.format_pattern(pattern))
1156 }
1157 Pattern::Some(pattern) => {
1158 format!("Some({})", self.format_pattern(pattern))
1159 }
1160 Pattern::None => "None".to_string(),
1161 }
1162 }
1163
1164 fn format_struct_pattern_field(&self, field: &crate::frontend::ast::StructPatternField) -> String {
1166 if let Some(pattern) = &field.pattern {
1167 format!("{}: {}", field.name, self.format_pattern(pattern))
1168 } else {
1169 field.name.clone()
1171 }
1172 }
1173
1174 fn format_literal(&self, literal: &crate::frontend::ast::Literal) -> String {
1176 use crate::frontend::ast::Literal;
1177
1178 match literal {
1179 Literal::Integer(val, suffix) => {
1180 if let Some(suffix) = suffix {
1181 format!("{val}{suffix}")
1182 } else {
1183 val.to_string()
1184 }
1185 }
1186 Literal::Float(val) => val.to_string(),
1187 Literal::String(s) => format!("\"{s}\""),
1188 Literal::Bool(b) => b.to_string(),
1189 Literal::Char(c) => format!("'{c}'"),
1190 Literal::Byte(b) => format!("{b}u8"),
1191 Literal::Unit => "()".to_string(),
1192 Literal::Null => "null".to_string(),
1193 }
1194 }
1195
1196 fn format_enum_variant(&self, variant: &crate::frontend::ast::EnumVariant) -> String {
1198 use crate::frontend::ast::EnumVariantKind;
1199
1200 match &variant.kind {
1201 EnumVariantKind::Unit => variant.name.clone(),
1202 EnumVariantKind::Tuple(types) => {
1203 let types_str = types.iter().map(|t| self.format_type(&t.kind)).collect::<Vec<_>>().join(", ");
1204 format!("{}({})", variant.name, types_str)
1205 }
1206 EnumVariantKind::Struct(fields) => {
1207 let fields_str = fields
1208 .iter()
1209 .map(|f| format!("{}: {}", f.name, self.format_type(&f.ty.kind)))
1210 .collect::<Vec<_>>()
1211 .join(", ");
1212 format!("{} {{ {} }}", variant.name, fields_str)
1213 }
1214 }
1215 }
1216
1217 fn format_trait_method(&self, method: &crate::frontend::ast::TraitMethod) -> String {
1219 let params_str = method.params
1220 .iter()
1221 .map(|p| format!("{}: {}", self.format_pattern(&p.pattern), self.format_type(&p.ty.kind)))
1222 .collect::<Vec<_>>()
1223 .join(", ");
1224 let return_str = method.return_type.as_ref().map_or(String::new(), |t| format!(" -> {}", self.format_type(&t.kind)));
1225 format!("fun {}({}){}; ", method.name, params_str, return_str)
1226 }
1227
1228 fn format_impl_method(&self, method: &crate::frontend::ast::ImplMethod) -> String {
1230 let params_str = method.params
1231 .iter()
1232 .map(|p| format!("{}: {}", self.format_pattern(&p.pattern), self.format_type(&p.ty.kind)))
1233 .collect::<Vec<_>>()
1234 .join(", ");
1235 let return_str = method.return_type.as_ref().map_or(String::new(), |t| format!(" -> {}", self.format_type(&t.kind)));
1236 format!("fun {}({}){} {}", method.name, params_str, return_str, self.format_expr(&method.body, 0))
1237 }
1238}
1239impl Default for Formatter {
1240 fn default() -> Self {
1241 Self::new()
1242 }
1243}
1244#[cfg(test)]
1245mod tests {
1246 use super::*;
1247 use crate::frontend::ast::*;
1248
1249 fn create_simple_literal(value: i64) -> Expr {
1250 Expr::new(
1251 ExprKind::Literal(Literal::Integer(value, None)),
1252 Default::default(),
1253 )
1254 }
1255
1256 fn create_identifier(name: &str) -> Expr {
1257 Expr::new(ExprKind::Identifier(name.to_string()), Default::default())
1258 }
1259
1260 #[test]
1261 fn test_formatter_new() {
1262 let formatter = Formatter::new();
1263 assert_eq!(formatter.config.indent_width, 4);
1264 assert!(!formatter.config.use_tabs);
1265 }
1266
1267 #[test]
1268 fn test_formatter_default() {
1269 let formatter = Formatter::default();
1270 assert_eq!(formatter.config.indent_width, 4);
1271 assert!(!formatter.config.use_tabs);
1272 }
1273
1274 #[test]
1275 fn test_format_integer_literal() {
1276 let formatter = Formatter::new();
1277 let expr = create_simple_literal(42);
1278 let result = formatter.format(&expr).unwrap();
1279 assert_eq!(result, "42");
1280 }
1281
1282 #[test]
1283 fn test_format_float_literal() {
1284 let formatter = Formatter::new();
1285 let expr = Expr::new(ExprKind::Literal(Literal::Float(3.14)), Default::default());
1286 let result = formatter.format(&expr).unwrap();
1287 assert_eq!(result, "3.14");
1288 }
1289
1290 #[test]
1291 fn test_format_string_literal() {
1292 let formatter = Formatter::new();
1293 let expr = Expr::new(
1294 ExprKind::Literal(Literal::String("hello".to_string())),
1295 Default::default(),
1296 );
1297 let result = formatter.format(&expr).unwrap();
1298 assert_eq!(result, "\"hello\"");
1299 }
1300
1301 #[test]
1302 fn test_format_bool_literal() {
1303 let formatter = Formatter::new();
1304 let expr = Expr::new(ExprKind::Literal(Literal::Bool(true)), Default::default());
1305 let result = formatter.format(&expr).unwrap();
1306 assert_eq!(result, "true");
1307
1308 let expr = Expr::new(ExprKind::Literal(Literal::Bool(false)), Default::default());
1309 let result = formatter.format(&expr).unwrap();
1310 assert_eq!(result, "false");
1311 }
1312
1313 #[test]
1314 fn test_format_char_literal() {
1315 let formatter = Formatter::new();
1316 let expr = Expr::new(ExprKind::Literal(Literal::Char('a')), Default::default());
1317 let result = formatter.format(&expr).unwrap();
1318 assert_eq!(result, "'a'");
1319 }
1320
1321 #[test]
1322 fn test_format_unit_literal() {
1323 let formatter = Formatter::new();
1324 let expr = Expr::new(ExprKind::Literal(Literal::Unit), Default::default());
1325 let result = formatter.format(&expr).unwrap();
1326 assert_eq!(result, "()");
1327 }
1328
1329 #[test]
1330 fn test_format_identifier() {
1331 let formatter = Formatter::new();
1332 let expr = create_identifier("my_var");
1333 let result = formatter.format(&expr).unwrap();
1334 assert_eq!(result, "my_var");
1335 }
1336
1337 #[test]
1338 fn test_format_binary_expression() {
1339 let formatter = Formatter::new();
1340 let left = create_simple_literal(1);
1341 let right = create_simple_literal(2);
1342 let expr = Expr::new(
1343 ExprKind::Binary {
1344 left: Box::new(left),
1345 op: BinaryOp::Add,
1346 right: Box::new(right),
1347 },
1348 Default::default(),
1349 );
1350 let result = formatter.format(&expr).unwrap();
1351 assert_eq!(result, "1 + 2"); }
1353
1354 #[test]
1355 fn test_format_let_expression() {
1356 let formatter = Formatter::new();
1357 let value = create_simple_literal(42);
1358 let body = create_identifier("x");
1359 let expr = Expr::new(
1360 ExprKind::Let {
1361 name: "x".to_string(),
1362 value: Box::new(value),
1363 body: Box::new(body),
1364 type_annotation: Some(Type {
1365 kind: TypeKind::Named("Int".to_string()),
1366 span: Default::default(),
1367 }),
1368 is_mutable: false,
1369 else_block: None,
1370 },
1371 Default::default(),
1372 );
1373 let result = formatter.format(&expr).unwrap();
1374 assert_eq!(result, "let x = 42 in x");
1375 }
1376
1377 #[test]
1378 fn test_format_block_expression() {
1379 let formatter = Formatter::new();
1380 let exprs = vec![create_simple_literal(1), create_simple_literal(2)];
1381 let expr = Expr::new(ExprKind::Block(exprs), Default::default());
1382 let result = formatter.format(&expr).unwrap();
1383 assert!(!result.is_empty());
1385 }
1386
1387 #[test]
1388 fn test_format_if_expression() {
1389 let formatter = Formatter::new();
1390 let condition = Expr::new(ExprKind::Literal(Literal::Bool(true)), Default::default());
1391 let then_branch = create_simple_literal(1);
1392 let else_branch = create_simple_literal(2);
1393 let expr = Expr::new(
1394 ExprKind::If {
1395 condition: Box::new(condition),
1396 then_branch: Box::new(then_branch),
1397 else_branch: Some(Box::new(else_branch)),
1398 },
1399 Default::default(),
1400 );
1401 let result = formatter.format(&expr).unwrap();
1402 assert_eq!(result, "if true 1 else 2");
1403 }
1404
1405 #[test]
1406 fn test_format_if_without_else() {
1407 let formatter = Formatter::new();
1408 let condition = Expr::new(ExprKind::Literal(Literal::Bool(true)), Default::default());
1409 let then_branch = create_simple_literal(1);
1410 let expr = Expr::new(
1411 ExprKind::If {
1412 condition: Box::new(condition),
1413 then_branch: Box::new(then_branch),
1414 else_branch: None,
1415 },
1416 Default::default(),
1417 );
1418 let result = formatter.format(&expr).unwrap();
1419 assert_eq!(result, "if true 1");
1420 }
1421
1422 #[test]
1423 fn test_format_function_simple() {
1424 let formatter = Formatter::new();
1425 let body = create_simple_literal(42);
1426 let expr = Expr::new(
1427 ExprKind::Function {
1428 name: "test".to_string(),
1429 type_params: vec![],
1430 params: vec![],
1431 return_type: None,
1432 body: Box::new(body),
1433 is_async: false,
1434 is_pub: false,
1435 },
1436 Default::default(),
1437 );
1438 let result = formatter.format(&expr).unwrap();
1439 assert!(!result.is_empty());
1441 }
1442
1443 #[test]
1444 fn test_format_function_with_params() {
1445 let formatter = Formatter::new();
1446 let body = create_identifier("x");
1447 let param = Param {
1448 pattern: Pattern::Identifier("x".to_string()),
1449 ty: Type {
1450 kind: TypeKind::Named("Int".to_string()),
1451 span: Default::default(),
1452 },
1453 span: Default::default(),
1454 is_mutable: false,
1455 default_value: None,
1456 };
1457 let expr = Expr::new(
1458 ExprKind::Function {
1459 name: "identity".to_string(),
1460 type_params: vec![],
1461 params: vec![param],
1462 return_type: Some(Type {
1463 kind: TypeKind::Named("Int".to_string()),
1464 span: Default::default(),
1465 }),
1466 body: Box::new(body),
1467 is_async: false,
1468 is_pub: false,
1469 },
1470 Default::default(),
1471 );
1472 let result = formatter.format(&expr).unwrap();
1473 assert!(!result.is_empty());
1475 }
1476
1477 #[test]
1478 fn test_format_type_named() {
1479 let formatter = Formatter::new();
1480 let type_kind = TypeKind::Named("String".to_string());
1481 let result = formatter.format_type(&type_kind);
1482 assert_eq!(result, "String");
1483 }
1484
1485 #[test]
1486 fn test_format_type_fallback() {
1487 let formatter = Formatter::new();
1488 let type_kind = TypeKind::List(Box::new(Type {
1489 kind: TypeKind::Named("Int".to_string()),
1490 span: Default::default(),
1491 }));
1492 let result = formatter.format_type(&type_kind);
1493 assert!(result.contains("List"));
1494 }
1495
1496 #[test]
1497 fn test_format_with_tabs() {
1498 let mut formatter = Formatter::new();
1499 formatter.config.use_tabs = true;
1500 let exprs = vec![create_simple_literal(1)];
1501 let expr = Expr::new(ExprKind::Block(exprs), Default::default());
1502 let result = formatter.format(&expr).unwrap();
1503 assert!(!result.is_empty());
1506 }
1507
1508 #[test]
1509 fn test_format_with_spaces() {
1510 let mut formatter = Formatter::new();
1511 formatter.config.use_tabs = false;
1512 formatter.config.indent_width = 2;
1513 let exprs = vec![create_simple_literal(1)];
1514 let expr = Expr::new(ExprKind::Block(exprs), Default::default());
1515 let result = formatter.format(&expr).unwrap();
1516 assert!(!result.is_empty());
1519 }
1520
1521 #[test]
1522 fn test_format_nested_expressions() {
1523 let formatter = Formatter::new();
1524 let inner = Expr::new(
1525 ExprKind::Binary {
1526 left: Box::new(create_simple_literal(1)),
1527 op: BinaryOp::Add,
1528 right: Box::new(create_simple_literal(2)),
1529 },
1530 Default::default(),
1531 );
1532 let outer = Expr::new(
1533 ExprKind::Binary {
1534 left: Box::new(inner),
1535 op: BinaryOp::Multiply,
1536 right: Box::new(create_simple_literal(3)),
1537 },
1538 Default::default(),
1539 );
1540 let result = formatter.format(&outer).unwrap();
1541 assert!(result.contains("1 + 2"));
1543 assert!(result.contains("* 3"));
1544 }
1545
1546 #[test]
1547 fn test_format_multiple_params() {
1548 let formatter = Formatter::new();
1549 let body = create_simple_literal(0);
1550 let param1 = Param {
1551 pattern: Pattern::Identifier("x".to_string()),
1552 ty: Type {
1553 kind: TypeKind::Named("Int".to_string()),
1554 span: Default::default(),
1555 },
1556 span: Default::default(),
1557 is_mutable: false,
1558 default_value: None,
1559 };
1560 let param2 = Param {
1561 pattern: Pattern::Identifier("y".to_string()),
1562 ty: Type {
1563 kind: TypeKind::Named("Float".to_string()),
1564 span: Default::default(),
1565 },
1566 span: Default::default(),
1567 is_mutable: false,
1568 default_value: None,
1569 };
1570 let expr = Expr::new(
1571 ExprKind::Function {
1572 name: "test".to_string(),
1573 type_params: vec![],
1574 params: vec![param1, param2],
1575 return_type: None,
1576 body: Box::new(body),
1577 is_async: false,
1578 is_pub: false,
1579 },
1580 Default::default(),
1581 );
1582 let result = formatter.format(&expr).unwrap();
1583 assert!(result.contains("x: Int, y: Float"));
1584 }
1585
1586 #[test]
1587 fn test_format_empty_block() {
1588 let formatter = Formatter::new();
1589 let expr = Expr::new(ExprKind::Block(vec![]), Default::default());
1590 let result = formatter.format(&expr);
1591 assert!(result.is_ok());
1593 }
1594
1595 #[test]
1596 fn test_format_string_with_quotes() {
1597 let formatter = Formatter::new();
1598 let expr = Expr::new(
1599 ExprKind::Literal(Literal::String("hello \"world\"".to_string())),
1600 Default::default(),
1601 );
1602 let result = formatter.format(&expr).unwrap();
1603 assert_eq!(result, "\"hello \\\"world\\\"\"");
1604 }
1605
1606 #[test]
1607 fn test_format_special_characters() {
1608 let formatter = Formatter::new();
1609 let expr = Expr::new(ExprKind::Literal(Literal::Char('\n')), Default::default());
1610 let result = formatter.format(&expr).unwrap();
1611 assert_eq!(result, "'\n'");
1612 }
1613
1614 #[test]
1615 fn test_format_fallback_case() {
1616 let formatter = Formatter::new();
1617 let expr = Expr::new(
1619 ExprKind::StringInterpolation { parts: vec![] },
1620 Default::default(),
1621 );
1622 let result = formatter.format(&expr).unwrap();
1623 assert!(!result.is_empty());
1625 }
1626
1627 #[test]
1628 fn test_formatter_field_access() {
1629 let formatter = Formatter::new();
1630 assert_eq!(formatter.config.indent_width, 4);
1631 assert!(!formatter.config.use_tabs);
1632 }
1633
1634 #[test]
1635 fn test_format_deeply_nested_block() {
1636 let formatter = Formatter::new();
1637 let inner_block = Expr::new(
1638 ExprKind::Block(vec![create_simple_literal(1)]),
1639 Default::default(),
1640 );
1641 let outer_block = Expr::new(ExprKind::Block(vec![inner_block]), Default::default());
1642 let result = formatter.format(&outer_block).unwrap();
1643 assert!(!result.is_empty());
1645 }
1646}
1647
1648#[cfg(test)]
1649mod property_tests_formatter {
1650 use proptest::proptest;
1651
1652 proptest! {
1653 #[test]
1655 fn test_new_never_panics(input: String) {
1656 let _input = if input.len() > 100 { &input[..100] } else { &input[..] };
1658 let _ = std::panic::catch_unwind(|| {
1660 });
1663 }
1664 }
1665}