codesearch 0.1.15

A fast, intelligent CLI tool with multiple search modes (regex, fuzzy, semantic), code analysis, and dead code detection for popular programming languages
Documentation
//! Helper Functions for Code Metrics
//!
//! Provides utility functions for counting code elements and analyzing structure.
//!
//! Performance note: regex patterns are pre-compiled at startup using lazy_static
//! to avoid repeated compilation overhead during analysis.

use regex::Regex;
use std::collections::HashMap;

lazy_static::lazy_static! {
    // Pre-compiled class counting patterns by extension
    static ref CLASS_PATTERNS: HashMap<&'static str, Vec<Regex>> = {
        let mut map = HashMap::new();
        map.insert("rs", vec![
            Regex::new(r"struct\s+\w+").unwrap(),
            Regex::new(r"enum\s+\w+").unwrap(),
            Regex::new(r"trait\s+\w+").unwrap(),
        ]);
        map.insert("py", vec![
            Regex::new(r"class\s+\w+").unwrap(),
        ]);
        map.insert("java", vec![
            Regex::new(r"class\s+\w+").unwrap(),
            Regex::new(r"interface\s+\w+").unwrap(),
        ]);
        map.insert("kt", vec![
            Regex::new(r"class\s+\w+").unwrap(),
            Regex::new(r"interface\s+\w+").unwrap(),
        ]);
        map.insert("js", vec![
            Regex::new(r"class\s+\w+").unwrap(),
        ]);
        map.insert("ts", vec![
            Regex::new(r"class\s+\w+").unwrap(),
        ]);
        map.insert("go", vec![
            Regex::new(r"type\s+\w+\s+struct").unwrap(),
        ]);
        map
    };

    // Pre-compiled function counting patterns by extension
    static ref FUNCTION_PATTERNS: HashMap<&'static str, Vec<Regex>> = {
        let mut map = HashMap::new();
        map.insert("rs", vec![
            Regex::new(r"fn\s+\w+").unwrap(),
        ]);
        map.insert("py", vec![
            Regex::new(r"def\s+\w+").unwrap(),
        ]);
        map.insert("java", vec![
            Regex::new(r"(?:public|private|protected)?\s*\w+\s+\w+\s*\(").unwrap(),
        ]);
        map.insert("kt", vec![
            Regex::new(r"(?:public|private|protected)?\s*\w+\s+\w+\s*\(").unwrap(),
        ]);
        map.insert("js", vec![
            Regex::new(r"function\s+\w+").unwrap(),
            Regex::new(r"\w+\s*:\s*\([^)]*\)\s*=>").unwrap(),
        ]);
        map.insert("ts", vec![
            Regex::new(r"function\s+\w+").unwrap(),
            Regex::new(r"\w+\s*:\s*\([^)]*\)\s*=>").unwrap(),
        ]);
        map.insert("go", vec![
            Regex::new(r"func\s+\w+").unwrap(),
        ]);
        map
    };

    // Pre-compiled field counting patterns by extension
    static ref FIELD_PATTERNS: HashMap<&'static str, Vec<Regex>> = {
        let mut map = HashMap::new();
        map.insert("rs", vec![
            Regex::new(r"\w+:\s*\w+,").unwrap(),
        ]);
        map.insert("py", vec![
            Regex::new(r"self\.\w+\s*=").unwrap(),
        ]);
        map.insert("java", vec![
            Regex::new(r"(?:private|public|protected)\s+\w+\s+\w+;").unwrap(),
        ]);
        map.insert("kt", vec![
            Regex::new(r"(?:private|public|protected)\s+\w+\s+\w+;").unwrap(),
        ]);
        map.insert("js", vec![
            Regex::new(r"this\.\w+\s*=").unwrap(),
        ]);
        map.insert("ts", vec![
            Regex::new(r"this\.\w+\s*=").unwrap(),
        ]);
        map
    };
}

/// Count class/type definitions in content based on file extension
pub fn count_classes(content: &str, ext: &str) -> usize {
    CLASS_PATTERNS
        .get(ext)
        .map(|patterns| {
            patterns
                .iter()
                .map(|re| re.find_iter(content).count())
                .sum()
        })
        .unwrap_or(0)
}

/// Count function/method definitions in content based on file extension
pub fn count_functions(content: &str, ext: &str) -> usize {
    FUNCTION_PATTERNS
        .get(ext)
        .map(|patterns| {
            patterns
                .iter()
                .map(|re| re.find_iter(content).count())
                .sum()
        })
        .unwrap_or(0)
}

/// Count fields/attributes in content based on file extension
pub fn count_fields(content: &str, ext: &str) -> usize {
    let count = FIELD_PATTERNS
        .get(ext)
        .map(|patterns| {
            patterns
                .iter()
                .map(|re| re.find_iter(content).count())
                .sum()
        })
        .unwrap_or(1);
    count.max(1)
}

pub fn calculate_max_nesting(content: &str) -> usize {
    let mut max_depth = 0usize;
    let mut current_depth = 0usize;

    for ch in content.chars() {
        match ch {
            '{' | '(' | '[' => {
                current_depth += 1;
                max_depth = max_depth.max(current_depth);
            }
            '}' | ')' | ']' => {
                current_depth = current_depth.saturating_sub(1);
            }
            _ => {}
        }
    }

    max_depth
}