Skip to main content

reovim_driver_syntax/
store.rs

1//! Syntax factory store for module self-registration.
2//!
3//! This module provides `SyntaxFactoryStore`, a registry where syntax modules
4//! can register their factories during `init()`. This follows the same pattern
5//! as `ModeInfoStore`, `CommandHandlerStore`, 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 store = ctx.services.get_or_create::<SyntaxFactoryStore>();
14//!         store.add(Arc::new(RustSyntaxFactory::new()));
15//!         ProbeResult::Success
16//!     }
17//! }
18//! ```
19
20use std::sync::Arc;
21
22use {parking_lot::RwLock, reovim_kernel::api::v1::Service};
23
24use crate::SyntaxDriverFactory;
25
26/// Store for syntax driver factories registered by modules during init.
27///
28/// Similar to `ModeInfoStore`, `CommandHandlerStore`, etc.
29/// Modules register their factories here, and bootstrap extracts them
30/// after module initialization.
31#[derive(Default)]
32pub struct SyntaxFactoryStore {
33    /// Registered factories (populated during module init).
34    factories: RwLock<Vec<Arc<dyn SyntaxDriverFactory>>>,
35}
36
37impl SyntaxFactoryStore {
38    /// Create a new empty store.
39    #[must_use]
40    pub fn new() -> Self {
41        Self::default()
42    }
43
44    /// Add a factory to the store.
45    ///
46    /// Called by syntax modules during `init()`.
47    pub fn add(&self, factory: Arc<dyn SyntaxDriverFactory>) {
48        self.factories.write().push(factory);
49    }
50
51    /// Take all registered factories.
52    ///
53    /// Called by bootstrap after all modules have initialized.
54    /// This drains the store, so subsequent calls return empty vec.
55    pub fn take_factories(&self) -> Vec<Arc<dyn SyntaxDriverFactory>> {
56        std::mem::take(&mut *self.factories.write())
57    }
58
59    /// Find a factory that supports the given language.
60    ///
61    /// Returns the first factory that reports supporting the language.
62    #[must_use]
63    pub fn find(&self, language_id: &str) -> Option<Arc<dyn SyntaxDriverFactory>> {
64        self.factories
65            .read()
66            .iter()
67            .find(|f| f.supports(language_id))
68            .cloned()
69    }
70
71    /// Get the number of registered factories.
72    #[must_use]
73    pub fn len(&self) -> usize {
74        self.factories.read().len()
75    }
76
77    /// Check if no factories are registered.
78    #[must_use]
79    pub fn is_empty(&self) -> bool {
80        self.factories.read().is_empty()
81    }
82}
83
84/// Implement `Service` trait for `ServiceRegistry` compatibility.
85impl Service for SyntaxFactoryStore {}
86
87impl std::fmt::Debug for SyntaxFactoryStore {
88    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89        f.debug_struct("SyntaxFactoryStore")
90            .field("count", &self.len())
91            .finish()
92    }
93}
94
95#[cfg(test)]
96#[path = "store_tests.rs"]
97mod tests;