Skip to main content

aster/lsp/
server.rs

1//! LSP 服务器实例
2//!
3//! 管理单个语言服务器的生命周期和通信
4
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use std::path::Path;
8use std::process::Stdio;
9use std::sync::atomic::{AtomicU64, Ordering};
10use std::sync::Arc;
11use tokio::process::{Child, Command};
12use tokio::sync::{mpsc, RwLock};
13
14use super::config::LSPServerConfig;
15
16/// LSP 服务器状态
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
18pub enum LSPServerState {
19    Initializing,
20    Ready,
21    Error,
22    Stopped,
23}
24
25/// LSP 诊断信息
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct LSPDiagnostic {
28    pub range: LSPRange,
29    pub severity: Option<u32>,
30    pub message: String,
31    pub source: Option<String>,
32    pub code: Option<String>,
33}
34
35/// LSP 范围
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct LSPRange {
38    pub start: LSPPosition,
39    pub end: LSPPosition,
40}
41
42/// LSP 位置
43#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct LSPPosition {
45    pub line: u32,
46    pub character: u32,
47}
48
49/// 打开的文档
50#[derive(Debug, Clone)]
51struct OpenDocument {
52    uri: String,
53    language_id: String,
54    version: u32,
55    content: String,
56}
57
58/// LSP 服务器实例
59pub struct LSPServer {
60    config: LSPServerConfig,
61    state: Arc<RwLock<LSPServerState>>,
62    process: Arc<RwLock<Option<Child>>>,
63    next_request_id: AtomicU64,
64    open_documents: Arc<RwLock<HashMap<String, OpenDocument>>>,
65    workspace_root: Arc<RwLock<String>>,
66    restart_count: Arc<RwLock<u32>>,
67    request_tx: Option<mpsc::Sender<String>>,
68}
69
70impl LSPServer {
71    /// 创建新的 LSP 服务器实例
72    pub fn new(config: LSPServerConfig) -> Self {
73        Self {
74            config,
75            state: Arc::new(RwLock::new(LSPServerState::Stopped)),
76            process: Arc::new(RwLock::new(None)),
77            next_request_id: AtomicU64::new(1),
78            open_documents: Arc::new(RwLock::new(HashMap::new())),
79            workspace_root: Arc::new(RwLock::new(String::new())),
80            restart_count: Arc::new(RwLock::new(0)),
81            request_tx: None,
82        }
83    }
84
85    /// 启动 LSP 服务器
86    pub async fn start(&mut self, workspace_root: &Path) -> Result<(), String> {
87        let mut state = self.state.write().await;
88        if *state != LSPServerState::Stopped {
89            return Err(format!("服务器已启动 (状态: {:?})", *state));
90        }
91
92        *state = LSPServerState::Initializing;
93        *self.workspace_root.write().await = workspace_root.display().to_string();
94
95        // 启动进程
96        let mut cmd = Command::new(&self.config.command);
97        cmd.args(&self.config.args)
98            .current_dir(workspace_root)
99            .stdin(Stdio::piped())
100            .stdout(Stdio::piped())
101            .stderr(Stdio::piped());
102
103        // 设置环境变量
104        for (key, value) in &self.config.env {
105            cmd.env(key, value);
106        }
107
108        match cmd.spawn() {
109            Ok(child) => {
110                *self.process.write().await = Some(child);
111                *state = LSPServerState::Ready;
112                tracing::info!("[LSP] {} 启动成功", self.config.name);
113                Ok(())
114            }
115            Err(e) => {
116                *state = LSPServerState::Error;
117                Err(format!("启动 {} 失败: {}", self.config.name, e))
118            }
119        }
120    }
121
122    /// 停止 LSP 服务器
123    pub async fn stop(&mut self) -> Result<(), String> {
124        let mut state = self.state.write().await;
125        if *state == LSPServerState::Stopped {
126            return Ok(());
127        }
128
129        // 杀死进程
130        if let Some(mut child) = self.process.write().await.take() {
131            let _ = child.kill().await;
132        }
133
134        *state = LSPServerState::Stopped;
135        tracing::info!("[LSP] {} 已停止", self.config.name);
136        Ok(())
137    }
138
139    /// 获取状态
140    pub async fn get_state(&self) -> LSPServerState {
141        *self.state.read().await
142    }
143
144    /// 获取配置
145    pub fn get_config(&self) -> &LSPServerConfig {
146        &self.config
147    }
148
149    /// 检查服务器是否健康
150    pub async fn is_healthy(&self) -> bool {
151        *self.state.read().await == LSPServerState::Ready
152    }
153
154    /// 获取重启次数
155    pub async fn get_restart_count(&self) -> u32 {
156        *self.restart_count.read().await
157    }
158
159    /// 打开文档
160    pub async fn open_document(&self, file_path: &Path, content: &str, language_id: &str) {
161        let uri = format!("file://{}", file_path.display());
162        let doc = OpenDocument {
163            uri: uri.clone(),
164            language_id: language_id.to_string(),
165            version: 1,
166            content: content.to_string(),
167        };
168        self.open_documents
169            .write()
170            .await
171            .insert(file_path.display().to_string(), doc);
172    }
173
174    /// 关闭文档
175    pub async fn close_document(&self, file_path: &Path) {
176        self.open_documents
177            .write()
178            .await
179            .remove(&file_path.display().to_string());
180    }
181
182    /// 检查文档是否打开
183    pub async fn is_document_open(&self, file_path: &Path) -> bool {
184        self.open_documents
185            .read()
186            .await
187            .contains_key(&file_path.display().to_string())
188    }
189
190    /// 获取下一个请求 ID
191    fn next_id(&self) -> u64 {
192        self.next_request_id.fetch_add(1, Ordering::SeqCst)
193    }
194}