Coverage Report

Created: 2025-09-05 15:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/noah/src/ruchy/src/quality/formatter.rs
Line
Count
Source
1
// Code formatter for Ruchy
2
// Toyota Way: Consistent code style prevents defects
3
4
use anyhow::Result;
5
use crate::frontend::ast::{Expr, ExprKind};
6
7
pub struct Formatter {
8
    indent_width: usize,
9
    use_tabs: bool,
10
    _line_width: usize,
11
}
12
13
impl Formatter {
14
0
    pub fn new() -> Self {
15
0
        Self {
16
0
            indent_width: 4,
17
0
            use_tabs: false,
18
0
            _line_width: 100,
19
0
        }
20
0
    }
21
    
22
0
    pub fn format(&self, ast: &Expr) -> Result<String> {
23
        // Simple formatter that converts AST back to source
24
0
        Ok(self.format_expr(ast, 0))
25
0
    }
26
    
27
0
    fn format_type(&self, ty_kind: &crate::frontend::ast::TypeKind) -> String {
28
0
        match ty_kind {
29
0
            crate::frontend::ast::TypeKind::Named(name) => name.clone(),
30
0
            _ => format!("{ty_kind:?}"),
31
        }
32
0
    }
33
    
34
0
    fn format_expr(&self, expr: &Expr, indent: usize) -> String {
35
0
        let indent_str = if self.use_tabs {
36
0
            "\t".repeat(indent)
37
        } else {
38
0
            " ".repeat(indent * self.indent_width)
39
        };
40
        
41
0
        match &expr.kind {
42
0
            ExprKind::Literal(lit) => match lit {
43
0
                crate::frontend::ast::Literal::Integer(n) => n.to_string(),
44
0
                crate::frontend::ast::Literal::Float(f) => f.to_string(),
45
0
                crate::frontend::ast::Literal::String(s) => format!("\"{s}\""),
46
0
                crate::frontend::ast::Literal::Bool(b) => b.to_string(),
47
0
                crate::frontend::ast::Literal::Char(c) => format!("'{c}'"),
48
0
                crate::frontend::ast::Literal::Unit => "()".to_string(),
49
            },
50
0
            ExprKind::Identifier(name) => name.clone(),
51
0
            ExprKind::Let { name, value, body, .. } => {
52
0
                format!(
53
0
                    "let {} = {} in {}",
54
                    name,
55
0
                    self.format_expr(value, indent),
56
0
                    self.format_expr(body, indent)
57
                )
58
            }
59
0
            ExprKind::Binary { left, op, right } => {
60
0
                format!(
61
0
                    "{} {} {}",
62
0
                    self.format_expr(left, indent),
63
                    op,
64
0
                    self.format_expr(right, indent)
65
                )
66
            }
67
0
            ExprKind::Block(exprs) => {
68
0
                let mut result = String::from("{\n");
69
0
                for expr in exprs {
70
0
                    result.push_str(&format!(
71
0
                        "{}{}\n",
72
0
                        indent_str,
73
0
                        self.format_expr(expr, indent + 1)
74
0
                    ));
75
0
                }
76
0
                result.push_str(&format!("{indent_str}}}"));
77
0
                result
78
            }
79
0
            ExprKind::Function { name, params, return_type, body, .. } => {
80
0
                let mut result = format!("fun {name}");
81
                
82
                // Parameters
83
0
                result.push('(');
84
0
                for (i, param) in params.iter().enumerate() {
85
0
                    if i > 0 { result.push_str(", "); }
86
0
                    if let crate::frontend::ast::Pattern::Identifier(param_name) = &param.pattern {
87
0
                        result.push_str(param_name);
88
0
                        result.push_str(": ");
89
0
                        result.push_str(&self.format_type(&param.ty.kind));
90
0
                    }
91
                }
92
0
                result.push(')');
93
                
94
                // Return type
95
0
                if let Some(ret_ty) = return_type {
96
0
                    result.push_str(" -> ");
97
0
                    result.push_str(&self.format_type(&ret_ty.kind));
98
0
                }
99
                
100
0
                result.push(' ');
101
0
                result.push_str(&self.format_expr(body.as_ref(), indent));
102
0
                result
103
            }
104
0
            ExprKind::If { condition, then_branch, else_branch } => {
105
0
                let mut result = "if ".to_string();
106
0
                result.push_str(&self.format_expr(condition, indent));
107
0
                result.push(' ');
108
0
                result.push_str(&self.format_expr(then_branch, indent));
109
0
                if let Some(else_expr) = else_branch {
110
0
                    result.push_str(" else ");
111
0
                    result.push_str(&self.format_expr(else_expr, indent));
112
0
                }
113
0
                result
114
            }
115
            _ => {
116
0
                format!("{:?}", expr.kind) // Fallback for unimplemented cases
117
            }
118
        }
119
0
    }
120
}
121
122
impl Default for Formatter {
123
0
    fn default() -> Self {
124
0
        Self::new()
125
0
    }
126
}