use anyhow::Result;
use async_trait::async_trait;
use std::path::Path;
use std::sync::Arc;
use crate::ast::core::{AstDag, Language, UnifiedAstNode};
pub mod c_cpp;
pub mod others;
pub mod python;
pub mod rust;
pub mod typescript;
#[async_trait]
pub trait LanguageStrategy: Send + Sync {
fn language(&self) -> Language;
fn can_parse(&self, path: &Path) -> bool;
async fn parse_file(&self, path: &Path, content: &str) -> Result<AstDag>;
fn extract_imports(&self, ast: &AstDag) -> Vec<String>;
fn extract_functions(&self, ast: &AstDag) -> Vec<UnifiedAstNode>;
fn extract_types(&self, ast: &AstDag) -> Vec<UnifiedAstNode>;
fn calculate_complexity(&self, ast: &AstDag) -> (u32, u32); }
pub struct LanguageRegistry {
strategies: Vec<Arc<dyn LanguageStrategy>>,
}
impl LanguageRegistry {
#[must_use]
pub fn new() -> Self {
let strategies: Vec<Arc<dyn LanguageStrategy>> = vec![
Arc::new(rust::RustStrategy::new()),
Arc::new(python::PythonStrategy::new()),
Arc::new(typescript::TypeScriptStrategy::new()),
Arc::new(typescript::JavaScriptStrategy::new()),
Arc::new(c_cpp::CStrategy::new()),
Arc::new(c_cpp::CppStrategy::new()),
];
Self { strategies }
}
pub fn register(&mut self, strategy: Arc<dyn LanguageStrategy>) {
self.strategies.push(strategy);
}
#[must_use]
pub fn find_strategy(&self, path: &Path) -> Option<Arc<dyn LanguageStrategy>> {
self.strategies.iter().find(|s| s.can_parse(path)).cloned()
}
#[must_use]
pub fn get_strategy(&self, language: Language) -> Option<Arc<dyn LanguageStrategy>> {
self.strategies
.iter()
.find(|s| s.language() == language)
.cloned()
}
}
impl Default for LanguageRegistry {
fn default() -> Self {
Self::new()
}
}