dk_engine/parser/
registry.rs1use super::engine::QueryDrivenParser;
2use super::lang_config::LanguageConfig;
3use super::langs;
4use super::LanguageParser;
5use dk_core::{FileAnalysis, Result};
6use std::collections::HashMap;
7use std::path::Path;
8use std::sync::Arc;
9
10pub struct ParserRegistry {
12 parsers: HashMap<String, Arc<dyn LanguageParser>>,
13}
14
15impl ParserRegistry {
16 pub fn new() -> Self {
18 let mut parsers: HashMap<String, Arc<dyn LanguageParser>> = HashMap::new();
19
20 let mut register = |config: Box<dyn LanguageConfig>| {
21 let exts: Vec<String> = config.extensions().iter().map(|s| s.to_string()).collect();
22 match QueryDrivenParser::new(config) {
23 Ok(parser) => {
24 let arc: Arc<dyn LanguageParser> = Arc::new(parser);
25 for ext in exts {
26 parsers.insert(ext, Arc::clone(&arc));
27 }
28 }
29 Err(e) => {
30 tracing::error!("Failed to initialize parser: {e}");
31 }
32 }
33 };
34
35 register(Box::new(langs::rust::RustConfig));
36 register(Box::new(langs::python::PythonConfig));
37 register(Box::new(langs::go::GoConfig));
38 register(Box::new(langs::java::JavaConfig));
39 register(Box::new(langs::cpp::CppConfig));
40 register(Box::new(langs::csharp::CSharpConfig));
41 register(Box::new(langs::ruby::RubyConfig));
42 register(Box::new(langs::php::PhpConfig));
43 register(Box::new(langs::swift::SwiftConfig));
44 register(Box::new(langs::scala::ScalaConfig));
45 register(Box::new(langs::haskell::HaskellConfig));
46 register(Box::new(langs::julia::JuliaConfig));
47 register(Box::new(langs::bash::BashConfig));
48 register(Box::new(langs::kotlin::KotlinConfig));
49
50 let ts_parser = langs::typescript::TypeScriptParser::new();
52 match ts_parser {
53 Ok(parser) => {
54 let arc: Arc<dyn LanguageParser> = Arc::new(parser);
55 for ext in ["ts", "tsx", "js", "jsx"] {
56 parsers.insert(ext.to_string(), Arc::clone(&arc));
57 }
58 }
59 Err(e) => {
60 tracing::error!("Failed to initialize TypeScript parser: {e}");
61 }
62 }
63
64 Self { parsers }
65 }
66
67 pub fn supports_file(&self, path: &Path) -> bool {
69 path.extension()
70 .and_then(|e| e.to_str())
71 .map(|ext| self.parsers.contains_key(ext))
72 .unwrap_or(false)
73 }
74
75 pub fn parse_file(&self, path: &Path, source: &[u8]) -> Result<FileAnalysis> {
77 let ext = path
78 .extension()
79 .and_then(|e| e.to_str())
80 .ok_or_else(|| dk_core::Error::UnsupportedLanguage("no extension".into()))?;
81
82 let parser = self
83 .parsers
84 .get(ext)
85 .ok_or_else(|| dk_core::Error::UnsupportedLanguage(ext.into()))?;
86
87 parser.parse_file(source, path)
88 }
89}
90
91impl Default for ParserRegistry {
92 fn default() -> Self {
93 Self::new()
94 }
95}