Skip to main content

lsp_service/jsonrpc/
response.rs

1use serde::{Deserialize, Deserializer, Serialize, de::Error};
2use serde_json::{Value, json, to_value};
3
4use super::{ErrorCode, Id};
5
6/// A Response Message sent as a result of a request
7///
8/// As defined in [JSON-RPC](https://www.jsonrpc.org/specification#response_object) and [LSP](https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#responseMessage).
9///
10/// Can either be [`Ok`] (the response had a `result`, and did not have attached `error` information),
11/// or as [`Err`] (the response had no `result`, instead having attached `error` information).
12///
13/// Both [`Ok`] and [`Err`] have an [`Id`] which matches the [`Id`] of the [`super::Request`] object.
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub enum Response {
16	/// [`Ok`]s also have an optional payload (serialised as a serde [`Value`]) which may contain more data about the
17	/// response, such as computed values.
18	Ok(Id, Value),
19	/// [`Err`]s also have an [`ErrorCode`] to determine which error occurred, an informatinal [`String`], and may contain
20	/// additional data (serialised as serde [`Value`]).
21	Err(Id, ErrorCode, String, Value),
22}
23
24impl Serialize for Response {
25	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
26	where
27		S: serde::Serializer,
28	{
29		#[derive(Serialize)]
30		struct Res<'a> {
31			id: &'a Id,
32			#[serde(skip_serializing_if = "Option::is_none")]
33			result: Option<&'a Value>,
34			#[serde(skip_serializing_if = "Option::is_none")]
35			error: Option<Value>,
36		}
37		if let Response::Ok(id, value) = self {
38			Res { id, result: Some(value), error: None }.serialize(serializer)
39		} else if let Response::Err(id, code, message, value) = self {
40			Res {
41				id,
42				result: None,
43				error: Some(json!({
44					"code": code, "message": message, "data": value
45				})),
46			}
47			.serialize(serializer)
48		} else {
49			unreachable!()
50		}
51	}
52}
53
54impl<'de> Deserialize<'de> for Response {
55	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
56	where
57		D: Deserializer<'de>,
58	{
59		#[derive(Deserialize)]
60		struct Err {
61			code: i32,
62			message: String,
63			#[serde(default = "serde_json::Value::default")]
64			data: Value,
65		}
66
67		fn present<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Option<Value>, D::Error> {
68			Value::deserialize(deserializer).map(Some)
69		}
70
71		#[derive(Deserialize)]
72		struct Res {
73			id: Id,
74			#[serde(default, deserialize_with = "present")]
75			result: Option<Value>,
76			error: Option<Err>,
77		}
78
79		let res = Res::deserialize(deserializer)?;
80		if let Some(result) = res.result {
81			if res.error.is_some() {
82				Err(Error::duplicate_field("error"))?
83			}
84			Ok(Response::Ok(res.id, result))
85		} else if let Some(error) = res.error {
86			if res.result.is_some() {
87				Err(Error::duplicate_field("result"))?
88			}
89			Ok(Response::Err(res.id, error.code.into(), error.message, error.data))
90		} else {
91			Err(Error::missing_field("result"))?
92		}
93	}
94}
95
96impl Response {
97	pub fn new_ok<T>(id: Id, result: T) -> Response
98	where
99		T: Serialize,
100	{
101		Response::Ok(id, to_value(result).unwrap())
102	}
103
104	pub fn new_err<T>(id: Id, error_code: ErrorCode, message: String, value: T) -> Response
105	where
106		T: Serialize,
107	{
108		Response::Err(id, error_code, message, to_value(value).unwrap())
109	}
110}
111
112/// The error a [`Handler`](crate::Handler) answers a request with: what went wrong, and the message the client shows.
113#[derive(Debug, Clone, PartialEq, Eq)]
114pub struct ResponseError {
115	pub code: ErrorCode,
116	pub message: String,
117}
118
119impl ResponseError {
120	pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
121		Self { code, message: message.into() }
122	}
123}
124
125impl From<ErrorCode> for ResponseError {
126	/// An error whose message names `code`.
127	fn from(code: ErrorCode) -> Self {
128		Self { code, message: format!("{code:?}") }
129	}
130}
131
132#[cfg(test)]
133mod tests {
134	use serde_json::{from_str, json, to_string};
135
136	use super::*;
137
138	#[test]
139	fn test_response_serialize_ok_omits_error() {
140		let response = Response::Ok(1.into(), json!({"capabilities": {}}));
141		let serialized = to_string(&response).unwrap();
142		assert!(serialized.contains("\"result\""), "should contain result");
143		assert!(!serialized.contains("\"error\""), "should not contain error key");
144		assert_eq!(serialized, r#"{"id":1,"result":{"capabilities":{}}}"#);
145	}
146
147	#[test]
148	fn test_response_serialize_err_omits_result() {
149		let response = Response::Err(1.into(), ErrorCode::ParseError, "Parse error".into(), Value::Null);
150		let serialized = to_string(&response).unwrap();
151		assert!(serialized.contains("\"error\""), "should contain error");
152		assert!(!serialized.contains("\"result\""), "should not contain result key");
153	}
154
155	#[test]
156	fn test_response_deserialize() {
157		assert_eq!(from_str::<Response>(r#"{"id":3, "result":7}"#).unwrap(), Response::Ok(3.into(), json!(7)));
158		assert_eq!(
159			from_str::<Response>(r#"{"id":4, "result":["a", "b"]}"#).unwrap(),
160			Response::Ok(4.into(), json!(["a", "b"]))
161		);
162		assert_eq!(from_str::<Response>(r#"{"id":5, "result":null}"#).unwrap(), Response::Ok(5.into(), Value::Null));
163		assert_eq!(
164			from_str::<Response>(r#"{"id":"a", "error":{"code": -32700, "message": "Parse error"}}"#).unwrap(),
165			Response::Err("a".into(), ErrorCode::ParseError, "Parse error".into(), Value::Null)
166		);
167		assert_eq!(
168			from_str::<Response>(
169				r#"{"id":"foo", "error":{"code": -32600, "message": "Invalid Request", "data": ["foo"]}}"#
170			)
171			.unwrap(),
172			Response::Err("foo".into(), ErrorCode::InvalidRequest, "Invalid Request".into(), json!(["foo"]))
173		);
174	}
175
176	#[test]
177	fn test_response_deserialize_error() {
178		// Missing result/error
179		assert!(from_str::<Response>(r#"{"id":3}"#).is_err());
180
181		// Missing error Code/Message
182		assert!(from_str::<Response>(r#"{"id":3, "error":{}}"#).is_err());
183
184		// Missing error Message
185		assert!(from_str::<Response>(r#"{"id":3, "error":{"code":0}}"#).is_err());
186
187		// Missing error Code
188		assert!(from_str::<Response>(r#"{"id":3, "error":{"message":""}}"#).is_err());
189
190		// Both error/result present
191		assert!(from_str::<Response>(r#"{"id":3, "error":{"code":0, "message": ""}, "result":7}"#).is_err());
192		assert!(from_str::<Response>(r#"{"id":3, "result":7, "error":{"code":0, "message": ""}}"#).is_err());
193	}
194}