use std::path::Path;
use crate::types::code::{CodeComplexity, Dependency, InterfaceInfo};
pub trait LanguageProcessor: Send + Sync + std::fmt::Debug {
fn supported_extensions(&self) -> Vec<&'static str>;
fn extract_dependencies(&self, content: &str, file_path: &Path) -> Vec<Dependency>;
#[allow(dead_code)]
fn determine_component_type(&self, file_path: &Path, content: &str) -> String;
fn is_important_line(&self, line: &str) -> bool;
#[allow(dead_code)]
fn language_name(&self) -> &'static str;
fn extract_interfaces(&self, content: &str, file_path: &Path) -> Vec<InterfaceInfo>;
}
#[derive(Debug)]
pub struct LanguageProcessorManager {
processors: Vec<Box<dyn LanguageProcessor>>,
}
impl Clone for LanguageProcessorManager {
fn clone(&self) -> Self {
Self::new()
}
}
impl LanguageProcessorManager {
pub fn new() -> Self {
Self {
processors: vec![
Box::new(rust::RustProcessor::new()),
Box::new(javascript::JavaScriptProcessor::new()),
Box::new(typescript::TypeScriptProcessor::new()),
Box::new(react::ReactProcessor::new()),
Box::new(vue::VueProcessor::new()),
Box::new(svelte::SvelteProcessor::new()),
Box::new(kotlin::KotlinProcessor::new()),
Box::new(python::PythonProcessor::new()),
Box::new(java::JavaProcessor::new()),
],
}
}
pub fn get_processor(&self, file_path: &Path) -> Option<&dyn LanguageProcessor> {
let extension = file_path.extension()?.to_str()?;
for processor in &self.processors {
if processor.supported_extensions().contains(&extension) {
return Some(processor.as_ref());
}
}
None
}
pub fn extract_dependencies(&self, file_path: &Path, content: &str) -> Vec<Dependency> {
if let Some(processor) = self.get_processor(file_path) {
processor.extract_dependencies(content, file_path)
} else {
Vec::new()
}
}
#[allow(dead_code)]
pub fn determine_component_type(&self, file_path: &Path, content: &str) -> String {
if let Some(processor) = self.get_processor(file_path) {
processor.determine_component_type(file_path, content)
} else {
"unknown".to_string()
}
}
pub fn is_important_line(&self, file_path: &Path, line: &str) -> bool {
if let Some(processor) = self.get_processor(file_path) {
processor.is_important_line(line)
} else {
false
}
}
pub fn extract_interfaces(&self, file_path: &Path, content: &str) -> Vec<InterfaceInfo> {
if let Some(processor) = self.get_processor(file_path) {
processor.extract_interfaces(content, file_path)
} else {
Vec::new()
}
}
pub fn calculate_complexity_metrics(&self, content: &str) -> CodeComplexity {
let lines: Vec<&str> = content.lines().collect();
let lines_of_code = lines.len();
let number_of_functions = content.matches("fn ").count()
+ content.matches("def ").count()
+ content.matches("function ").count();
let number_of_classes =
content.matches("class ").count() + content.matches("struct ").count();
let cyclomatic_complexity = 1.0
+ content.matches("if ").count() as f64
+ content.matches("while ").count() as f64
+ content.matches("for ").count() as f64
+ content.matches("match ").count() as f64
+ content.matches("case ").count() as f64;
CodeComplexity {
cyclomatic_complexity,
lines_of_code,
number_of_functions,
number_of_classes,
depth_of_inheritance: 0, coupling_factor: 0.5, cohesion_score: 0.7, }
}
}
pub mod java;
pub mod javascript;
pub mod kotlin;
pub mod python;
pub mod react;
pub mod rust;
pub mod svelte;
pub mod typescript;
pub mod vue;