Skip to main content

scope_engine/language/
mod.rs

1pub mod c;
2pub mod cpp;
3pub mod go;
4pub mod java;
5pub mod php;
6pub mod python;
7pub mod ruby;
8pub mod rust;
9pub mod typescript;
10
11use tree_sitter::{Language, Parser};
12
13/// Language-specific queries for tree-sitter symbol extraction.
14/// Each language provides patterns for finding definitions and references.
15/// Language-specific queries for tree-sitter symbol extraction.
16/// Each language provides patterns for finding definitions and references.
17pub struct LanguageQueries {
18    pub definitions: &'static str,
19    pub references: &'static str,
20}
21
22pub trait LanguageAdapter: Send + Sync {
23    fn language_name(&self) -> &'static str;
24    fn extensions(&self) -> &[&'static str];
25    fn language(&self) -> Language;
26    fn queries(&self) -> LanguageQueries;
27    fn parser(&self) -> Parser {
28        let mut p = Parser::new();
29        p.set_language(&self.language())
30            .expect("tree-sitter language init failed");
31        p
32    }
33}
34
35use std::collections::HashMap;
36
37pub struct LanguageRegistry {
38    adapters: Vec<Box<dyn LanguageAdapter>>,
39    by_ext: HashMap<String, usize>,
40}
41
42impl LanguageRegistry {
43    pub fn new() -> Self {
44        let mut r = Self {
45            adapters: Vec::new(),
46            by_ext: HashMap::new(),
47        };
48        r.register(Box::new(rust::RustAdapter::new()));
49        r.register(Box::new(python::PythonAdapter::new()));
50        r.register(Box::new(go::GoAdapter::new()));
51        r.register(Box::new(typescript::TypeScriptAdapter::new()));
52        r.register(Box::new(typescript::TsxAdapter::new()));
53        r.register(Box::new(typescript::JavaScriptAdapter::new()));
54        r.register(Box::new(java::JavaAdapter::new()));
55        r.register(Box::new(c::CAdapter::new()));
56        r.register(Box::new(cpp::CppAdapter::new()));
57        r.register(Box::new(ruby::RubyAdapter::new()));
58        r.register(Box::new(php::PhpAdapter::new()));
59        r
60    }
61
62    pub fn register(&mut self, adapter: Box<dyn LanguageAdapter>) {
63        let idx = self.adapters.len();
64        for ext in adapter.extensions() {
65            self.by_ext.insert(ext.to_string(), idx);
66        }
67        self.adapters.push(adapter);
68    }
69
70    pub fn get(&self, ext: &str) -> Option<&dyn LanguageAdapter> {
71        let idx = self.by_ext.get(ext)?;
72        Some(self.adapters[*idx].as_ref())
73    }
74
75    /// Return a list of (language_name, extensions) for all registered adapters.
76    pub fn list_languages(&self) -> Vec<(&str, &[&str])> {
77        self.adapters
78            .iter()
79            .map(|a| (a.language_name(), a.extensions()))
80            .collect()
81    }
82}
83
84impl Default for LanguageRegistry {
85    fn default() -> Self {
86        Self::new()
87    }
88}