cuenv_cubes/
formatter.rs

1//! Code formatting integration
2//!
3//! This module provides formatting capabilities for various programming languages.
4
5use crate::cube::FormatConfig;
6use crate::{CodegenError, Result};
7
8/// Language-specific code formatter
9#[derive(Debug)]
10pub struct Formatter;
11
12impl Formatter {
13    /// Create a new formatter
14    #[must_use]
15    pub const fn new() -> Self {
16        Self
17    }
18
19    /// Format code content based on language and configuration
20    ///
21    /// # Errors
22    ///
23    /// Returns an error if formatting fails
24    pub fn format(&self, content: &str, language: &str, config: &FormatConfig) -> Result<String> {
25        match language {
26            "json" => self.format_json(content, config),
27            "typescript" | "javascript" => {
28                // For now, return content as-is
29                // In a full implementation, we'd integrate with prettier or biome
30                Ok(content.to_string())
31            }
32            "rust" => {
33                // For now, return content as-is
34                // In a full implementation, we'd integrate with rustfmt
35                Ok(content.to_string())
36            }
37            _ => Ok(content.to_string()),
38        }
39    }
40
41    /// Format JSON content
42    #[allow(clippy::unused_self)] // Will use self for formatting state in future
43    fn format_json(&self, content: &str, config: &FormatConfig) -> Result<String> {
44        let value: serde_json::Value = serde_json::from_str(content)?;
45
46        let indent_size = config.indent_size.unwrap_or(2);
47        let indent_char = if config.indent == "tab" { '\t' } else { ' ' };
48
49        let formatted = if indent_char == '\t' {
50            serde_json::to_string_pretty(&value)?
51        } else {
52            let mut buf = Vec::new();
53            let indent = vec![b' '; indent_size];
54            let formatter = serde_json::ser::PrettyFormatter::with_indent(indent.as_slice());
55            let mut ser = serde_json::Serializer::with_formatter(&mut buf, formatter);
56            serde::Serialize::serialize(&value, &mut ser)
57                .map_err(|e| CodegenError::Formatting(e.to_string()))?;
58            String::from_utf8(buf).map_err(|e| CodegenError::Formatting(e.to_string()))?
59        };
60
61        Ok(formatted)
62    }
63}
64
65impl Default for Formatter {
66    fn default() -> Self {
67        Self::new()
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn test_format_json() {
77        let fmt = Formatter::new();
78        let input = r#"{"name":"test","value":123}"#;
79        let config = FormatConfig {
80            indent: "space".to_string(),
81            indent_size: Some(2),
82            ..Default::default()
83        };
84
85        let result = fmt.format(input, "json", &config);
86        assert!(result.is_ok());
87
88        let output = result.unwrap();
89        assert!(output.contains("  ")); // Should have 2-space indentation
90        assert!(output.contains("\"name\": \"test\""));
91    }
92
93    #[test]
94    fn test_format_unknown_language() {
95        let formatter = Formatter::new();
96        let input = "some content";
97        let config = FormatConfig::default();
98
99        let result = formatter.format(input, "unknown", &config);
100        assert!(result.is_ok());
101        assert_eq!(result.unwrap(), input);
102    }
103}