Skip to main content

matrixcode_core/lsp/
registry.rs

1//! LSP Client Registry
2//!
3//! 管理多个语言的 LSP 客户端。
4
5use anyhow::Result;
6use std::collections::HashMap;
7use std::path::Path;
8use std::sync::Arc;
9use tokio::sync::RwLock;
10use tokio::time::{Duration, timeout};
11
12use super::client::LspClient;
13use super::types::LspServerConfig;
14
15/// LSP 客户端注册表
16pub struct LspClientRegistry {
17    /// 语言 -> 客户端映射
18    clients: Arc<RwLock<HashMap<String, Arc<LspClient>>>>,
19}
20
21/// 默认等待 LSP 客户端启动的时间(与启动超时一致)
22const LSP_WAIT_TIMEOUT_SECS: u64 = 180;
23
24impl LspClientRegistry {
25    /// 创建空注册表
26    pub fn new() -> Self {
27        Self {
28            clients: Arc::new(RwLock::new(HashMap::new())),
29        }
30    }
31
32    /// 启动并注册 LSP 客户端
33    pub async fn register(&self, config: &LspServerConfig, project_root: &Path) -> Result<()> {
34        let client = LspClient::from_config(config, project_root.to_path_buf());
35        client.spawn(config).await?;
36        let mut clients = self.clients.write().await;
37        clients.insert(config.language.clone(), Arc::new(client));
38        log::info!("LSP client registered for language: {}", config.language);
39        Ok(())
40    }
41
42    /// 获取指定语言的客户端(立即返回,不等待)
43    pub async fn get_client(&self, language: &str) -> Option<Arc<LspClient>> {
44        let clients = self.clients.read().await;
45        clients.get(language).cloned()
46    }
47
48    /// 获取指定语言的客户端,等待启动完成(最多 30 秒)
49    pub async fn get_client_or_wait(&self, language: &str) -> Result<Arc<LspClient>> {
50        // 先尝试立即获取
51        if let Some(client) = self.get_client(language).await {
52            return Ok(client);
53        }
54
55        // 等待客户端启动
56        log::info!("Waiting for LSP client '{}' to start...", language);
57        let wait_duration = Duration::from_secs(LSP_WAIT_TIMEOUT_SECS);
58
59        timeout(wait_duration, async {
60            loop {
61                if let Some(client) = self.get_client(language).await {
62                    log::info!("LSP client '{}' is now available", language);
63                    return Ok(client);
64                }
65                tokio::time::sleep(Duration::from_millis(500)).await;
66            }
67        })
68        .await
69        .map_err(|_| anyhow::anyhow!(
70            "LSP 客户端 '{}' 启动超时({}秒)。\n\
71            提示:LSP 服务器可能正在后台启动,请稍后再试。\n\
72            状态:检查 TUI 状态栏 LSP 是否显示 'starting...'",
73            language, LSP_WAIT_TIMEOUT_SECS
74        ))?
75    }
76
77    /// 是否有活跃客户端
78    pub async fn has_active_clients(&self) -> bool {
79        let clients = self.clients.read().await;
80        !clients.is_empty()
81    }
82
83    /// 获取所有活跃语言
84    pub async fn active_languages(&self) -> Vec<String> {
85        let clients = self.clients.read().await;
86        clients.keys().cloned().collect()
87    }
88
89    /// 关闭所有客户端
90    pub async fn shutdown_all(&self) -> Result<()> {
91        let mut clients = self.clients.write().await;
92        for (language, client) in clients.iter() {
93            if let Err(e) = client.shutdown().await {
94                log::warn!("Failed to shutdown LSP client '{}': {}", language, e);
95            }
96        }
97        clients.clear();
98        Ok(())
99    }
100}
101
102impl Default for LspClientRegistry {
103    fn default() -> Self {
104        Self::new()
105    }
106}