diff options
author | Michael Davis | 2023-01-10 09:31:41 +0000 |
---|---|---|
committer | GitHub | 2023-01-10 09:31:41 +0000 |
commit | 22298434f10e203bc1adb8eebfdfbfbff05db977 (patch) | |
tree | ae94944949a012b41bed93ad10d5be55af66459b /helix-lsp | |
parent | 2d601d6a59dd46cccfcbda625387f21981e0a8a5 (diff) |
jsonrpc: Skip serializing params if params are None (#5471)
The JSONRPC spec says:
> If present, parameters for the rpc call MUST be provided as a
> Structured value
https://www.jsonrpc.org/specification#parameter_structures
(Where a "Structured value" is elsewhere defined as either a map or
array.)
This change skips the serialization of the `params` field for JSONRPC
method calls and notifications if the `params` field is the `None`
variant. This fixes compatibility with LSP servers which adhere closely
to that part of the spec: `ocamllsp` in the wild.
Diffstat (limited to 'helix-lsp')
-rw-r--r-- | helix-lsp/src/jsonrpc.rs | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/helix-lsp/src/jsonrpc.rs b/helix-lsp/src/jsonrpc.rs index 75ac9309..69d02707 100644 --- a/helix-lsp/src/jsonrpc.rs +++ b/helix-lsp/src/jsonrpc.rs @@ -170,6 +170,10 @@ impl Params { serde_json::from_value(value) .map_err(|err| Error::invalid_params(format!("Invalid params: {}.", err))) } + + pub fn is_none(&self) -> bool { + self == &Params::None + } } impl From<Params> for Value { @@ -187,7 +191,7 @@ impl From<Params> for Value { pub struct MethodCall { pub jsonrpc: Option<Version>, pub method: String, - #[serde(default = "default_params")] + #[serde(default = "default_params", skip_serializing_if = "Params::is_none")] pub params: Params, pub id: Id, } @@ -197,7 +201,7 @@ pub struct MethodCall { pub struct Notification { pub jsonrpc: Option<Version>, pub method: String, - #[serde(default = "default_params")] + #[serde(default = "default_params", skip_serializing_if = "Params::is_none")] pub params: Params, } @@ -335,6 +339,33 @@ fn notification_serialize() { } #[test] +fn serialize_skip_none_params() { + use serde_json; + + let m = MethodCall { + jsonrpc: Some(Version::V2), + method: "shutdown".to_owned(), + params: Params::None, + id: Id::Num(1), + }; + + let serialized = serde_json::to_string(&m).unwrap(); + assert_eq!( + serialized, + r#"{"jsonrpc":"2.0","method":"shutdown","id":1}"# + ); + + let n = Notification { + jsonrpc: Some(Version::V2), + method: "exit".to_owned(), + params: Params::None, + }; + + let serialized = serde_json::to_string(&n).unwrap(); + assert_eq!(serialized, r#"{"jsonrpc":"2.0","method":"exit"}"#); +} + +#[test] fn success_output_deserialize() { use serde_json; |