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;