mod registry;
pub use registry::LanguageRegistry;
use anyhow::Result;
use serde::Deserialize;
use tree_sitter::{Language, Query};
use crate::model::{Relation, Symbol};
#[derive(Debug, Clone, Deserialize)]
pub struct CustomEdgeDef {
pub name: String,
pub capture: String,
}
pub trait CustomExtractor: Send + Sync {
fn extract(
&self,
path: &str,
source: &[u8],
language: &str,
) -> Result<(Vec<Symbol>, Vec<Relation>)>;
}
pub enum ParserBackend {
TreeSitter {
grammar: Language,
entity_query: Query,
relation_query: Query,
},
Custom(Box<dyn CustomExtractor>),
}
pub struct LanguagePack {
pub name: String,
pub extensions: Vec<String>,
pub backend: ParserBackend,
pub custom_edges: Vec<CustomEdgeDef>,
}
impl LanguagePack {
pub fn new(
name: &str,
extensions: Vec<&str>,
grammar: Language,
entity_query_src: &str,
relation_query_src: &str,
) -> Result<Self> {
let entity_query = Query::new(&grammar, entity_query_src)?;
let relation_query = Query::new(&grammar, relation_query_src)?;
Ok(Self {
name: name.to_string(),
extensions: extensions.into_iter().map(String::from).collect(),
backend: ParserBackend::TreeSitter {
grammar,
entity_query,
relation_query,
},
custom_edges: Vec::new(),
})
}
pub fn new_with_custom_edges(
name: &str,
extensions: Vec<&str>,
grammar: Language,
entity_query_src: &str,
relation_query_src: &str,
custom_edges: Vec<CustomEdgeDef>,
) -> Result<Self> {
let mut pack = Self::new(
name,
extensions,
grammar,
entity_query_src,
relation_query_src,
)?;
pack.custom_edges = custom_edges;
Ok(pack)
}
pub fn new_custom(
name: &str,
extensions: Vec<String>,
extractor: Box<dyn CustomExtractor>,
) -> Self {
Self {
name: name.to_string(),
extensions,
backend: ParserBackend::Custom(extractor),
custom_edges: Vec::new(),
}
}
}
impl std::fmt::Debug for LanguagePack {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LanguagePack")
.field("name", &self.name)
.field("extensions", &self.extensions)
.finish()
}
}