matrixcode_core/lsp/
registry.rs1use 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
15pub struct LspClientRegistry {
17 clients: Arc<RwLock<HashMap<String, Arc<LspClient>>>>,
19}
20
21const LSP_WAIT_TIMEOUT_SECS: u64 = 180;
23
24impl LspClientRegistry {
25 pub fn new() -> Self {
27 Self {
28 clients: Arc::new(RwLock::new(HashMap::new())),
29 }
30 }
31
32 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 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 pub async fn get_client_or_wait(&self, language: &str) -> Result<Arc<LspClient>> {
50 if let Some(client) = self.get_client(language).await {
52 return Ok(client);
53 }
54
55 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 pub async fn has_active_clients(&self) -> bool {
79 let clients = self.clients.read().await;
80 !clients.is_empty()
81 }
82
83 pub async fn active_languages(&self) -> Vec<String> {
85 let clients = self.clients.read().await;
86 clients.keys().cloned().collect()
87 }
88
89 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}