context_creator/core/semantic/
mod.rs

1//! Semantic analysis module for context-creator
2//!
3//! This module provides language-agnostic semantic analysis capabilities including:
4//! - Import/dependency tracing
5//! - Function call analysis
6//! - Type dependency tracking
7
8#![allow(clippy::new_without_default)]
9
10pub mod analyzer;
11pub mod cache;
12pub mod cycle_detector;
13pub mod dependency_types;
14pub mod graph_builder;
15pub mod graph_traverser;
16pub mod languages;
17pub mod parallel_analyzer;
18pub mod parser_pool;
19pub mod path_validator;
20pub mod query_engine;
21pub mod resolver;
22pub mod type_resolver;
23
24#[cfg(test)]
25mod rust_function_call_test;
26
27// Re-export commonly used types
28pub use cache::AstCacheV2;
29
30#[cfg(test)]
31mod javascript_test;
32#[cfg(test)]
33mod python_test;
34#[cfg(test)]
35mod test;
36
37pub use analyzer::{LanguageAnalyzer, SemanticContext, SemanticResult};
38pub use resolver::{ModuleResolver, ResolvedPath};
39
40use crate::utils::error::ContextCreatorError;
41use std::path::Path;
42
43/// Semantic analysis options
44#[derive(Debug, Clone)]
45pub struct SemanticOptions {
46    /// Enable import tracing
47    pub trace_imports: bool,
48    /// Include function callers
49    pub include_callers: bool,
50    /// Include type dependencies
51    pub include_types: bool,
52    /// Maximum depth for dependency traversal
53    pub semantic_depth: usize,
54}
55
56impl SemanticOptions {
57    /// Create SemanticOptions from CLI config
58    pub fn from_config(config: &crate::cli::Config) -> Self {
59        Self {
60            trace_imports: config.trace_imports,
61            include_callers: config.include_callers,
62            include_types: config.include_types,
63            semantic_depth: config.semantic_depth,
64        }
65    }
66
67    /// Check if any semantic analysis is enabled
68    pub fn is_enabled(&self) -> bool {
69        self.trace_imports || self.include_callers || self.include_types
70    }
71}
72
73/// Get the appropriate language analyzer for a file
74pub fn get_analyzer_for_file(
75    path: &Path,
76) -> Result<Option<Box<dyn LanguageAnalyzer>>, ContextCreatorError> {
77    let extension = path.extension().and_then(|ext| ext.to_str()).unwrap_or("");
78
79    let analyzer: Option<Box<dyn LanguageAnalyzer>> = match extension {
80        "rs" => Some(Box::new(languages::rust::RustAnalyzer::new())),
81        "py" => Some(Box::new(languages::python::PythonAnalyzer::new())),
82        "js" | "jsx" => Some(Box::new(languages::javascript::JavaScriptAnalyzer::new())),
83        "ts" | "tsx" => Some(Box::new(languages::typescript::TypeScriptAnalyzer::new())),
84        "go" => Some(Box::new(languages::go::GoAnalyzer::new())),
85        "java" => Some(Box::new(languages::java::JavaAnalyzer::new())),
86        "cpp" | "cc" | "cxx" | "hpp" | "h" => Some(Box::new(languages::cpp::CppAnalyzer::new())),
87        "c" => Some(Box::new(languages::c::CAnalyzer::new())),
88        "cs" => Some(Box::new(languages::csharp::CSharpAnalyzer::new())),
89        "rb" => Some(Box::new(languages::ruby::RubyAnalyzer::new())),
90        "php" => Some(Box::new(languages::php::PhpAnalyzer::new())),
91        "swift" => Some(Box::new(languages::swift::SwiftAnalyzer::new())),
92        "kt" | "kts" => Some(Box::new(languages::kotlin::KotlinAnalyzer::new())),
93        "scala" | "sc" => Some(Box::new(languages::scala::ScalaAnalyzer::new())),
94        "dart" => Some(Box::new(languages::dart::DartAnalyzer::new())),
95        "lua" => Some(Box::new(languages::lua::LuaAnalyzer::new())),
96        "r" | "R" => Some(Box::new(languages::r::RAnalyzer::new())),
97        "jl" => Some(Box::new(languages::julia::JuliaAnalyzer::new())),
98        "ex" | "exs" => Some(Box::new(languages::elixir::ElixirAnalyzer::new())),
99        "elm" => Some(Box::new(languages::elm::ElmAnalyzer::new())),
100        _ => None,
101    };
102
103    Ok(analyzer)
104}
105
106/// Get the appropriate module resolver for a file
107pub fn get_resolver_for_file(
108    path: &Path,
109) -> Result<Option<Box<dyn ModuleResolver>>, ContextCreatorError> {
110    let extension = path.extension().and_then(|ext| ext.to_str()).unwrap_or("");
111
112    let resolver: Option<Box<dyn ModuleResolver>> = match extension {
113        "rs" => Some(Box::new(languages::rust::RustModuleResolver)),
114        "py" => Some(Box::new(languages::python::PythonModuleResolver)),
115        "js" | "jsx" => Some(Box::new(languages::javascript::JavaScriptModuleResolver)),
116        "ts" | "tsx" => Some(Box::new(languages::typescript::TypeScriptModuleResolver)),
117        _ => None,
118    };
119
120    Ok(resolver)
121}