Starts the message reader task.
(&self, stdout: ChildStdout)
| 146 | |
| 147 | /// Starts the message reader task. |
| 148 | async fn start_read_task(&self, stdout: ChildStdout) { |
| 149 | let pending_requests = self.pending_requests.clone(); |
| 150 | let notification_tx = self.notification_tx.clone(); |
| 151 | let id = self.id.clone(); |
| 152 | let crash_callback = self.crash_callback.clone(); |
| 153 | |
| 154 | tokio::spawn(async move { |
| 155 | let mut reader = BufReader::new(stdout); |
| 156 | let mut consecutive_timeouts = 0; |
| 157 | const MAX_CONSECUTIVE_TIMEOUTS: u32 = 3; |
| 158 | |
| 159 | loop { |
| 160 | match timeout(Duration::from_secs(30), read_message(&mut reader)).await { |
| 161 | Ok(Ok(message)) => { |
| 162 | consecutive_timeouts = 0; |
| 163 | |
| 164 | match &message { |
| 165 | JsonRpcMessage::Response(response) => { |
| 166 | let request_id = response.id; |
| 167 | let mut pending = pending_requests.write().await; |
| 168 | |
| 169 | if let Some(sender) = pending.remove(&request_id) { |
| 170 | let _ = sender.send(response.clone()); |
| 171 | } else { |
| 172 | warn!( |
| 173 | "[{}] Received response for unknown request ID: {}", |
| 174 | id, request_id |
| 175 | ); |
| 176 | } |
| 177 | } |
| 178 | JsonRpcMessage::Notification(_) => { |
| 179 | if let Err(e) = notification_tx.send(message) { |
| 180 | error!("[{}] Failed to send notification: {}", id, e); |
| 181 | break; |
| 182 | } |
| 183 | } |
| 184 | JsonRpcMessage::Request(_req) => { |
| 185 | if let Err(e) = notification_tx.send(message) { |
| 186 | error!("[{}] Failed to send request: {}", id, e); |
| 187 | break; |
| 188 | } |
| 189 | } |
| 190 | } |
| 191 | } |
| 192 | Ok(Err(e)) => { |
| 193 | error!("[{}] Failed to read message: {}", id, e); |
| 194 | error!("[{}] This usually means the LSP server is outputting non-protocol data to stdout", id); |
| 195 | break; |
| 196 | } |
| 197 | Err(_) => { |
| 198 | consecutive_timeouts += 1; |
| 199 | |
| 200 | if consecutive_timeouts >= MAX_CONSECUTIVE_TIMEOUTS { |
| 201 | warn!( |
| 202 | "[{}] No LSP messages for {}s (this is normal if idle)", |
| 203 | id, |
| 204 | 30 * MAX_CONSECUTIVE_TIMEOUTS |
| 205 | ); |