codesearch 0.1.9

A fast, intelligent CLI tool with multiple search modes (regex, fuzzy, semantic), code analysis, and dead code detection for popular programming languages
Documentation
//! Analysis Command Handlers
//!
//! Handles all code analysis CLI commands.

use crate::{analysis, complexity, deadcode};
use serde_json;
use std::path::Path;

/// Handle the analyze command
///
/// Performs comprehensive codebase analysis including file counts,
/// language detection, and code patterns.
///
/// # Arguments
///
/// * `path` - The directory to analyze
/// * `extensions` - Optional file extensions to filter by
/// * `exclude` - Optional directories to exclude
/// * `with_metrics` - Whether to show additional metrics
/// * `format` - Output format (text/json)
///
/// # Examples
///
/// ```no_run
/// use codesearch::commands::analysis::handle_analyze_command;
/// use std::path::Path;
///
/// handle_analyze_command(Path::new("src"), None, None, false, "text").unwrap();
/// ```
pub fn handle_analyze_command(
    path: &Path,
    extensions: Option<&[String]>,
    exclude: Option<&[String]>,
    with_metrics: bool,
    format: &str,
) -> Result<(), Box<dyn std::error::Error>> {
    analysis::analyze_codebase(path, extensions, exclude)?;

    if with_metrics {
        use crate::codemetrics::{analyze_project_metrics, print_metrics_report};
        let project_metrics = analyze_project_metrics(path, extensions, exclude)?;

        if format == "json" {
            println!("{}", serde_json::to_string_pretty(&project_metrics)?);
        } else {
            print_metrics_report(&project_metrics, false);
        }
    }

    Ok(())
}

/// Handle the complexity command
///
/// Analyzes code complexity metrics including cyclomatic and cognitive complexity.
///
/// # Arguments
///
/// * `path` - The directory to analyze
/// * `extensions` - Optional file extensions to filter by
/// * `exclude` - Optional directories to exclude
/// * `threshold` - Minimum complexity threshold to report (optional)
/// * `sort` - Whether to sort results by complexity
///
/// # Examples
///
/// ```no_run
/// use codesearch::commands::analysis::handle_complexity_command;
/// use std::path::Path;
///
/// handle_complexity_command(Path::new("src"), None, None, Some(10), true).unwrap();
/// ```
pub fn handle_complexity_command(
    path: &Path,
    extensions: Option<&[String]>,
    exclude: Option<&[String]>,
    threshold: Option<u32>,
    sort: bool,
) -> Result<(), Box<dyn std::error::Error>> {
    complexity::analyze_complexity(path, extensions, exclude, threshold, sort)?;
    Ok(())
}

/// Handle the deadcode command
///
/// Detects potential dead code including unused variables, unreachable code,
/// empty functions, and TODO markers.
///
/// # Arguments
///
/// * `path` - The directory to analyze
/// * `extensions` - Optional file extensions to filter by
/// * `exclude` - Optional directories to exclude
///
/// # Examples
///
/// ```no_run
/// use codesearch::commands::analysis::handle_deadcode_command;
/// use std::path::Path;
///
/// handle_deadcode_command(Path::new("src"), Some(&[String::from("rs")]), None).unwrap();
/// ```
pub fn handle_deadcode_command(
    path: &Path,
    extensions: Option<&[String]>,
    exclude: Option<&[String]>,
) -> Result<(), Box<dyn std::error::Error>> {
    deadcode::detect_dead_code(path, extensions, exclude)?;
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;
    use tempfile::tempdir;

    #[test]
    fn test_handle_analyze_command() {
        let dir = tempdir().unwrap();
        fs::write(dir.path().join("test.rs"), "fn test() {}").unwrap();

        let result = handle_analyze_command(dir.path(), None, None, false, "text");
        assert!(result.is_ok());
    }

    #[test]
    fn test_handle_complexity_command() {
        let dir = tempdir().unwrap();
        fs::write(dir.path().join("test.rs"), "fn test() { if true { } }").unwrap();

        let result = handle_complexity_command(dir.path(), None, None, Some(1), false);
        assert!(result.is_ok());
    }

    #[test]
    fn test_handle_deadcode_command() {
        let dir = tempdir().unwrap();
        fs::write(dir.path().join("test.rs"), "fn test() { let x = 1; }").unwrap();

        let result = handle_deadcode_command(dir.path(), None, None);
        assert!(result.is_ok());
    }
}