Skip to main content

garbage_code_hunter/debt_invoice/
mod.rs

1//! Technical Debt Invoice — estimate the cost of your code's problems.
2
3pub mod cost_model;
4pub mod display;
5
6use crate::analyzer::CodeAnalyzer;
7use crate::common::OutputFormat;
8use anyhow::Result;
9use std::path::Path;
10
11/// Run the debt invoice analysis on a path.
12pub 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    // Count total lines
17    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}