garbage_code_hunter/debt_invoice/
mod.rs1pub mod cost_model;
4pub mod display;
5
6use crate::analyzer::CodeAnalyzer;
7use crate::common::OutputFormat;
8use anyhow::Result;
9use std::path::Path;
10
11pub fn run(path: &Path, format: &OutputFormat, lang: &str) -> Result<String> {
13 let analyzer = CodeAnalyzer::new(&[], lang);
14 let issues = analyzer.analyze_path(path);
15
16 let total_lines = count_lines(path);
18 let invoice = cost_model::generate_invoice(&issues, total_lines);
19
20 let output = match format {
21 OutputFormat::Terminal => display::format_terminal(&invoice, lang),
22 OutputFormat::Json => display::format_json(&invoice),
23 };
24
25 Ok(output)
26}
27
28fn count_lines(path: &Path) -> usize {
29 if path.is_file() {
30 return std::fs::read_to_string(path)
31 .map(|c| c.lines().count())
32 .unwrap_or(0);
33 }
34
35 walkdir::WalkDir::new(path)
36 .into_iter()
37 .filter_map(|e| e.ok())
38 .filter(|e| e.path().extension().is_some_and(|ext| ext == "rs"))
39 .filter_map(|e| std::fs::read_to_string(e.path()).ok())
40 .map(|c| c.lines().count())
41 .sum()
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn test_run_on_current_dir() {
50 let result = run(std::path::Path::new("."), &OutputFormat::Terminal, "en-US");
51 assert!(result.is_ok());
52 }
53}