#![cfg_attr(coverage_nightly, coverage(off))]
use crate::ast::polyglot::{Language, NodeKind, PolyglotPathValidator, UnifiedNode};
use crate::services::context::AstItem;
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use std::collections::HashMap;
use std::path::Path;
use std::sync::Arc;
use tokio::fs;
#[async_trait]
pub trait LanguageMapper: Send + Sync {
fn language(&self) -> Language;
async fn map_file(&self, path: &Path) -> Result<Vec<UnifiedNode>>;
async fn map_directory(&self, path: &Path, recursive: bool) -> Result<Vec<UnifiedNode>>;
async fn map_source(&self, source: &str, path: &Path) -> Result<Vec<UnifiedNode>>;
fn convert_ast_items(&self, items: &[AstItem], path: &Path) -> Vec<UnifiedNode>;
fn clone_box(&self) -> Box<dyn LanguageMapper>;
fn create_test_node(&self, kind: NodeKind, name: &str) -> UnifiedNode {
UnifiedNode::new(kind, name, self.language())
}
}
pub struct LanguageMapperFactory;
impl LanguageMapperFactory {
pub fn create(language: Language) -> Result<Arc<dyn LanguageMapper>> {
match language {
Language::Java => Ok(Arc::new(JavaMapper::new())),
Language::Kotlin => Ok(Arc::new(KotlinMapper::new())),
Language::Scala => Ok(Arc::new(ScalaMapper::new())),
Language::TypeScript => Ok(Arc::new(TypeScriptMapper::new())),
Language::JavaScript => Ok(Arc::new(JavaScriptMapper::new())),
_ => Err(anyhow!("Unsupported language: {:?}", language)),
}
}
pub fn create_all() -> HashMap<Language, Arc<dyn LanguageMapper>> {
let mut mappers = HashMap::new();
for language in &[
Language::Java,
Language::Kotlin,
Language::Scala,
Language::TypeScript,
Language::JavaScript,
] {
if let Ok(mapper) = Self::create(*language) {
mappers.insert(*language, mapper);
}
}
mappers
}
pub fn create_for_file(path: &Path) -> Result<Arc<dyn LanguageMapper>> {
let language = Language::from_path(path)
.ok_or_else(|| anyhow!("Unsupported file type: {:?}", path))?;
Self::create(language)
}
}
#[derive(Clone)]
pub struct BaseLanguageMapper {
language: Language,
}
impl BaseLanguageMapper {
pub fn new(language: Language) -> Self {
Self { language }
}
}
include!("language_mapper_base.rs");
include!("language_mapper_jvm.rs");
include!("language_mapper_web.rs");
include!("language_mapper_misc.rs");
#[cfg(test)]
#[path = "language_mapper_tests.rs"]
mod tests;