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
//! Search Module
//!
//! Core search functionality with parallel processing, fuzzy matching, and semantic search.

pub mod core;
pub mod engine;
pub mod fuzzy;
pub mod pure;
pub mod semantic;
pub mod utilities;

pub use core::{list_files, search_code};
pub use engine::DefaultSearchEngine;
pub use fuzzy::{calculate_relevance_score, search_in_file_parallel};
pub use semantic::enhance_query_semantically;
pub use utilities::{compare_with_grep, print_results, print_search_stats};

#[cfg(test)]
mod tests {
    use super::*;
    use crate::types::SearchOptions;
    use std::path::Path;

    #[test]
    fn test_enhance_query_semantically() {
        let enhanced = enhance_query_semantically("function");
        assert!(
            enhanced.contains("function") || enhanced.contains("def") || enhanced.contains("fn")
        );

        let enhanced = enhance_query_semantically("class");
        assert!(enhanced.contains("class") || enhanced.contains("struct"));
    }

    #[test]
    fn test_calculate_relevance_score() {
        let score = calculate_relevance_score(
            "fn test_function() {",
            "test",
            10,
            Path::new("test.rs"),
            false,
            None,
        );
        assert!(score > 0.0);
        assert!(score <= 100.0);
    }

    #[test]
    fn test_search_code_basic() {
        use std::fs;
        use tempfile::tempdir;

        let dir = tempdir().unwrap();
        let file_path = dir.path().join("test.rs");
        fs::write(&file_path, "fn test() {\n    println!(\"hello\");\n}").unwrap();

        let options = SearchOptions {
            extensions: Some(vec!["rs".to_string()]),
            ignore_case: true,
            fuzzy: false,
            fuzzy_threshold: 0.6,
            max_results: 10,
            exclude: None,
            rank: false,
            cache: false,
            semantic: false,
            benchmark: false,
            vs_grep: false,
        };
        let results = search_code("test", dir.path(), &options);

        assert!(results.is_ok());
        let results = results.unwrap();
        assert!(!results.is_empty());
    }

    #[test]
    fn test_list_files() {
        use std::fs;
        use tempfile::tempdir;

        let dir = tempdir().unwrap();
        fs::write(dir.path().join("test1.rs"), "test").unwrap();
        fs::write(dir.path().join("test2.py"), "test").unwrap();

        let files = list_files(dir.path(), Some(&["rs".to_string()]), None);
        assert!(files.is_ok());
        let files = files.unwrap();
        assert_eq!(files.len(), 1);
    }

    #[test]
    fn test_list_files_with_extension_filter() {
        use std::fs;
        use tempfile::tempdir;

        let dir = tempdir().unwrap();
        fs::write(dir.path().join("test1.rs"), "test").unwrap();
        fs::write(dir.path().join("test2.py"), "test").unwrap();

        let files = list_files(dir.path(), Some(&["rs".to_string()]), None);
        assert!(files.is_ok());
        let files = files.unwrap();
        assert_eq!(files.len(), 1);
    }

    #[test]
    fn test_list_files_nonexistent_directory() {
        use std::path::Path;

        let result = list_files(Path::new("/nonexistent/path"), None, None);
        assert!(result.is_err());
        // The error should mention the directory was not found
        let error_msg = result.unwrap_err().to_string();
        assert!(error_msg.contains("not found") || error_msg.contains("Directory"));
    }

    #[test]
    fn test_list_files_file_instead_of_directory() {
        use std::fs;
        use tempfile::tempdir;

        let dir = tempdir().unwrap();
        let file_path = dir.path().join("test.rs");
        fs::write(&file_path, "fn test() {}").unwrap();

        // Try to list files on a file path instead of directory
        let result = list_files(&file_path, None, None);
        assert!(result.is_err());
        let error_msg = result.unwrap_err().to_string();
        assert!(error_msg.contains("not a directory") || error_msg.contains("Invalid"));
    }

    #[test]
    fn test_search_code_with_invalid_regex() {
        use std::fs;
        use tempfile::tempdir;

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

        // Invalid regex pattern (unclosed bracket)
        let options = SearchOptions {
            extensions: Some(vec!["rs".to_string()]),
            ignore_case: false,
            fuzzy: false,
            fuzzy_threshold: 0.6,
            max_results: 10,
            exclude: None,
            rank: false,
            cache: false,
            semantic: false,
            benchmark: false,
            vs_grep: false,
        };

        let result = search_code("[invalid", dir.path(), &options);
        assert!(result.is_err());
        let error_msg = result.unwrap_err().to_string();
        assert!(error_msg.contains("Invalid regex") || error_msg.contains("Invalid pattern"));
    }

    #[test]
    fn test_search_code_with_extension_filter() {
        use std::fs;
        use tempfile::tempdir;

        let dir = tempdir().unwrap();
        fs::write(dir.path().join("test.rs"), "fn test() {}").unwrap();
        fs::write(dir.path().join("test.py"), "def test(): pass").unwrap();

        let options = SearchOptions {
            extensions: Some(vec!["rs".to_string()]),
            ignore_case: true,
            fuzzy: false,
            fuzzy_threshold: 0.6,
            max_results: 10,
            exclude: None,
            rank: false,
            cache: false,
            semantic: false,
            benchmark: false,
            vs_grep: false,
        };
        let results = search_code("test", dir.path(), &options);

        assert!(results.is_ok());
        let results = results.unwrap();
        assert_eq!(results.len(), 1);
    }
}