Skip to main content

reovim_driver_syntax/
lang_store.rs

1//! Language info store for module self-registration.
2//!
3//! This module provides [`LanguageInfoStore`], a registry where syntax modules
4//! can register their [`LanguageInfo`] metadata during `init()`. This follows
5//! the same pattern as [`SyntaxFactoryStore`], [`ModeInfoStore`], etc.
6//!
7//! # Self-Registration Pattern
8//!
9//! ```ignore
10//! // In treesitter-rust module's init():
11//! impl Module for TreesitterRustModule {
12//!     fn init(&mut self, ctx: &ModuleContext) -> ProbeResult {
13//!         let lang_store = ctx.services.get_or_create::<LanguageInfoStore>();
14//!         lang_store.add(
15//!             LanguageInfo::new("rust", "Rust")
16//!                 .with_extensions(["rs"])
17//!                 .with_mime_types(["text/x-rust"])
18//!                 .with_comments(CommentTokens::with_block("//", "/*", "*/"))
19//!         );
20//!         ProbeResult::Success
21//!     }
22//! }
23//! ```
24
25use {parking_lot::RwLock, reovim_kernel::api::v1::Service};
26
27use crate::LanguageInfo;
28
29/// Store for language info registered by modules during init.
30///
31/// Modules register their `LanguageInfo` here, and bootstrap extracts them
32/// to build a concrete `LanguageRegistry` after module initialization.
33#[derive(Default)]
34pub struct LanguageInfoStore {
35    entries: RwLock<Vec<LanguageInfo>>,
36}
37
38impl LanguageInfoStore {
39    /// Create a new empty store.
40    #[must_use]
41    pub fn new() -> Self {
42        Self::default()
43    }
44
45    /// Add language info to the store.
46    ///
47    /// Called by syntax modules during `init()`.
48    pub fn add(&self, info: LanguageInfo) {
49        self.entries.write().push(info);
50    }
51
52    /// Take all registered language info entries.
53    ///
54    /// Called by bootstrap after all modules have initialized.
55    /// This drains the store, so subsequent calls return empty vec.
56    pub fn take_all(&self) -> Vec<LanguageInfo> {
57        std::mem::take(&mut *self.entries.write())
58    }
59
60    /// Get the number of registered entries.
61    #[must_use]
62    pub fn len(&self) -> usize {
63        self.entries.read().len()
64    }
65
66    /// Check if no entries are registered.
67    #[must_use]
68    pub fn is_empty(&self) -> bool {
69        self.entries.read().is_empty()
70    }
71}
72
73impl Service for LanguageInfoStore {}
74
75impl std::fmt::Debug for LanguageInfoStore {
76    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77        f.debug_struct("LanguageInfoStore")
78            .field("count", &self.len())
79            .finish()
80    }
81}
82
83#[cfg(test)]
84#[path = "lang_store_tests.rs"]
85mod tests;