Always respond to language server, even when its requests are malformed

Antonio Scandurra and Petros Amoiridis created

This was causing Pyright to get stuck waiting for a response when sending
us the `workspace/configuration` request. For some reason, after upgrading
to Pyright 1.1.293, `scopeUri` is being sent as an empty string sometimes,
which causes serde to error when trying to deserialize that request.

Co-Authored-By: Petros Amoiridis <petros@zed.dev>

Change summary

crates/lsp/src/lsp.rs | 84 ++++++++++++++++++++++++++++----------------
1 file changed, 54 insertions(+), 30 deletions(-)

Detailed changes

crates/lsp/src/lsp.rs 🔗

@@ -65,6 +65,7 @@ struct Request<'a, T> {
 
 #[derive(Serialize, Deserialize)]
 struct AnyResponse<'a> {
+    jsonrpc: &'a str,
     id: usize,
     #[serde(default)]
     error: Option<Error>,
@@ -204,8 +205,9 @@ impl LanguageServer {
                         } else {
                             on_unhandled_notification(msg);
                         }
-                    } else if let Ok(AnyResponse { id, error, result }) =
-                        serde_json::from_slice(&buffer)
+                    } else if let Ok(AnyResponse {
+                        id, error, result, ..
+                    }) = serde_json::from_slice(&buffer)
                     {
                         if let Some(handler) = response_handlers
                             .lock()
@@ -461,35 +463,57 @@ impl LanguageServer {
             method,
             Box::new(move |id, params, cx| {
                 if let Some(id) = id {
-                    if let Some(params) = serde_json::from_str(params).log_err() {
-                        let response = f(params, cx.clone());
-                        cx.foreground()
-                            .spawn({
-                                let outbound_tx = outbound_tx.clone();
-                                async move {
-                                    let response = match response.await {
-                                        Ok(result) => Response {
-                                            jsonrpc: JSON_RPC_VERSION,
-                                            id,
-                                            result: Some(result),
-                                            error: None,
-                                        },
-                                        Err(error) => Response {
-                                            jsonrpc: JSON_RPC_VERSION,
-                                            id,
-                                            result: None,
-                                            error: Some(Error {
-                                                message: error.to_string(),
-                                            }),
-                                        },
-                                    };
-                                    if let Some(response) = serde_json::to_vec(&response).log_err()
-                                    {
-                                        outbound_tx.try_send(response).ok();
+                    match serde_json::from_str(params) {
+                        Ok(params) => {
+                            let response = f(params, cx.clone());
+                            cx.foreground()
+                                .spawn({
+                                    let outbound_tx = outbound_tx.clone();
+                                    async move {
+                                        let response = match response.await {
+                                            Ok(result) => Response {
+                                                jsonrpc: JSON_RPC_VERSION,
+                                                id,
+                                                result: Some(result),
+                                                error: None,
+                                            },
+                                            Err(error) => Response {
+                                                jsonrpc: JSON_RPC_VERSION,
+                                                id,
+                                                result: None,
+                                                error: Some(Error {
+                                                    message: error.to_string(),
+                                                }),
+                                            },
+                                        };
+                                        if let Some(response) =
+                                            serde_json::to_vec(&response).log_err()
+                                        {
+                                            outbound_tx.try_send(response).ok();
+                                        }
                                     }
-                                }
-                            })
-                            .detach();
+                                })
+                                .detach();
+                        }
+                        Err(error) => {
+                            log::error!(
+                                "error deserializing {} request: {:?}, message: {:?}",
+                                method,
+                                error,
+                                params
+                            );
+                            let response = AnyResponse {
+                                jsonrpc: JSON_RPC_VERSION,
+                                id,
+                                result: None,
+                                error: Some(Error {
+                                    message: error.to_string(),
+                                }),
+                            };
+                            if let Some(response) = serde_json::to_vec(&response).log_err() {
+                                outbound_tx.try_send(response).ok();
+                            }
+                        }
                     }
                 }
             }),