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