(config: LspServerConfig, root: PathBuf)
| 164 | |
| 165 | impl LspClient { |
| 166 | pub async fn start(config: LspServerConfig, root: PathBuf) -> Result<Self, LspError> { |
| 167 | let mut child = Command::new(&config.command) |
| 168 | .args(&config.args) |
| 169 | .stdin(Stdio::piped()) |
| 170 | .stdout(Stdio::piped()) |
| 171 | .stderr(Stdio::piped()) |
| 172 | .spawn() |
| 173 | .map_err(|e| LspError::ServerStartError(e.to_string()))?; |
| 174 | |
| 175 | let stdin = child |
| 176 | .stdin |
| 177 | .take() |
| 178 | .ok_or_else(|| LspError::ServerStartError("Failed to get stdin".to_string()))?; |
| 179 | let stdout = child |
| 180 | .stdout |
| 181 | .take() |
| 182 | .ok_or_else(|| LspError::ServerStartError("Failed to get stdout".to_string()))?; |
| 183 | |
| 184 | let (event_tx, _) = broadcast::channel(256); |
| 185 | |
| 186 | let client = Self { |
| 187 | root, |
| 188 | stdin: Arc::new(Mutex::new(stdin)), |
| 189 | request_id: Arc::new(Mutex::new(0)), |
| 190 | pending_responses: Arc::new(RwLock::new(HashMap::new())), |
| 191 | diagnostics: Arc::new(RwLock::new(HashMap::new())), |
| 192 | file_versions: Arc::new(RwLock::new(HashMap::new())), |
| 193 | event_tx, |
| 194 | }; |
| 195 | |
| 196 | let pending = client.pending_responses.clone(); |
| 197 | let diagnostics = client.diagnostics.clone(); |
| 198 | let server_id = config.id.clone(); |
| 199 | let event_tx_clone = client.event_tx.clone(); |
| 200 | |
| 201 | tokio::spawn(async move { |
| 202 | let reader = BufReader::new(stdout); |
| 203 | let mut lines = reader.lines(); |
| 204 | |
| 205 | while let Ok(Some(line)) = lines.next_line().await { |
| 206 | if line.is_empty() || line.starts_with("Content-Length:") { |
| 207 | continue; |
| 208 | } |
| 209 | |
| 210 | if let Ok(notification) = serde_json::from_str::<JsonRpcNotification>(&line) { |
| 211 | if notification.method == "textDocument/publishDiagnostics" { |
| 212 | if let Some(params) = notification.params { |
| 213 | if let Ok(diag_params) = serde_json::from_value::< |
| 214 | lsp_types::PublishDiagnosticsParams, |
| 215 | >(params) |
| 216 | { |
| 217 | let path = uri_to_path(&diag_params.uri); |
| 218 | |
| 219 | diagnostics |
| 220 | .write() |
| 221 | .await |
| 222 | .insert(path.clone(), diag_params.diagnostics); |
| 223 |
no test coverage detected