use anyhow::Result;
use std::collections::HashMap;
use std::path::Path;
use std::sync::Arc;
use tokio::sync::RwLock;
use super::client::LspClient;
use super::types::LspServerConfig;
pub struct LspClientRegistry {
clients: Arc<RwLock<HashMap<String, Arc<LspClient>>>>,
}
impl LspClientRegistry {
pub fn new() -> Self {
Self {
clients: Arc::new(RwLock::new(HashMap::new())),
}
}
pub async fn register(&self, config: &LspServerConfig, project_root: &Path) -> Result<()> {
let client = LspClient::from_config(config, project_root.to_path_buf());
client.spawn(config).await?;
let mut clients = self.clients.write().await;
clients.insert(config.language.clone(), Arc::new(client));
log::info!("LSP client registered for language: {}", config.language);
Ok(())
}
pub async fn get_client(&self, language: &str) -> Option<Arc<LspClient>> {
let clients = self.clients.read().await;
clients.get(language).cloned()
}
pub async fn has_active_clients(&self) -> bool {
let clients = self.clients.read().await;
!clients.is_empty()
}
pub async fn active_languages(&self) -> Vec<String> {
let clients = self.clients.read().await;
clients.keys().cloned().collect()
}
pub async fn shutdown_all(&self) -> Result<()> {
let mut clients = self.clients.write().await;
for (language, client) in clients.iter() {
if let Err(e) = client.shutdown().await {
log::warn!("Failed to shutdown LSP client '{}': {}", language, e);
}
}
clients.clear();
Ok(())
}
}
impl Default for LspClientRegistry {
fn default() -> Self {
Self::new()
}
}