uncomment 3.0.0

A CLI tool to remove comments from code using tree-sitter for accurate parsing
Documentation
use anyhow::{Context, Result};
use std::path::Path;
use std::time::{Duration, Instant};

pub struct BenchmarkResult {
    pub total_files: usize,
    pub processed_files: usize,
    pub modified_files: usize,
    pub total_comments_removed: usize,
    pub duration: Duration,
    pub files_per_second: f64,
    pub comments_per_second: f64,
}

impl BenchmarkResult {
    pub fn print_summary(&self) {
        println!("\n🚀 BENCHMARK RESULTS");
        println!("==================");
        println!("📊 Files:");
        println!("  • Total found: {}", self.total_files);
        println!("  • Processed: {}", self.processed_files);
        println!("  • Modified: {}", self.modified_files);
        println!(
            "  • Modification rate: {:.1}%",
            (self.modified_files as f64 / self.processed_files as f64) * 100.0
        );

        println!("\n💬 Comments:");
        println!("  • Total removed: {}", self.total_comments_removed);
        println!(
            "  • Avg per file: {:.1}",
            self.total_comments_removed as f64 / self.processed_files as f64
        );

        println!("\n⚡ Performance:");
        println!("  • Duration: {:.2}s", self.duration.as_secs_f64());
        println!("  • Files/sec: {:.1}", self.files_per_second);
        println!("  • Comments/sec: {:.1}", self.comments_per_second);

        println!("\n📈 Throughput:");
        if self.duration.as_secs() > 0 {
            let mb_per_sec =
                (self.processed_files as f64 * 5.0) / 1024.0 / self.duration.as_secs_f64();
            println!("  • Est. ~{mb_per_sec:.1} MB/sec");
        }
    }
}

pub fn run_benchmark(
    uncomment_binary: &Path,
    target_dir: &Path,
    threads: usize,
) -> Result<BenchmarkResult> {
    let start_time = Instant::now();

    println!("🔍 Starting uncomment benchmark...");
    println!("📁 Target: {}", target_dir.display());

    let mut cmd = std::process::Command::new(uncomment_binary);
    cmd.arg(target_dir).arg("--dry-run").arg("--verbose");

    if threads > 0 {
        cmd.arg("--threads").arg(threads.to_string());
    }

    println!("🚀 Running benchmark...\n");

    let output = cmd
        .output()
        .context("failed to execute benchmark command")?;
    let duration = start_time.elapsed();

    if !output.status.success() {
        anyhow::bail!(
            "benchmark command failed: {}",
            String::from_utf8_lossy(&output.stderr)
        );
    }

    let stdout = String::from_utf8_lossy(&output.stdout);

    let mut total_files = 0;
    let mut processed_files = 0;
    let mut modified_files = 0;
    let mut total_comments_removed = 0;

    for line in stdout.lines() {
        if line.contains("[DRY RUN] Would modify:") {
            modified_files += 1;
            processed_files += 1;
        } else if line.contains("✓ No changes needed:") {
            processed_files += 1;
        } else if line.contains("Removed")
            && line.contains("comment(s)")
            && let Some(parts) = line.split("Removed ").nth(1)
            && let Some(count_str) = parts.split(" comment").next()
            && let Ok(count) = count_str.trim().parse::<usize>()
        {
            total_comments_removed += count;
        }
    }

    for line in stdout.lines() {
        if line.contains("Summary:")
            && line.contains("files processed")
            && let Some(summary_part) = line.split("Summary: ").nth(1)
        {
            if let Some(files_part) = summary_part.split(" files processed").next()
                && let Ok(count) = files_part.trim().parse::<usize>()
            {
                total_files = count;
                processed_files = count;
            }

            if let Some(modified_part) = summary_part.split(", ").nth(1)
                && let Some(modified_str) = modified_part.split(' ').next()
                && let Ok(count) = modified_str.trim().parse::<usize>()
            {
                modified_files = count;
            }
        }
    }

    if total_files == 0 {
        total_files = processed_files;
    }

    let files_per_second = if duration.as_secs_f64() > 0.0 {
        processed_files as f64 / duration.as_secs_f64()
    } else {
        0.0
    };

    let comments_per_second = if duration.as_secs_f64() > 0.0 {
        total_comments_removed as f64 / duration.as_secs_f64()
    } else {
        0.0
    };

    Ok(BenchmarkResult {
        total_files,
        processed_files,
        modified_files,
        total_comments_removed,
        duration,
        files_per_second,
        comments_per_second,
    })
}