lsp: Skip serializing of params if unit type (#46027)

Closes #45994 

Per the JSON-RPC specification, `params` "MUST be provided as a
Structured value" or the member "MAY be omitted." See specification
here: https://www.jsonrpc.org/specification#request_object

The code was passing in unit `()` for params which serde_json was
serializing to `null` which is not valid.

This pulls request adds an `is_unit` function and annotates the `params`
fields in the `Request` and `Notification` structs with the following:
 ```rs
#[serde(default, skip_serializing_if = "is_unit")]
```

so that the field will be omitted if the type is unit. This does also introduce a `'static` bound to these structs.

> [!WARNING]
> While this seems to me like a simple change, I am not super familiar with Rust, please look at this PR with extra scrutiny. The last thing I want to do is break everyone's LSP integration.


Release Notes:
- LSP integrations: send language server shutdown requests with correct parameters
This commit is contained in:
Michael Barth authored and GitHub committed 2026-01-22 15:06:02 +02:00
1 parent c0baaadc05
commit f2f900bbd5
1 file changed
+15 -2
+15 -2
View File
@@ -25,6 +25,7 @@ use smol::{
};
use std::{
any::TypeId,
collections::BTreeSet,
ffi::{OsStr, OsString},
fmt,
@@ -200,14 +201,22 @@ pub enum RequestId {
Str(String),
}
fn is_unit<T: 'static>(_: &T) -> bool {
TypeId::of::<T>() == TypeId::of::<()>()
}
/// Language server protocol RPC request message.
///
/// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage)
#[derive(Serialize, Deserialize)]
pub struct Request<'a, T> {
pub struct Request<'a, T>
where
T: 'static,
{
jsonrpc: &'static str,
id: RequestId,
method: &'a str,
#[serde(default, skip_serializing_if = "is_unit")]
params: T,
}
@@ -245,10 +254,14 @@ enum LspResult<T> {
///
/// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#notificationMessage)
#[derive(Serialize, Deserialize)]
struct Notification<'a, T> {
struct Notification<'a, T>
where
T: 'static,
{
jsonrpc: &'static str,
#[serde(borrow)]
method: &'a str,
#[serde(default, skip_serializing_if = "is_unit")]
params: T,
}