Skip to main content

aster/lsp/
manager.rs

1//! LSP 服务器管理器
2//!
3//! 管理多个语言服务器实例
4
5use std::collections::HashMap;
6use std::path::{Path, PathBuf};
7use std::sync::Arc;
8use tokio::sync::RwLock;
9
10use super::config::{default_lsp_configs, load_lsp_config_file, LSPServerConfig};
11use super::server::{LSPDiagnostic, LSPServer, LSPServerState};
12
13/// 初始化选项
14#[derive(Debug, Clone, Default)]
15pub struct InitializeLSPOptions {
16    /// 是否加载 .lsp.json 配置文件
17    pub load_config_file: bool,
18    /// 是否注册默认服务器
19    pub use_defaults: bool,
20    /// 自定义服务器配置
21    pub custom_configs: Vec<LSPServerConfig>,
22}
23
24/// LSP 服务器管理器
25pub struct LSPServerManager {
26    servers: Arc<RwLock<HashMap<String, LSPServer>>>,
27    server_configs: Arc<RwLock<Vec<LSPServerConfig>>>,
28    workspace_root: PathBuf,
29    extension_to_server: Arc<RwLock<HashMap<String, Vec<String>>>>,
30    diagnostics_cache: Arc<RwLock<HashMap<String, Vec<LSPDiagnostic>>>>,
31}
32
33impl LSPServerManager {
34    /// 创建新的管理器
35    pub fn new(workspace_root: impl AsRef<Path>) -> Self {
36        Self {
37            servers: Arc::new(RwLock::new(HashMap::new())),
38            server_configs: Arc::new(RwLock::new(Vec::new())),
39            workspace_root: workspace_root.as_ref().to_path_buf(),
40            extension_to_server: Arc::new(RwLock::new(HashMap::new())),
41            diagnostics_cache: Arc::new(RwLock::new(HashMap::new())),
42        }
43    }
44
45    /// 注册 LSP 服务器配置
46    pub async fn register_server(&self, config: LSPServerConfig) {
47        // 建立扩展名索引
48        let mut ext_map = self.extension_to_server.write().await;
49        for ext in &config.file_extensions {
50            let normalized = if ext.starts_with('.') {
51                ext.to_lowercase()
52            } else {
53                format!(".{}", ext.to_lowercase())
54            };
55            ext_map
56                .entry(normalized)
57                .or_default()
58                .push(config.name.clone());
59        }
60
61        self.server_configs.write().await.push(config);
62    }
63
64    /// 从 .lsp.json 加载配置
65    pub async fn load_config_from_file(&self) -> Vec<LSPServerConfig> {
66        let configs = load_lsp_config_file(&self.workspace_root);
67        for config in &configs {
68            self.register_server(config.clone()).await;
69        }
70        configs
71    }
72
73    /// 初始化所有服务器
74    pub async fn initialize(&self, options: InitializeLSPOptions) -> Result<(), String> {
75        // 1. 加载配置文件
76        if options.load_config_file {
77            let file_configs = self.load_config_from_file().await;
78            if !file_configs.is_empty() {
79                tracing::info!("[LSP] 从配置文件加载了 {} 个服务器", file_configs.len());
80            }
81        }
82
83        // 2. 注册自定义配置
84        for config in options.custom_configs {
85            self.register_server(config).await;
86        }
87
88        // 3. 注册默认服务器
89        if options.use_defaults {
90            let existing: std::collections::HashSet<_> = self
91                .server_configs
92                .read()
93                .await
94                .iter()
95                .map(|c| c.name.clone())
96                .collect();
97            for config in default_lsp_configs() {
98                if !existing.contains(&config.name) {
99                    self.register_server(config).await;
100                }
101            }
102        }
103
104        // 4. 启动所有服务器
105        let configs = self.server_configs.read().await.clone();
106        for config in configs {
107            let mut server = LSPServer::new(config.clone());
108            if let Err(e) = server.start(&self.workspace_root).await {
109                tracing::warn!("[LSP] 启动 {} 失败: {}", config.name, e);
110                continue;
111            }
112            self.servers
113                .write()
114                .await
115                .insert(config.name.clone(), server);
116        }
117
118        let count = self.servers.read().await.len();
119        tracing::info!("[LSP] 初始化完成: {} 个服务器启动成功", count);
120        Ok(())
121    }
122
123    /// 关闭所有服务器
124    pub async fn shutdown(&self) {
125        let mut servers = self.servers.write().await;
126        for (name, server) in servers.iter_mut() {
127            if let Err(e) = server.stop().await {
128                tracing::warn!("[LSP] 停止 {} 失败: {}", name, e);
129            }
130        }
131        servers.clear();
132    }
133
134    /// 根据文件类型获取服务器
135    pub async fn get_server_for_file(&self, file_path: &Path) -> Option<String> {
136        let ext = file_path.extension()?.to_str()?;
137        let normalized = format!(".{}", ext.to_lowercase());
138
139        let ext_map = self.extension_to_server.read().await;
140        let server_names = ext_map.get(&normalized)?;
141
142        let servers = self.servers.read().await;
143        for name in server_names {
144            if let Some(server) = servers.get(name) {
145                if server.is_healthy().await {
146                    return Some(name.clone());
147                }
148            }
149        }
150        None
151    }
152
153    /// 获取所有服务器状态
154    pub async fn get_all_server_status(&self) -> HashMap<String, LSPServerState> {
155        let servers = self.servers.read().await;
156        let mut status = HashMap::new();
157        for (name, server) in servers.iter() {
158            status.insert(name.clone(), server.get_state().await);
159        }
160        status
161    }
162
163    /// 获取文件的诊断信息
164    pub async fn get_file_diagnostics(&self, file_path: &Path) -> Vec<LSPDiagnostic> {
165        let uri = format!("file://{}", file_path.display());
166        self.diagnostics_cache
167            .read()
168            .await
169            .get(&uri)
170            .cloned()
171            .unwrap_or_default()
172    }
173
174    /// 清除诊断缓存
175    pub async fn clear_diagnostics(&self, file_path: Option<&Path>) {
176        if let Some(path) = file_path {
177            let uri = format!("file://{}", path.display());
178            self.diagnostics_cache.write().await.remove(&uri);
179        } else {
180            self.diagnostics_cache.write().await.clear();
181        }
182    }
183}