Skip to main content

aster/parser/
lsp_client.rs

1//! LSP Client
2//!
3//! Language Server Protocol 客户端实现
4
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7use std::collections::HashMap;
8use std::io::Write;
9use std::process::{Child, Command, Stdio};
10use std::sync::atomic::{AtomicU64, Ordering};
11use std::sync::Arc;
12use tokio::sync::{broadcast, Mutex, RwLock};
13
14use super::types::*;
15
16/// LSP 请求响应发送器类型
17pub(crate) type LspResponseSender = tokio::sync::oneshot::Sender<Result<Value, LspError>>;
18
19/// LSP 待处理请求映射类型
20pub(crate) type PendingRequestsMap = Arc<Mutex<HashMap<u64, LspResponseSender>>>;
21
22/// LSP 消息
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct LspMessage {
25    pub jsonrpc: String,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub id: Option<u64>,
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub method: Option<String>,
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub params: Option<Value>,
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub result: Option<Value>,
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub error: Option<LspError>,
36}
37
38/// LSP 错误
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct LspError {
41    pub code: i32,
42    pub message: String,
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub data: Option<Value>,
45}
46
47/// LSP 服务器状态
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum LspServerState {
50    Stopped,
51    Starting,
52    Running,
53    Error,
54}
55
56/// LSP 客户端配置
57#[derive(Debug, Clone)]
58pub struct LspClientConfig {
59    /// 命令
60    pub command: String,
61    /// 参数
62    pub args: Vec<String>,
63    /// 根目录 URI
64    pub root_uri: Option<String>,
65    /// 初始化选项
66    pub initialization_options: Option<Value>,
67}
68
69/// LSP 客户端事件
70#[derive(Debug, Clone)]
71pub enum LspClientEvent {
72    StateChange(LspServerState),
73    Notification { method: String, params: Value },
74    Error(String),
75}
76
77/// LSP 客户端
78pub struct LspClient {
79    language: String,
80    config: LspClientConfig,
81    state: Arc<RwLock<LspServerState>>,
82    process: Arc<Mutex<Option<Child>>>,
83    message_id: AtomicU64,
84    pending_requests: PendingRequestsMap,
85    capabilities: Arc<RwLock<Option<Value>>>,
86    event_sender: broadcast::Sender<LspClientEvent>,
87}
88
89impl LspClient {
90    /// 创建新的 LSP 客户端
91    pub fn new(language: impl Into<String>, config: LspClientConfig) -> Self {
92        let (event_sender, _) = broadcast::channel(64);
93        Self {
94            language: language.into(),
95            config,
96            state: Arc::new(RwLock::new(LspServerState::Stopped)),
97            process: Arc::new(Mutex::new(None)),
98            message_id: AtomicU64::new(0),
99            pending_requests: Arc::new(Mutex::new(HashMap::new())),
100            capabilities: Arc::new(RwLock::new(None)),
101            event_sender,
102        }
103    }
104
105    /// 订阅事件
106    pub fn subscribe(&self) -> broadcast::Receiver<LspClientEvent> {
107        self.event_sender.subscribe()
108    }
109
110    /// 获取状态
111    pub async fn get_state(&self) -> LspServerState {
112        *self.state.read().await
113    }
114
115    /// 获取能力
116    pub async fn get_capabilities(&self) -> Option<Value> {
117        self.capabilities.read().await.clone()
118    }
119
120    /// 启动 LSP 服务器
121    pub async fn start(&self) -> Result<bool, String> {
122        let current_state = *self.state.read().await;
123        if current_state == LspServerState::Running {
124            return Ok(true);
125        }
126
127        *self.state.write().await = LspServerState::Starting;
128        let _ = self
129            .event_sender
130            .send(LspClientEvent::StateChange(LspServerState::Starting));
131
132        // 启动进程
133        let child = Command::new(&self.config.command)
134            .args(&self.config.args)
135            .stdin(Stdio::piped())
136            .stdout(Stdio::piped())
137            .stderr(Stdio::piped())
138            .spawn()
139            .map_err(|e| format!("Failed to spawn LSP server: {}", e))?;
140
141        *self.process.lock().await = Some(child);
142
143        // 发送 initialize 请求
144        let init_params = serde_json::json!({
145            "processId": std::process::id(),
146            "capabilities": {
147                "textDocument": {
148                    "documentSymbol": {
149                        "hierarchicalDocumentSymbolSupport": true
150                    },
151                    "references": {
152                        "dynamicRegistration": false
153                    },
154                    "definition": {
155                        "dynamicRegistration": false
156                    }
157                }
158            },
159            "rootUri": self.config.root_uri,
160            "initializationOptions": self.config.initialization_options
161        });
162
163        match self.send_request("initialize", init_params).await {
164            Ok(result) => {
165                if let Some(caps) = result.get("capabilities") {
166                    *self.capabilities.write().await = Some(caps.clone());
167                }
168
169                // 发送 initialized 通知
170                self.send_notification("initialized", serde_json::json!({}))
171                    .await;
172
173                *self.state.write().await = LspServerState::Running;
174                let _ = self
175                    .event_sender
176                    .send(LspClientEvent::StateChange(LspServerState::Running));
177                Ok(true)
178            }
179            Err(e) => {
180                *self.state.write().await = LspServerState::Error;
181                let _ = self
182                    .event_sender
183                    .send(LspClientEvent::StateChange(LspServerState::Error));
184                Err(format!("Initialize failed: {}", e))
185            }
186        }
187    }
188
189    /// 停止 LSP 服务器
190    pub async fn stop(&self) {
191        if *self.state.read().await == LspServerState::Stopped {
192            return;
193        }
194
195        // 发送 shutdown 请求
196        let _ = self.send_request("shutdown", Value::Null).await;
197        self.send_notification("exit", Value::Null).await;
198
199        // 终止进程
200        if let Some(mut child) = self.process.lock().await.take() {
201            let _ = child.kill();
202        }
203
204        *self.state.write().await = LspServerState::Stopped;
205        let _ = self
206            .event_sender
207            .send(LspClientEvent::StateChange(LspServerState::Stopped));
208    }
209
210    /// 发送请求
211    async fn send_request(&self, method: &str, params: Value) -> Result<Value, String> {
212        let id = self.message_id.fetch_add(1, Ordering::SeqCst);
213
214        let message = LspMessage {
215            jsonrpc: "2.0".to_string(),
216            id: Some(id),
217            method: Some(method.to_string()),
218            params: Some(params),
219            result: None,
220            error: None,
221        };
222
223        self.send_message(&message).await?;
224
225        // 简化实现:同步等待响应
226        // 实际实现需要异步读取响应
227        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
228
229        Ok(Value::Null)
230    }
231
232    /// 发送通知
233    async fn send_notification(&self, method: &str, params: Value) {
234        let message = LspMessage {
235            jsonrpc: "2.0".to_string(),
236            id: None,
237            method: Some(method.to_string()),
238            params: Some(params),
239            result: None,
240            error: None,
241        };
242
243        let _ = self.send_message(&message).await;
244    }
245
246    /// 发送消息
247    async fn send_message(&self, message: &LspMessage) -> Result<(), String> {
248        let content = serde_json::to_string(message)
249            .map_err(|e| format!("Failed to serialize message: {}", e))?;
250
251        let header = format!("Content-Length: {}\r\n\r\n", content.len());
252
253        let mut process = self.process.lock().await;
254        if let Some(ref mut child) = *process {
255            if let Some(ref mut stdin) = child.stdin {
256                stdin
257                    .write_all(header.as_bytes())
258                    .map_err(|e| format!("Failed to write header: {}", e))?;
259                stdin
260                    .write_all(content.as_bytes())
261                    .map_err(|e| format!("Failed to write content: {}", e))?;
262                stdin
263                    .flush()
264                    .map_err(|e| format!("Failed to flush: {}", e))?;
265            }
266        }
267
268        Ok(())
269    }
270
271    /// 获取文档符号
272    pub async fn get_document_symbols(&self, uri: &str) -> Result<Vec<Value>, String> {
273        if *self.state.read().await != LspServerState::Running {
274            return Err("LSP server is not running".to_string());
275        }
276
277        let params = serde_json::json!({
278            "textDocument": { "uri": uri }
279        });
280
281        let result = self
282            .send_request("textDocument/documentSymbol", params)
283            .await?;
284
285        match result {
286            Value::Array(symbols) => Ok(symbols),
287            Value::Null => Ok(Vec::new()),
288            _ => Ok(Vec::new()),
289        }
290    }
291
292    /// 打开文档
293    pub async fn open_document(&self, uri: &str, language_id: &str, version: i32, text: &str) {
294        let params = serde_json::json!({
295            "textDocument": {
296                "uri": uri,
297                "languageId": language_id,
298                "version": version,
299                "text": text
300            }
301        });
302
303        self.send_notification("textDocument/didOpen", params).await;
304    }
305
306    /// 关闭文档
307    pub async fn close_document(&self, uri: &str) {
308        let params = serde_json::json!({
309            "textDocument": { "uri": uri }
310        });
311
312        self.send_notification("textDocument/didClose", params)
313            .await;
314    }
315
316    /// 查找引用
317    pub async fn find_references(
318        &self,
319        uri: &str,
320        position: LspPosition,
321    ) -> Result<Vec<LspLocation>, String> {
322        if *self.state.read().await != LspServerState::Running {
323            return Err("LSP server is not running".to_string());
324        }
325
326        let params = serde_json::json!({
327            "textDocument": { "uri": uri },
328            "position": { "line": position.line, "character": position.character },
329            "context": { "includeDeclaration": true }
330        });
331
332        let result = self.send_request("textDocument/references", params).await?;
333
334        match result {
335            Value::Array(locations) => {
336                let parsed: Vec<LspLocation> = locations
337                    .iter()
338                    .filter_map(|v| serde_json::from_value(v.clone()).ok())
339                    .collect();
340                Ok(parsed)
341            }
342            _ => Ok(Vec::new()),
343        }
344    }
345
346    /// 跳转到定义
347    pub async fn get_definition(
348        &self,
349        uri: &str,
350        position: LspPosition,
351    ) -> Result<Option<LspLocation>, String> {
352        if *self.state.read().await != LspServerState::Running {
353            return Err("LSP server is not running".to_string());
354        }
355
356        let params = serde_json::json!({
357            "textDocument": { "uri": uri },
358            "position": { "line": position.line, "character": position.character }
359        });
360
361        let result = self.send_request("textDocument/definition", params).await?;
362
363        match result {
364            Value::Array(locations) if !locations.is_empty() => {
365                serde_json::from_value(locations[0].clone())
366                    .map(Some)
367                    .map_err(|e| format!("Failed to parse location: {}", e))
368            }
369            Value::Object(_) => serde_json::from_value(result)
370                .map(Some)
371                .map_err(|e| format!("Failed to parse location: {}", e)),
372            _ => Ok(None),
373        }
374    }
375}
376
377#[cfg(test)]
378mod tests {
379    use super::*;
380
381    #[test]
382    fn test_lsp_server_state() {
383        assert_eq!(LspServerState::Stopped, LspServerState::Stopped);
384        assert_ne!(LspServerState::Running, LspServerState::Stopped);
385    }
386
387    #[test]
388    fn test_lsp_client_config() {
389        let config = LspClientConfig {
390            command: "typescript-language-server".to_string(),
391            args: vec!["--stdio".to_string()],
392            root_uri: Some("file:///tmp".to_string()),
393            initialization_options: None,
394        };
395        assert_eq!(config.command, "typescript-language-server");
396    }
397
398    #[test]
399    fn test_lsp_message_serialize() {
400        let msg = LspMessage {
401            jsonrpc: "2.0".to_string(),
402            id: Some(1),
403            method: Some("initialize".to_string()),
404            params: Some(serde_json::json!({})),
405            result: None,
406            error: None,
407        };
408        let json = serde_json::to_string(&msg).unwrap();
409        assert!(json.contains("jsonrpc"));
410        assert!(json.contains("initialize"));
411    }
412}