cargo_quality/
formatter.rs1use std::process::Command;
5
6use masterror::AppResult;
7
8use crate::error::IoError;
9
10#[derive(Debug, Clone)]
17pub struct RustfmtConfig {
18 pub trailing_comma: &'static str,
19 pub brace_style: &'static str,
20 pub struct_field_align_threshold: u32,
21 pub wrap_comments: bool,
22 pub format_code_in_doc_comments: bool,
23 pub struct_lit_single_line: bool,
24 pub max_width: u32,
25 pub imports_granularity: &'static str,
26 pub group_imports: &'static str,
27 pub reorder_imports: bool,
28 pub unstable_features: bool
29}
30
31impl Default for RustfmtConfig {
32 fn default() -> Self {
46 Self {
47 trailing_comma: "Never",
48 brace_style: "SameLineWhere",
49 struct_field_align_threshold: 20,
50 wrap_comments: true,
51 format_code_in_doc_comments: true,
52 struct_lit_single_line: false,
53 max_width: 99,
54 imports_granularity: "Crate",
55 group_imports: "StdExternalCrate",
56 reorder_imports: true,
57 unstable_features: true
58 }
59 }
60}
61
62impl RustfmtConfig {
63 pub fn to_args(&self) -> Vec<String> {
82 vec![
83 "--config".to_string(),
84 format!("trailing_comma={}", self.trailing_comma),
85 "--config".to_string(),
86 format!("brace_style={}", self.brace_style),
87 "--config".to_string(),
88 format!(
89 "struct_field_align_threshold={}",
90 self.struct_field_align_threshold
91 ),
92 "--config".to_string(),
93 format!("wrap_comments={}", self.wrap_comments),
94 "--config".to_string(),
95 format!(
96 "format_code_in_doc_comments={}",
97 self.format_code_in_doc_comments
98 ),
99 "--config".to_string(),
100 format!("struct_lit_single_line={}", self.struct_lit_single_line),
101 "--config".to_string(),
102 format!("max_width={}", self.max_width),
103 "--config".to_string(),
104 format!("imports_granularity={}", self.imports_granularity),
105 "--config".to_string(),
106 format!("group_imports={}", self.group_imports),
107 "--config".to_string(),
108 format!("reorder_imports={}", self.reorder_imports),
109 "--config".to_string(),
110 format!("unstable_features={}", self.unstable_features),
111 ]
112 }
113}
114
115pub fn format_code() -> AppResult<()> {
132 let config = RustfmtConfig::default();
133 let args = config.to_args();
134
135 let mut command = Command::new("cargo");
136 command.arg("+nightly").arg("fmt").arg("--");
137
138 for arg in args {
139 command.arg(arg);
140 }
141
142 let status = command.status().map_err(IoError::from)?;
143
144 if status.success() {
145 println!("Code formatted successfully");
146 Ok(())
147 } else {
148 Err(IoError::from(std::io::Error::other(format!(
149 "cargo fmt failed with status: {}",
150 status
151 )))
152 .into())
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn test_default_config() {
162 let config = RustfmtConfig::default();
163 assert_eq!(config.max_width, 99);
164 assert_eq!(config.trailing_comma, "Never");
165 assert_eq!(config.brace_style, "SameLineWhere");
166 assert_eq!(config.imports_granularity, "Crate");
167 assert_eq!(config.group_imports, "StdExternalCrate");
168 assert!(config.wrap_comments);
169 assert!(config.format_code_in_doc_comments);
170 assert!(!config.struct_lit_single_line);
171 assert!(config.reorder_imports);
172 assert!(config.unstable_features);
173 }
174
175 #[test]
176 fn test_config_to_args() {
177 let config = RustfmtConfig::default();
178 let args = config.to_args();
179
180 assert!(args.contains(&"--config".to_string()));
181 assert!(args.contains(&"max_width=99".to_string()));
182 assert!(args.contains(&"trailing_comma=Never".to_string()));
183 assert!(args.contains(&"brace_style=SameLineWhere".to_string()));
184 assert!(args.contains(&"imports_granularity=Crate".to_string()));
185 assert!(args.contains(&"group_imports=StdExternalCrate".to_string()));
186 }
187
188 #[test]
189 fn test_config_to_args_count() {
190 let config = RustfmtConfig::default();
191 let args = config.to_args();
192 assert_eq!(args.len(), 22);
193 }
194
195 #[test]
196 fn test_config_to_args_pairs() {
197 let config = RustfmtConfig::default();
198 let args = config.to_args();
199
200 for i in (0..args.len()).step_by(2) {
201 assert_eq!(args[i], "--config");
202 assert!(args[i + 1].contains('='));
203 }
204 }
205
206 #[test]
207 fn test_format_code_execution() {
208 let result = format_code();
209 assert!(result.is_ok() || result.is_err());
210 }
211}