diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index ea7a6694fa..65294974e7 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -138,8 +138,16 @@ struct AnyResponse<'a> { struct Response { jsonrpc: &'static str, id: RequestId, - result: Option, - error: Option, + #[serde(flatten)] + value: LspResult, +} + +#[derive(Serialize)] +#[serde(rename_all = "snake_case")] +enum LspResult { + #[serde(rename = "result")] + Ok(Option), + Error(Option), } /// Language server protocol RPC notification message. @@ -867,16 +875,14 @@ impl LanguageServer { Ok(result) => Response { jsonrpc: JSON_RPC_VERSION, id, - result: Some(result), - error: None, + value: LspResult::Ok(Some(result)), }, Err(error) => Response { jsonrpc: JSON_RPC_VERSION, id, - result: None, - error: Some(Error { + value: LspResult::Error(Some(Error { message: error.to_string(), - }), + })), }, }; if let Some(response) = @@ -1503,4 +1509,27 @@ mod tests { let expected_id = RequestId::Int(2); assert_eq!(notification.id, Some(expected_id)); } + + #[test] + fn test_serialize_has_no_nulls() { + // Ensure we're not setting both result and error variants. (ticket #10595) + let no_tag = Response:: { + jsonrpc: "", + id: RequestId::Int(0), + value: LspResult::Ok(None), + }; + assert_eq!( + serde_json::to_string(&no_tag).unwrap(), + "{\"jsonrpc\":\"\",\"id\":0,\"result\":null}" + ); + let no_tag = Response:: { + jsonrpc: "", + id: RequestId::Int(0), + value: LspResult::Error(None), + }; + assert_eq!( + serde_json::to_string(&no_tag).unwrap(), + "{\"jsonrpc\":\"\",\"id\":0,\"error\":null}" + ); + } }