Mountain/ApplicationState/State/ExtensionState/ProviderRegistration/ProviderRegistration.rs
1//! # ProviderRegistration Module (ApplicationState)
2//!
3//! ## RESPONSIBILITIES
4//! Manages language providers registration state including completion,
5//! hover, document symbol, and other language feature providers.
6//!
7//! ## ARCHITECTURAL ROLE
8//! ProviderRegistration is part of the **ExtensionState** module, representing
9//! language provider registration state.
10//!
11//! ## KEY COMPONENTS
12//! - Registration: Main struct containing language providers map
13//! - Default: Initialization implementation
14//! - Helper methods: Provider manipulation utilities
15//!
16//! ## ERROR HANDLING
17//! - Thread-safe access via `Arc<Mutex<...>>`
18//! - Proper lock error handling with `MapLockError` helpers
19//!
20//! ## LOGGING
21//! State changes are logged at appropriate levels (debug, info, warn, error).
22//!
23//! ## PERFORMANCE CONSIDERATIONS
24//! - Lock mutexes briefly and release immediately
25//! - Avoid nested locks to prevent deadlocks
26//! - Use Arc for shared ownership across threads
27//!
28//! ## TODO
29//! - [ ] Add provider validation invariants
30//! - [ ] Implement provider lifecycle events
31//! - [ ] Add provider metrics collection
32
33use std::{
34 collections::HashMap,
35 sync::{Arc, Mutex as StandardMutex},
36};
37
38use crate::{ApplicationState::DTO::ProviderRegistrationDTO::ProviderRegistrationDTO, dev_log};
39
40/// Language provider registration state.
41#[derive(Clone)]
42pub struct Registration {
43 /// Registered language providers by handle.
44 pub LanguageProviders:Arc<StandardMutex<HashMap<u32, ProviderRegistrationDTO>>>,
45}
46
47impl Default for Registration {
48 fn default() -> Self {
49 dev_log!(
50 "extensions",
51 "[ProviderRegistration] Initializing default provider registration..."
52 );
53
54 Self { LanguageProviders:Arc::new(StandardMutex::new(HashMap::new())) }
55 }
56}
57
58impl Registration {
59 /// Gets all registered language providers.
60 pub fn GetProviders(&self) -> HashMap<u32, ProviderRegistrationDTO> {
61 self.LanguageProviders
62 .lock()
63 .ok()
64 .map(|guard| guard.clone())
65 .unwrap_or_default()
66 }
67
68 /// Gets a provider by its handle.
69 pub fn GetProvider(&self, handle:u32) -> Option<ProviderRegistrationDTO> {
70 self.LanguageProviders.lock().ok().and_then(|guard| guard.get(&handle).cloned())
71 }
72
73 /// Registers a language provider.
74 pub fn RegisterProvider(&self, handle:u32, provider:ProviderRegistrationDTO) {
75 if let Ok(mut guard) = self.LanguageProviders.lock() {
76 guard.insert(handle, provider);
77
78 // Duplicate of the `provider-register` log line emitted by
79 // `MountainVinegRPCService`'s OR match - both fire per
80 // provider registration. Route this one to
81 // `provider-register` too (now short-muted) so the
82 // `extensions` tag stays signal-only (scan start/end,
83 // classification changes, install events).
84 dev_log!(
85 "provider-register",
86 "[ProviderRegistration] Provider registered with handle: {}",
87 handle
88 );
89 }
90 }
91
92 /// Unregisters a language provider.
93 pub fn UnregisterProvider(&self, handle:u32) {
94 if let Ok(mut guard) = self.LanguageProviders.lock() {
95 guard.remove(&handle);
96
97 dev_log!(
98 "extensions",
99 "[ProviderRegistration] Provider unregistered with handle: {}",
100 handle
101 );
102 }
103 }
104
105 /// Gets all providers for a specific language.
106 pub fn GetProvidersForLanguage(&self, language:&str) -> Vec<ProviderRegistrationDTO> {
107 self.LanguageProviders
108 .lock()
109 .ok()
110 .map(|guard| guard.values().filter(|p| p.MatchesSelector("", language)).cloned().collect())
111 .unwrap_or_default()
112 }
113}