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;