Skip to main content

sh_layer3/lsp/
client.rs

1//! LSP 客户端实现
2//!
3//! 完整的 LSP 客户端,支持与语言服务器通信。
4
5use super::protocol::*;
6use super::server::{LanguageServer, LanguageServerManager};
7use super::types::*;
8use super::{LspError, LspResult};
9
10// Re-export protocol functions needed for implementations
11use super::protocol::{create_implementation_request, create_type_definition_request};
12use std::collections::HashMap;
13use std::io::{BufRead, Write};
14use std::path::{Path, PathBuf};
15use std::sync::atomic::{AtomicI64, Ordering};
16use std::sync::Arc;
17use tokio::sync::RwLock;
18
19/// LSP 服务器连接状态
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum ConnectionState {
22    /// 未连接
23    Disconnected,
24    /// 正在初始化
25    Initializing,
26    /// 已连接并就绪
27    Ready,
28    /// 已关闭
29    Shutdown,
30    /// 错误状态
31    Error,
32}
33
34/// LSP 服务器连接
35#[allow(dead_code)]
36struct ServerConnection {
37    /// 语言名称
38    language: String,
39    /// 根路径
40    root_path: PathBuf,
41    /// stdin 写入器
42    stdin: std::process::ChildStdin,
43    /// stdout 读取器(需要互斥访问)
44    stdout: std::io::BufReader<std::process::ChildStdout>,
45    /// 服务器能力
46    capabilities: Option<ServerCapabilities>,
47    /// 文档版本计数器
48    doc_versions: HashMap<String, i32>,
49    /// 已打开的文档
50    open_docs: HashMap<String, String>,
51}
52
53/// LSP 客户端
54pub struct LspClient {
55    /// 服务器管理器
56    manager: Arc<LanguageServerManager>,
57    /// 请求 ID 计数器
58    request_id: AtomicI64,
59    /// 服务器连接(按语言区分)
60    connections: Arc<RwLock<HashMap<String, ServerConnection>>>,
61    /// 连接状态
62    states: Arc<RwLock<HashMap<String, ConnectionState>>>,
63    /// 超时时间(毫秒)
64    timeout_ms: u64,
65}
66
67impl LspClient {
68    /// 创建新的 LSP 客户端
69    pub fn new() -> Self {
70        Self {
71            manager: Arc::new(LanguageServerManager::new()),
72            request_id: AtomicI64::new(1),
73            connections: Arc::new(RwLock::new(HashMap::new())),
74            states: Arc::new(RwLock::new(HashMap::new())),
75            timeout_ms: 30000,
76        }
77    }
78
79    /// 设置超时时间
80    pub fn with_timeout(mut self, timeout_ms: u64) -> Self {
81        self.timeout_ms = timeout_ms;
82        self
83    }
84
85    /// 获取下一个请求 ID
86    fn next_id(&self) -> RequestId {
87        RequestId::Number(self.request_id.fetch_add(1, Ordering::SeqCst))
88    }
89
90    /// 获取连接状态
91    pub async fn get_state(&self, language: &str) -> ConnectionState {
92        self.states
93            .read()
94            .await
95            .get(language)
96            .copied()
97            .unwrap_or(ConnectionState::Disconnected)
98    }
99
100    /// 检查是否已连接
101    pub async fn is_connected(&self, language: &str) -> bool {
102        self.get_state(language).await == ConnectionState::Ready
103    }
104
105    /// 启动语言服务器并初始化
106    pub async fn initialize(
107        &self,
108        language: &str,
109        root_path: &Path,
110    ) -> LspResult<InitializeResult> {
111        let root_path = root_path
112            .canonicalize()
113            .unwrap_or_else(|_| root_path.to_path_buf());
114
115        // 设置状态为初始化中
116        self.states
117            .write()
118            .await
119            .insert(language.to_string(), ConnectionState::Initializing);
120
121        // 获取服务器配置
122        let config = self
123            .manager
124            .get_config(language)
125            .ok_or_else(|| LspError::ServerNotFound(language.to_string()))?
126            .clone();
127
128        // 启动服务器进程
129        let mut server = LanguageServer::new(config.clone(), root_path.clone())?;
130        server.start()?;
131
132        // 获取 stdin/stdout
133        let stdin = server
134            .process
135            .as_mut()
136            .and_then(|p| p.stdin.take())
137            .ok_or_else(|| LspError::RequestFailed("Failed to get stdin".to_string()))?;
138
139        let stdout = server
140            .process
141            .as_mut()
142            .and_then(|p| p.stdout.take())
143            .ok_or_else(|| LspError::RequestFailed("Failed to get stdout".to_string()))?;
144
145        // 创建连接
146        let root_uri = self.path_to_uri(&root_path);
147        let request = create_initialize_request(
148            self.next_id(),
149            Some(root_uri),
150            "continuum",
151            env!("CARGO_PKG_VERSION"),
152        );
153
154        // 发送初始化请求
155        let mut writer = std::io::BufWriter::new(stdin);
156        let mut reader = std::io::BufReader::new(stdout);
157
158        write_message(&mut writer, &request)?;
159        writer.flush().map_err(LspError::Io)?;
160
161        // 读取响应
162        let response = self.read_response::<InitializeResult>(&mut reader)?;
163
164        // 发送 initialized 通知
165        let initialized_notification = LspNotification {
166            jsonrpc: "2.0".to_string(),
167            method: "initialized".to_string(),
168            params: Some(serde_json::json!({})),
169        };
170        write_message(&mut writer, &initialized_notification)?;
171        writer.flush().map_err(LspError::Io)?;
172
173        // 保存连接
174        let connection = ServerConnection {
175            language: language.to_string(),
176            root_path: root_path.clone(),
177            stdin: writer
178                .into_inner()
179                .map_err(|e| LspError::RequestFailed(format!("Failed to get stdin: {}", e)))?,
180            stdout: reader,
181            capabilities: Some(
182                response
183                    .result
184                    .clone()
185                    .map(|r| r.capabilities)
186                    .unwrap_or_default(),
187            ),
188            doc_versions: HashMap::new(),
189            open_docs: HashMap::new(),
190        };
191
192        self.connections
193            .write()
194            .await
195            .insert(language.to_string(), connection);
196        self.states
197            .write()
198            .await
199            .insert(language.to_string(), ConnectionState::Ready);
200
201        // 注册服务器
202        self.manager
203            .servers
204            .lock()
205            .await
206            .insert(language.to_string(), server);
207
208        Ok(response.result.unwrap_or_else(|| InitializeResult {
209            capabilities: ServerCapabilities::default(),
210            server_info: None,
211        }))
212    }
213
214    /// 打开文档
215    pub async fn open_document(&self, language: &str, file_path: &Path) -> LspResult<()> {
216        let mut connections = self.connections.write().await;
217        let conn = connections.get_mut(language).ok_or_else(|| {
218            LspError::RequestFailed("Language server not initialized".to_string())
219        })?;
220
221        let uri = self.path_to_uri(file_path);
222
223        // 检查是否已打开
224        if conn.open_docs.contains_key(&uri) {
225            return Ok(());
226        }
227
228        // 读取文件内容
229        let content = std::fs::read_to_string(file_path)
230            .map_err(|e| LspError::RequestFailed(format!("Failed to read file: {}", e)))?;
231
232        let version = conn.doc_versions.entry(uri.clone()).or_insert(0);
233        *version += 1;
234
235        // 发送 didOpen 通知
236        let notification = create_did_open_notification(uri.clone(), language, *version, &content);
237
238        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
239        write_message(&mut writer, &notification)?;
240        writer.flush().map_err(LspError::Io)?;
241
242        conn.open_docs.insert(uri, content);
243
244        Ok(())
245    }
246
247    /// 关闭文档
248    pub async fn close_document(&self, language: &str, file_path: &Path) -> LspResult<()> {
249        let mut connections = self.connections.write().await;
250        let conn = connections.get_mut(language).ok_or_else(|| {
251            LspError::RequestFailed("Language server not initialized".to_string())
252        })?;
253
254        let uri = self.path_to_uri(file_path);
255
256        // 发送 didClose 通知
257        let notification = create_did_close_notification(uri.clone());
258
259        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
260        write_message(&mut writer, &notification)?;
261        writer.flush().map_err(LspError::Io)?;
262
263        conn.open_docs.remove(&uri);
264        conn.doc_versions.remove(&uri);
265
266        Ok(())
267    }
268
269    /// 跳转到定义
270    pub async fn go_to_definition(
271        &self,
272        language: &str,
273        file_path: &Path,
274        position: Position,
275    ) -> LspResult<Vec<Location>> {
276        // 确保文档已打开
277        self.open_document(language, file_path).await?;
278
279        let mut connections = self.connections.write().await;
280        let conn = connections.get_mut(language).ok_or_else(|| {
281            LspError::RequestFailed("Language server not initialized".to_string())
282        })?;
283
284        // 检查能力
285        if !conn
286            .capabilities
287            .as_ref()
288            .map(|c| c.definition_provider.unwrap_or(false))
289            .unwrap_or(false)
290        {
291            return Err(LspError::RequestFailed(
292                "Server does not support go to definition".to_string(),
293            ));
294        }
295
296        let uri = self.path_to_uri(file_path);
297        let request = create_definition_request(self.next_id(), uri, position);
298
299        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
300        write_message(&mut writer, &request)?;
301        writer.flush().map_err(LspError::Io)?;
302
303        // 读取响应
304        let response = self.read_response::<Option<DefinitionResult>>(&mut conn.stdout)?;
305
306        match response.result {
307            Some(Some(result)) => Ok(result.to_locations()),
308            Some(None) => Ok(Vec::new()),
309            None => Ok(Vec::new()),
310        }
311    }
312
313    /// 查找引用
314    pub async fn find_references(
315        &self,
316        language: &str,
317        file_path: &Path,
318        position: Position,
319        include_declaration: bool,
320    ) -> LspResult<Vec<Location>> {
321        // 确保文档已打开
322        self.open_document(language, file_path).await?;
323
324        let mut connections = self.connections.write().await;
325        let conn = connections.get_mut(language).ok_or_else(|| {
326            LspError::RequestFailed("Language server not initialized".to_string())
327        })?;
328
329        // 检查能力
330        if !conn
331            .capabilities
332            .as_ref()
333            .map(|c| c.references_provider.unwrap_or(false))
334            .unwrap_or(false)
335        {
336            return Err(LspError::RequestFailed(
337                "Server does not support find references".to_string(),
338            ));
339        }
340
341        let uri = self.path_to_uri(file_path);
342        let request = create_references_request(self.next_id(), uri, position, include_declaration);
343
344        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
345        write_message(&mut writer, &request)?;
346        writer.flush().map_err(LspError::Io)?;
347
348        // 读取响应
349        let response = self.read_response::<Option<ReferenceResult>>(&mut conn.stdout)?;
350
351        Ok(response.result.flatten().unwrap_or_default())
352    }
353
354    /// 获取 Hover 信息
355    pub async fn get_hover(
356        &self,
357        language: &str,
358        file_path: &Path,
359        position: Position,
360    ) -> LspResult<Option<Hover>> {
361        // 确保文档已打开
362        self.open_document(language, file_path).await?;
363
364        let mut connections = self.connections.write().await;
365        let conn = connections.get_mut(language).ok_or_else(|| {
366            LspError::RequestFailed("Language server not initialized".to_string())
367        })?;
368
369        // 检查能力
370        if !conn
371            .capabilities
372            .as_ref()
373            .map(|c| c.hover_provider.unwrap_or(false))
374            .unwrap_or(false)
375        {
376            return Ok(None);
377        }
378
379        let uri = self.path_to_uri(file_path);
380        let request = create_hover_request(self.next_id(), uri, position);
381
382        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
383        write_message(&mut writer, &request)?;
384        writer.flush().map_err(LspError::Io)?;
385
386        // 读取响应
387        let response = self.read_response::<Option<Hover>>(&mut conn.stdout)?;
388
389        Ok(response.result.flatten())
390    }
391
392    /// 重命名符号
393    pub async fn rename_symbol(
394        &self,
395        language: &str,
396        file_path: &Path,
397        position: Position,
398        new_name: &str,
399    ) -> LspResult<Option<WorkspaceEdit>> {
400        // 确保文档已打开
401        self.open_document(language, file_path).await?;
402
403        let mut connections = self.connections.write().await;
404        let conn = connections.get_mut(language).ok_or_else(|| {
405            LspError::RequestFailed("Language server not initialized".to_string())
406        })?;
407
408        // 检查能力
409        if conn
410            .capabilities
411            .as_ref()
412            .map(|c| c.rename_provider.is_none())
413            .unwrap_or(true)
414        {
415            return Err(LspError::RequestFailed(
416                "Server does not support rename".to_string(),
417            ));
418        }
419
420        let uri = self.path_to_uri(file_path);
421        let request = create_rename_request(self.next_id(), uri, position, new_name);
422
423        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
424        write_message(&mut writer, &request)?;
425        writer.flush().map_err(LspError::Io)?;
426
427        // 读取响应
428        let response = self.read_response::<Option<RenameResult>>(&mut conn.stdout)?;
429
430        Ok(response.result.flatten())
431    }
432
433    /// 获取文档符号
434    pub async fn get_document_symbols(
435        &self,
436        language: &str,
437        file_path: &Path,
438    ) -> LspResult<Vec<DocumentSymbol>> {
439        // 确保文档已打开
440        self.open_document(language, file_path).await?;
441
442        let mut connections = self.connections.write().await;
443        let conn = connections.get_mut(language).ok_or_else(|| {
444            LspError::RequestFailed("Language server not initialized".to_string())
445        })?;
446
447        // 检查能力
448        if !conn
449            .capabilities
450            .as_ref()
451            .map(|c| c.document_symbol_provider.unwrap_or(false))
452            .unwrap_or(false)
453        {
454            return Ok(Vec::new());
455        }
456
457        let uri = self.path_to_uri(file_path);
458        let request = create_document_symbol_request(self.next_id(), uri);
459
460        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
461        write_message(&mut writer, &request)?;
462        writer.flush().map_err(LspError::Io)?;
463
464        // 读取响应
465        let response = self.read_response::<Option<Vec<DocumentSymbol>>>(&mut conn.stdout)?;
466
467        Ok(response.result.flatten().unwrap_or_default())
468    }
469
470    /// 获取工作区符号
471    pub async fn get_workspace_symbols(
472        &self,
473        language: &str,
474        query: &str,
475    ) -> LspResult<Vec<SymbolInformation>> {
476        let mut connections = self.connections.write().await;
477        let conn = connections.get_mut(language).ok_or_else(|| {
478            LspError::RequestFailed("Language server not initialized".to_string())
479        })?;
480
481        // 检查能力
482        if !conn
483            .capabilities
484            .as_ref()
485            .map(|c| c.workspace_symbol_provider.unwrap_or(false))
486            .unwrap_or(false)
487        {
488            return Ok(Vec::new());
489        }
490
491        let request = create_workspace_symbol_request(self.next_id(), query);
492
493        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
494        write_message(&mut writer, &request)?;
495        writer.flush().map_err(LspError::Io)?;
496
497        // 读取响应
498        let response = self.read_response::<Option<Vec<SymbolInformation>>>(&mut conn.stdout)?;
499
500        Ok(response.result.flatten().unwrap_or_default())
501    }
502
503    /// 获取代码操作
504    pub async fn get_code_actions(
505        &self,
506        language: &str,
507        file_path: &Path,
508        range: Range,
509        diagnostics: Vec<Diagnostic>,
510        only: Option<Vec<CodeActionKind>>,
511    ) -> LspResult<Vec<CodeAction>> {
512        // 确保文档已打开
513        self.open_document(language, file_path).await?;
514
515        let mut connections = self.connections.write().await;
516        let conn = connections.get_mut(language).ok_or_else(|| {
517            LspError::RequestFailed("Language server not initialized".to_string())
518        })?;
519
520        // 检查能力
521        if conn
522            .capabilities
523            .as_ref()
524            .map(|c| c.code_action_provider.is_none())
525            .unwrap_or(true)
526        {
527            return Ok(Vec::new());
528        }
529
530        let uri = self.path_to_uri(file_path);
531        let request = create_code_action_request(
532            self.next_id(),
533            uri,
534            range,
535            CodeActionContext { diagnostics, only },
536        );
537
538        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
539        write_message(&mut writer, &request)?;
540        writer.flush().map_err(LspError::Io)?;
541
542        // 读取响应
543        let response = self.read_response::<Option<Vec<CodeAction>>>(&mut conn.stdout)?;
544
545        Ok(response.result.flatten().unwrap_or_default())
546    }
547
548    /// 获取签名帮助
549    pub async fn get_signature_help(
550        &self,
551        language: &str,
552        file_path: &Path,
553        position: Position,
554    ) -> LspResult<Option<SignatureHelp>> {
555        // 确保文档已打开
556        self.open_document(language, file_path).await?;
557
558        let mut connections = self.connections.write().await;
559        let conn = connections.get_mut(language).ok_or_else(|| {
560            LspError::RequestFailed("Language server not initialized".to_string())
561        })?;
562
563        // 检查能力
564        if conn
565            .capabilities
566            .as_ref()
567            .map(|c| c.signature_help_provider.is_none())
568            .unwrap_or(true)
569        {
570            return Ok(None);
571        }
572
573        let uri = self.path_to_uri(file_path);
574        let request = create_signature_help_request(self.next_id(), uri, position);
575
576        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
577        write_message(&mut writer, &request)?;
578        writer.flush().map_err(LspError::Io)?;
579
580        // 读取响应
581        let response = self.read_response::<Option<SignatureHelp>>(&mut conn.stdout)?;
582
583        Ok(response.result.flatten())
584    }
585
586    /// 获取文档高亮
587    pub async fn get_document_highlights(
588        &self,
589        language: &str,
590        file_path: &Path,
591        position: Position,
592    ) -> LspResult<Vec<DocumentHighlight>> {
593        // 确保文档已打开
594        self.open_document(language, file_path).await?;
595
596        let mut connections = self.connections.write().await;
597        let conn = connections.get_mut(language).ok_or_else(|| {
598            LspError::RequestFailed("Language server not initialized".to_string())
599        })?;
600
601        let uri = self.path_to_uri(file_path);
602        let request = create_document_highlight_request(self.next_id(), uri, position);
603
604        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
605        write_message(&mut writer, &request)?;
606        writer.flush().map_err(LspError::Io)?;
607
608        // 读取响应
609        let response = self.read_response::<Option<Vec<DocumentHighlight>>>(&mut conn.stdout)?;
610
611        Ok(response.result.flatten().unwrap_or_default())
612    }
613
614    /// 格式化文档
615    pub async fn format_document(
616        &self,
617        language: &str,
618        file_path: &Path,
619        tab_size: u32,
620        insert_spaces: bool,
621    ) -> LspResult<Vec<TextEdit>> {
622        // 确保文档已打开
623        self.open_document(language, file_path).await?;
624
625        let mut connections = self.connections.write().await;
626        let conn = connections.get_mut(language).ok_or_else(|| {
627            LspError::RequestFailed("Language server not initialized".to_string())
628        })?;
629
630        // 检查能力
631        if !conn
632            .capabilities
633            .as_ref()
634            .map(|c| c.document_formatting_provider.unwrap_or(false))
635            .unwrap_or(false)
636        {
637            return Ok(Vec::new());
638        }
639
640        let uri = self.path_to_uri(file_path);
641        let request = create_formatting_request(
642            self.next_id(),
643            uri,
644            FormattingOptions {
645                tab_size,
646                insert_spaces,
647                trim_trailing_whitespace: Some(true),
648                insert_final_newline: Some(true),
649                trim_final_newlines: Some(true),
650            },
651        );
652
653        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
654        write_message(&mut writer, &request)?;
655        writer.flush().map_err(LspError::Io)?;
656
657        // 读取响应
658        let response = self.read_response::<Option<Vec<TextEdit>>>(&mut conn.stdout)?;
659
660        Ok(response.result.flatten().unwrap_or_default())
661    }
662
663    /// 获取代码补全
664    pub async fn get_completions(
665        &self,
666        language: &str,
667        file_path: &Path,
668        position: Position,
669    ) -> LspResult<Vec<CompletionItem>> {
670        // 确保文档已打开
671        self.open_document(language, file_path).await?;
672
673        let mut connections = self.connections.write().await;
674        let conn = connections.get_mut(language).ok_or_else(|| {
675            LspError::RequestFailed("Language server not initialized".to_string())
676        })?;
677
678        // 检查能力
679        if conn
680            .capabilities
681            .as_ref()
682            .map(|c| c.completion_provider.is_none())
683            .unwrap_or(true)
684        {
685            return Ok(Vec::new());
686        }
687
688        let uri = self.path_to_uri(file_path);
689        let request = create_completion_request(self.next_id(), uri, position);
690
691        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
692        write_message(&mut writer, &request)?;
693        writer.flush().map_err(LspError::Io)?;
694
695        // 读取响应
696        let response = self.read_response::<Option<CompletionResult>>(&mut conn.stdout)?;
697
698        match response.result {
699            Some(Some(CompletionResult::List(list))) => Ok(list.items),
700            Some(Some(CompletionResult::Items(items))) => Ok(items),
701            _ => Ok(Vec::new()),
702        }
703    }
704
705    /// 跳转到实现
706    pub async fn go_to_implementation(
707        &self,
708        language: &str,
709        file_path: &Path,
710        position: Position,
711    ) -> LspResult<Vec<Location>> {
712        // 确保文档已打开
713        self.open_document(language, file_path).await?;
714
715        let mut connections = self.connections.write().await;
716        let conn = connections.get_mut(language).ok_or_else(|| {
717            LspError::RequestFailed("Language server not initialized".to_string())
718        })?;
719
720        // 检查能力
721        if !conn
722            .capabilities
723            .as_ref()
724            .map(|c| c.implementation_provider.unwrap_or(false))
725            .unwrap_or(false)
726        {
727            return Ok(Vec::new());
728        }
729
730        let uri = self.path_to_uri(file_path);
731        let request = create_implementation_request(self.next_id(), uri, position);
732
733        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
734        write_message(&mut writer, &request)?;
735        writer.flush().map_err(LspError::Io)?;
736
737        // 读取响应
738        let response = self.read_response::<Option<DefinitionResult>>(&mut conn.stdout)?;
739
740        match response.result {
741            Some(Some(result)) => Ok(result.to_locations()),
742            _ => Ok(Vec::new()),
743        }
744    }
745
746    /// 跳转到类型定义
747    pub async fn go_to_type_definition(
748        &self,
749        language: &str,
750        file_path: &Path,
751        position: Position,
752    ) -> LspResult<Option<Location>> {
753        // 确保文档已打开
754        self.open_document(language, file_path).await?;
755
756        let mut connections = self.connections.write().await;
757        let conn = connections.get_mut(language).ok_or_else(|| {
758            LspError::RequestFailed("Language server not initialized".to_string())
759        })?;
760
761        // 检查能力
762        if !conn
763            .capabilities
764            .as_ref()
765            .map(|c| c.type_definition_provider.unwrap_or(false))
766            .unwrap_or(false)
767        {
768            return Ok(None);
769        }
770
771        let uri = self.path_to_uri(file_path);
772        let request = create_type_definition_request(self.next_id(), uri, position);
773
774        let mut writer = std::io::BufWriter::new(&mut conn.stdin);
775        write_message(&mut writer, &request)?;
776        writer.flush().map_err(LspError::Io)?;
777
778        // 读取响应
779        let response = self.read_response::<Option<DefinitionResult>>(&mut conn.stdout)?;
780
781        match response.result {
782            Some(Some(DefinitionResult::Single(loc))) => Ok(Some(loc)),
783            Some(Some(DefinitionResult::Multiple(locs))) => Ok(locs.first().cloned()),
784            Some(Some(DefinitionResult::Link(link))) => Ok(Some(Location {
785                uri: link.target_uri,
786                range: link.target_selection_range,
787            })),
788            Some(Some(DefinitionResult::Links(links))) => Ok(links.first().map(|link| Location {
789                uri: link.target_uri.clone(),
790                range: link.target_selection_range.clone(),
791            })),
792            _ => Ok(None),
793        }
794    }
795
796    /// 关闭语言服务器
797    pub async fn shutdown(&self, language: &str) -> LspResult<()> {
798        let mut states = self.states.write().await;
799        states.insert(language.to_string(), ConnectionState::Shutdown);
800
801        // 发送 shutdown 请求
802        {
803            let mut connections = self.connections.write().await;
804            if let Some(conn) = connections.get_mut(language) {
805                let request = LspRequest {
806                    jsonrpc: "2.0".to_string(),
807                    id: self.next_id(),
808                    method: "shutdown".to_string(),
809                    params: None::<()>,
810                };
811
812                let mut writer = std::io::BufWriter::new(&mut conn.stdin);
813                write_message(&mut writer, &request)?;
814                writer.flush().ok();
815
816                // 发送 exit 通知
817                let notification = LspNotification {
818                    jsonrpc: "2.0".to_string(),
819                    method: "exit".to_string(),
820                    params: None::<()>,
821                };
822                write_message(&mut writer, &notification)?;
823                writer.flush().ok();
824            }
825            connections.remove(language);
826        }
827
828        self.manager.stop_server(language).await?;
829
830        Ok(())
831    }
832
833    /// 关闭所有语言服务器
834    pub async fn shutdown_all(&self) -> LspResult<()> {
835        let languages: Vec<String> = self.connections.read().await.keys().cloned().collect();
836        for lang in languages {
837            self.shutdown(&lang).await.ok();
838        }
839        Ok(())
840    }
841
842    /// 路径转 URI
843    fn path_to_uri(&self, path: &Path) -> String {
844        let path = path.canonicalize().unwrap_or_else(|_| path.to_path_buf());
845        let path_str = path.display().to_string();
846        if cfg!(windows) {
847            format!("file:///{}", path_str.replace('\\', "/"))
848        } else {
849            format!("file://{}", path_str)
850        }
851    }
852
853    /// URI 转路径
854    #[allow(dead_code)]
855    fn uri_to_path(&self, uri: &str) -> PathBuf {
856        let path = uri.strip_prefix("file://").unwrap_or(uri);
857        let path = path.strip_prefix('/').unwrap_or(path);
858        if cfg!(windows) {
859            PathBuf::from(path.replace('/', "\\"))
860        } else {
861            PathBuf::from(path)
862        }
863    }
864
865    /// 读取响应
866    fn read_response<R: serde::de::DeserializeOwned>(
867        &self,
868        reader: &mut impl BufRead,
869    ) -> LspResult<LspResponse<R>> {
870        let message = read_message(reader)?;
871
872        match message {
873            LspMessage::Response(response) => {
874                let response: LspResponse<R> =
875                    serde_json::from_value(serde_json::to_value(response)?)?;
876                if let Some(error) = &response.error {
877                    return Err(LspError::RequestFailed(format!(
878                        "LSP error {}: {}",
879                        error.code, error.message
880                    )));
881                }
882                Ok(response)
883            }
884            LspMessage::Request(_) => Err(LspError::InvalidMessage(
885                "Expected response, got request".to_string(),
886            )),
887            LspMessage::Notification(_) => {
888                // 忽略通知,继续读取
889                self.read_response(reader)
890            }
891        }
892    }
893
894    /// 根据文件扩展名获取语言
895    pub fn get_language_from_extension(ext: &str) -> Option<&'static str> {
896        LanguageServerManager::get_language_from_extension(ext)
897    }
898
899    /// 获取服务器管理器
900    pub fn manager(&self) -> Arc<LanguageServerManager> {
901        self.manager.clone()
902    }
903}
904
905impl Default for LspClient {
906    fn default() -> Self {
907        Self::new()
908    }
909}
910
911// ============================================================================
912// 同步 LSP 客户端(简化版,用于单次调用)
913// ============================================================================
914
915/// 同步 LSP 客户端
916pub struct SyncLspClient {
917    inner: LspClient,
918    runtime: tokio::runtime::Runtime,
919}
920
921impl SyncLspClient {
922    pub fn new() -> Self {
923        Self {
924            inner: LspClient::new(),
925            runtime: tokio::runtime::Runtime::new().expect("Failed to create tokio runtime"),
926        }
927    }
928
929    pub fn initialize(&self, language: &str, root_path: &Path) -> LspResult<InitializeResult> {
930        self.runtime
931            .block_on(self.inner.initialize(language, root_path))
932    }
933
934    pub fn go_to_definition(
935        &self,
936        language: &str,
937        file_path: &Path,
938        position: Position,
939    ) -> LspResult<Vec<Location>> {
940        self.runtime
941            .block_on(self.inner.go_to_definition(language, file_path, position))
942    }
943
944    pub fn find_references(
945        &self,
946        language: &str,
947        file_path: &Path,
948        position: Position,
949        include_declaration: bool,
950    ) -> LspResult<Vec<Location>> {
951        self.runtime.block_on(self.inner.find_references(
952            language,
953            file_path,
954            position,
955            include_declaration,
956        ))
957    }
958
959    pub fn get_hover(
960        &self,
961        language: &str,
962        file_path: &Path,
963        position: Position,
964    ) -> LspResult<Option<Hover>> {
965        self.runtime
966            .block_on(self.inner.get_hover(language, file_path, position))
967    }
968
969    pub fn rename_symbol(
970        &self,
971        language: &str,
972        file_path: &Path,
973        position: Position,
974        new_name: &str,
975    ) -> LspResult<Option<WorkspaceEdit>> {
976        self.runtime.block_on(
977            self.inner
978                .rename_symbol(language, file_path, position, new_name),
979        )
980    }
981
982    pub fn get_document_symbols(
983        &self,
984        language: &str,
985        file_path: &Path,
986    ) -> LspResult<Vec<DocumentSymbol>> {
987        self.runtime
988            .block_on(self.inner.get_document_symbols(language, file_path))
989    }
990
991    pub fn open_document(&self, language: &str, file_path: &Path) -> LspResult<()> {
992        self.runtime
993            .block_on(self.inner.open_document(language, file_path))
994    }
995
996    pub fn close_document(&self, language: &str, file_path: &Path) -> LspResult<()> {
997        self.runtime
998            .block_on(self.inner.close_document(language, file_path))
999    }
1000
1001    pub fn shutdown(&self, language: &str) -> LspResult<()> {
1002        self.runtime.block_on(self.inner.shutdown(language))
1003    }
1004
1005    pub fn shutdown_all(&self) -> LspResult<()> {
1006        self.runtime.block_on(self.inner.shutdown_all())
1007    }
1008
1009    pub fn is_connected(&self, language: &str) -> bool {
1010        self.runtime.block_on(self.inner.is_connected(language))
1011    }
1012
1013    pub fn get_workspace_symbols(
1014        &self,
1015        language: &str,
1016        query: &str,
1017    ) -> LspResult<Vec<SymbolInformation>> {
1018        self.runtime
1019            .block_on(self.inner.get_workspace_symbols(language, query))
1020    }
1021
1022    pub fn get_code_actions(
1023        &self,
1024        language: &str,
1025        file_path: &Path,
1026        range: Range,
1027        diagnostics: Vec<Diagnostic>,
1028        only: Option<Vec<CodeActionKind>>,
1029    ) -> LspResult<Vec<CodeAction>> {
1030        self.runtime.block_on(self.inner.get_code_actions(
1031            language,
1032            file_path,
1033            range,
1034            diagnostics,
1035            only,
1036        ))
1037    }
1038
1039    pub fn get_signature_help(
1040        &self,
1041        language: &str,
1042        file_path: &Path,
1043        position: Position,
1044    ) -> LspResult<Option<SignatureHelp>> {
1045        self.runtime
1046            .block_on(self.inner.get_signature_help(language, file_path, position))
1047    }
1048
1049    pub fn get_document_highlights(
1050        &self,
1051        language: &str,
1052        file_path: &Path,
1053        position: Position,
1054    ) -> LspResult<Vec<DocumentHighlight>> {
1055        self.runtime.block_on(
1056            self.inner
1057                .get_document_highlights(language, file_path, position),
1058        )
1059    }
1060
1061    pub fn format_document(
1062        &self,
1063        language: &str,
1064        file_path: &Path,
1065        tab_size: u32,
1066        insert_spaces: bool,
1067    ) -> LspResult<Vec<TextEdit>> {
1068        self.runtime.block_on(self.inner.format_document(
1069            language,
1070            file_path,
1071            tab_size,
1072            insert_spaces,
1073        ))
1074    }
1075
1076    pub fn get_completions(
1077        &self,
1078        language: &str,
1079        file_path: &Path,
1080        position: Position,
1081    ) -> LspResult<Vec<CompletionItem>> {
1082        self.runtime
1083            .block_on(self.inner.get_completions(language, file_path, position))
1084    }
1085
1086    pub fn go_to_implementation(
1087        &self,
1088        language: &str,
1089        file_path: &Path,
1090        position: Position,
1091    ) -> LspResult<Vec<Location>> {
1092        self.runtime.block_on(
1093            self.inner
1094                .go_to_implementation(language, file_path, position),
1095        )
1096    }
1097
1098    pub fn go_to_type_definition(
1099        &self,
1100        language: &str,
1101        file_path: &Path,
1102        position: Position,
1103    ) -> LspResult<Option<Location>> {
1104        self.runtime.block_on(
1105            self.inner
1106                .go_to_type_definition(language, file_path, position),
1107        )
1108    }
1109}
1110
1111impl Default for SyncLspClient {
1112    fn default() -> Self {
1113        Self::new()
1114    }
1115}
1116
1117// ============================================================================
1118// 便捷函数
1119// ============================================================================
1120
1121/// 快速跳转到定义(自动检测语言并初始化服务器)
1122pub async fn quick_go_to_definition(
1123    file_path: &Path,
1124    position: Position,
1125) -> LspResult<Vec<Location>> {
1126    let ext = file_path
1127        .extension()
1128        .and_then(|e| e.to_str())
1129        .ok_or_else(|| LspError::RequestFailed("Unknown file extension".to_string()))?;
1130
1131    let language = LanguageServerManager::get_language_from_extension(ext)
1132        .ok_or_else(|| LspError::ServerNotFound(format!("No LSP server for extension: {}", ext)))?;
1133
1134    let client = LspClient::new();
1135    let root_path = file_path.parent().unwrap_or(Path::new("."));
1136
1137    client.initialize(language, root_path).await?;
1138    let result = client.go_to_definition(language, file_path, position).await;
1139    client.shutdown(language).await?;
1140
1141    result
1142}
1143
1144/// 快速查找引用
1145pub async fn quick_find_references(
1146    file_path: &Path,
1147    position: Position,
1148    include_declaration: bool,
1149) -> LspResult<Vec<Location>> {
1150    let ext = file_path
1151        .extension()
1152        .and_then(|e| e.to_str())
1153        .ok_or_else(|| LspError::RequestFailed("Unknown file extension".to_string()))?;
1154
1155    let language = LanguageServerManager::get_language_from_extension(ext)
1156        .ok_or_else(|| LspError::ServerNotFound(format!("No LSP server for extension: {}", ext)))?;
1157
1158    let client = LspClient::new();
1159    let root_path = file_path.parent().unwrap_or(Path::new("."));
1160
1161    client.initialize(language, root_path).await?;
1162    let result = client
1163        .find_references(language, file_path, position, include_declaration)
1164        .await;
1165    client.shutdown(language).await?;
1166
1167    result
1168}
1169
1170#[cfg(test)]
1171mod tests {
1172    use super::*;
1173
1174    #[test]
1175    fn test_client_creation() {
1176        let client = LspClient::new();
1177        assert!(client.manager().get_config("rust").is_some());
1178    }
1179
1180    #[test]
1181    fn test_sync_client_creation() {
1182        let client = SyncLspClient::new();
1183        assert!(!client.is_connected("rust"));
1184    }
1185
1186    #[test]
1187    fn test_request_id_increment() {
1188        let client = LspClient::new();
1189        let id1 = client.next_id();
1190        let id2 = client.next_id();
1191        assert_ne!(id1, id2);
1192    }
1193
1194    #[test]
1195    fn test_path_to_uri() {
1196        let client = LspClient::new();
1197        let path = Path::new("/home/user/test.rs");
1198        let uri = client.path_to_uri(path);
1199        assert!(uri.starts_with("file://"));
1200    }
1201
1202    #[test]
1203    fn test_connection_state() {
1204        use tokio::runtime::Runtime;
1205        let rt = Runtime::new().unwrap();
1206        let client = LspClient::new();
1207
1208        rt.block_on(async {
1209            let state = client.get_state("rust").await;
1210            assert_eq!(state, ConnectionState::Disconnected);
1211        });
1212    }
1213}