Skip to main content

matrixcode_core/lsp/
manager.rs

1//! LSP Manager
2//!
3//! 管理多个 LSP 服务器连接
4
5use std::collections::HashMap;
6use std::sync::{Arc, RwLock};
7
8use super::types::{LspConfig, LspServerConfig, LspServerInfo, LspServerStatus};
9
10/// LSP 管理器
11///
12/// 管理多个语言服务器的连接状态
13pub struct LspManager {
14    /// 服务器配置(按名称索引)
15    configs: HashMap<String, LspServerConfig>,
16    /// 服务器状态(按名称索引)
17    statuses: Arc<RwLock<HashMap<String, LspServerStatus>>>,
18}
19
20impl LspManager {
21    /// 创建新的 LSP 管理器
22    pub fn new() -> Self {
23        Self {
24            configs: HashMap::new(),
25            statuses: Arc::new(RwLock::new(HashMap::new())),
26        }
27    }
28
29    /// 从配置创建 LSP 管理器
30    pub fn from_config(config: &LspConfig) -> Self {
31        let configs: HashMap<String, LspServerConfig> = config
32            .servers
33            .iter()
34            .filter(|s| s.enabled)
35            .map(|s| (s.language.clone(), s.clone()))
36            .collect();
37
38        // 初始化所有状态为 NotStarted
39        let statuses = configs
40            .keys()
41            .map(|k| (k.clone(), LspServerStatus::NotStarted))
42            .collect();
43
44        Self {
45            configs,
46            statuses: Arc::new(RwLock::new(statuses)),
47        }
48    }
49
50    /// 添加服务器配置
51    pub fn add_server(&mut self, config: LspServerConfig) {
52        let name = config.language.clone();
53        self.configs.insert(name.clone(), config);
54        if let Ok(mut statuses) = self.statuses.write() {
55            statuses.insert(name, LspServerStatus::NotStarted);
56        }
57    }
58
59    /// 移除服务器配置
60    pub fn remove_server(&mut self, name: &str) {
61        self.configs.remove(name);
62        if let Ok(mut statuses) = self.statuses.write() {
63            statuses.remove(name);
64        }
65    }
66
67    /// 获取所有服务器信息(用于 TUI 显示)
68    pub fn server_infos(&self) -> Vec<LspServerInfo> {
69        if let Ok(statuses) = self.statuses.read() {
70            self.configs
71                .iter()
72                .map(|(name, config)| {
73                    let status = statuses
74                        .get(name)
75                        .cloned()
76                        .unwrap_or(LspServerStatus::NotStarted);
77                    LspServerInfo {
78                        name: config.command.clone(),
79                        language: config.language.clone(),
80                        status,
81                    }
82                })
83                .collect()
84        } else {
85            // 返回默认状态
86            self.configs
87                .iter()
88                .map(|(_name, config)| LspServerInfo {
89                    name: config.command.clone(),
90                    language: config.language.clone(),
91                    status: LspServerStatus::NotStarted,
92                })
93                .collect()
94        }
95    }
96
97    /// 获取服务器状态
98    pub fn get_status(&self, name: &str) -> LspServerStatus {
99        self.statuses
100            .read()
101            .map(|s| s.get(name).cloned().unwrap_or(LspServerStatus::NotStarted))
102            .unwrap_or(LspServerStatus::NotStarted)
103    }
104
105    /// 更新服务器状态
106    pub fn set_status(&self, name: &str, status: LspServerStatus) {
107        if let Ok(mut statuses) = self.statuses.write() {
108            statuses.insert(name.to_string(), status);
109        }
110    }
111
112    /// 标记服务器已连接
113    pub fn mark_connected(&self, name: &str) {
114        self.set_status(name, LspServerStatus::Connected);
115    }
116
117    /// 标记服务器错误
118    pub fn mark_error(&self, name: &str, msg: impl Into<String>) {
119        self.set_status(name, LspServerStatus::Error(msg.into()));
120    }
121
122    /// 获取服务器配置
123    pub fn get_config(&self, name: &str) -> Option<&LspServerConfig> {
124        self.configs.get(name)
125    }
126
127    /// 获取所有服务器名称
128    pub fn server_names(&self) -> Vec<&String> {
129        self.configs.keys().collect()
130    }
131
132    /// 获取已连接的服务器数量
133    pub fn connected_count(&self) -> usize {
134        self.statuses
135            .read()
136            .map(|s| s.values().filter(|s| s.is_ok()).count())
137            .unwrap_or(0)
138    }
139
140    /// 获取有错误的服务器数量
141    pub fn error_count(&self) -> usize {
142        self.statuses
143            .read()
144            .map(|s| s.values().filter(|s| s.is_error()).count())
145            .unwrap_or(0)
146    }
147
148    /// 是否有任何服务器配置
149    pub fn has_servers(&self) -> bool {
150        !self.configs.is_empty()
151    }
152
153    /// 重置所有状态为未启动
154    pub fn reset_all(&self) {
155        if let Ok(mut statuses) = self.statuses.write() {
156            for name in self.configs.keys() {
157                statuses.insert(name.clone(), LspServerStatus::NotStarted);
158            }
159        }
160    }
161}
162
163impl Default for LspManager {
164    fn default() -> Self {
165        Self::new()
166    }
167}
168
169/// 查找 LSP 配置文件
170///
171/// 在当前目录或用户主目录查找 `lsp.toml`
172pub fn find_lsp_config(start_dir: &std::path::Path) -> Option<std::path::PathBuf> {
173    // 当前目录
174    let local_config = start_dir.join("lsp.toml");
175    if local_config.exists() {
176        return Some(local_config);
177    }
178
179    // 用户主目录
180    if let Some(home) = dirs::home_dir() {
181        let home_config = home.join(".config").join("matrixcode").join("lsp.toml");
182        if home_config.exists() {
183            return Some(home_config);
184        }
185    }
186
187    None
188}
189
190/// 加载 LSP 配置
191///
192/// 自动查找配置文件,找不到则返回默认配置
193pub fn load_lsp_config(start_dir: &std::path::Path) -> LspConfig {
194    find_lsp_config(start_dir)
195        .and_then(|p| LspConfig::from_file(&p).ok())
196        .unwrap_or_default()
197}