Skip to main content

lsp_server/
msg.rs

1use std::{
2    fmt,
3    io::{self, BufRead, Write},
4};
5
6use serde::de::DeserializeOwned;
7use serde_derive::{Deserialize, Serialize};
8
9use crate::error::ExtractError;
10
11#[derive(Serialize, Deserialize, Debug, Clone)]
12#[serde(untagged)]
13pub enum Message {
14    Request(Request),
15    Response(Response),
16    Notification(Notification),
17}
18
19impl From<Request> for Message {
20    fn from(request: Request) -> Message {
21        Message::Request(request)
22    }
23}
24
25impl From<Response> for Message {
26    fn from(response: Response) -> Message {
27        Message::Response(response)
28    }
29}
30
31impl From<Notification> for Message {
32    fn from(notification: Notification) -> Message {
33        Message::Notification(notification)
34    }
35}
36
37#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
38#[serde(transparent)]
39pub struct RequestId(IdRepr);
40
41#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42#[serde(untagged)]
43enum IdRepr {
44    I32(i32),
45    String(String),
46}
47
48impl From<i32> for RequestId {
49    fn from(id: i32) -> RequestId {
50        RequestId(IdRepr::I32(id))
51    }
52}
53
54impl From<String> for RequestId {
55    fn from(id: String) -> RequestId {
56        RequestId(IdRepr::String(id))
57    }
58}
59
60impl fmt::Display for RequestId {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        match &self.0 {
63            IdRepr::I32(it) => fmt::Display::fmt(it, f),
64            // Use debug here, to make it clear that `92` and `"92"` are
65            // different, and to reduce WTF factor if the sever uses `" "` as an
66            // ID.
67            IdRepr::String(it) => fmt::Debug::fmt(it, f),
68        }
69    }
70}
71
72#[derive(Debug, Serialize, Deserialize, Clone)]
73pub struct Request {
74    pub id: RequestId,
75    pub method: String,
76    #[serde(default = "serde_json::Value::default")]
77    #[serde(skip_serializing_if = "serde_json::Value::is_null")]
78    pub params: serde_json::Value,
79}
80
81#[derive(Debug, Serialize, Deserialize, Clone)]
82pub struct Response {
83    // JSON-RPC allows this to be null if we can't find or parse the
84    // request id. We fail deserialization in that case, so we just
85    // make this field mandatory.
86    pub id: RequestId,
87    #[serde(flatten, with = "ResponseResult")]
88    pub response_result: Result<serde_json::Value, ResponseError>,
89}
90
91#[derive(Serialize, Deserialize)]
92#[serde(remote = "Result<serde_json::Value, ResponseError>")]
93enum ResponseResult {
94    #[serde(rename = "result")]
95    Ok(serde_json::Value),
96    #[serde(rename = "error")]
97    Err(ResponseError),
98}
99
100#[derive(Debug, Serialize, Deserialize, Clone)]
101pub struct ResponseError {
102    pub code: i32,
103    pub message: String,
104    #[serde(skip_serializing_if = "Option::is_none", default)]
105    pub data: Option<serde_json::Value>,
106}
107
108#[derive(Clone, Copy, Debug)]
109#[non_exhaustive]
110pub enum ErrorCode {
111    // Defined by JSON RPC:
112    ParseError = -32700,
113    InvalidRequest = -32600,
114    MethodNotFound = -32601,
115    InvalidParams = -32602,
116    InternalError = -32603,
117    ServerErrorStart = -32099,
118    ServerErrorEnd = -32000,
119
120    /// Error code indicating that a server received a notification or
121    /// request before the server has received the `initialize` request.
122    ServerNotInitialized = -32002,
123    UnknownErrorCode = -32001,
124
125    // Defined by the protocol:
126    /// The client has canceled a request and a server has detected
127    /// the cancel.
128    RequestCanceled = -32800,
129
130    /// The server detected that the content of a document got
131    /// modified outside normal conditions. A server should
132    /// NOT send this error code if it detects a content change
133    /// in it unprocessed messages. The result even computed
134    /// on an older state might still be useful for the client.
135    ///
136    /// If a client decides that a result is not of any use anymore
137    /// the client should cancel the request.
138    ContentModified = -32801,
139
140    /// The server cancelled the request. This error code should
141    /// only be used for requests that explicitly support being
142    /// server cancellable.
143    ///
144    /// @since 3.17.0
145    ServerCancelled = -32802,
146
147    /// A request failed but it was syntactically correct, e.g the
148    /// method name was known and the parameters were valid. The error
149    /// message should contain human readable information about why
150    /// the request failed.
151    ///
152    /// @since 3.17.0
153    RequestFailed = -32803,
154}
155
156#[derive(Debug, Serialize, Deserialize, Clone)]
157pub struct Notification {
158    pub method: String,
159    #[serde(default = "serde_json::Value::default")]
160    #[serde(skip_serializing_if = "serde_json::Value::is_null")]
161    pub params: serde_json::Value,
162}
163
164fn invalid_data(error: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
165    io::Error::new(io::ErrorKind::InvalidData, error)
166}
167
168macro_rules! invalid_data {
169    ($($tt:tt)*) => (invalid_data(format!($($tt)*)))
170}
171
172impl Message {
173    pub fn read(r: &mut impl BufRead) -> io::Result<Option<Message>> {
174        Message::_read(r)
175    }
176    fn _read(r: &mut dyn BufRead) -> io::Result<Option<Message>> {
177        let text = match read_msg_text(r)? {
178            None => return Ok(None),
179            Some(text) => text,
180        };
181
182        let msg = match serde_json::from_str(&text) {
183            Ok(msg) => msg,
184            Err(e) => {
185                return Err(invalid_data!("malformed LSP payload `{e:?}`: {text:?}"));
186            }
187        };
188
189        Ok(Some(msg))
190    }
191    pub fn write(&self, w: &mut impl Write) -> io::Result<()> {
192        self._write(w)
193    }
194    fn _write(&self, w: &mut dyn Write) -> io::Result<()> {
195        #[derive(Serialize)]
196        struct JsonRpc<'a> {
197            jsonrpc: &'static str,
198            #[serde(flatten)]
199            msg: &'a Message,
200        }
201        let text = serde_json::to_string(&JsonRpc { jsonrpc: "2.0", msg: self })?;
202        write_msg_text(w, &text)
203    }
204}
205
206impl Response {
207    pub fn new_ok<R: serde::Serialize>(id: RequestId, result: R) -> Response {
208        Response { id, response_result: Ok(serde_json::to_value(result).unwrap()) }
209    }
210    pub fn new_err(id: RequestId, code: i32, message: String) -> Response {
211        let error = ResponseError { code, message, data: None };
212        Response { id, response_result: Err(error) }
213    }
214}
215
216impl Request {
217    pub fn new<P: serde::Serialize>(id: RequestId, method: String, params: P) -> Request {
218        Request { id, method, params: serde_json::to_value(params).unwrap() }
219    }
220    pub fn extract<P: DeserializeOwned>(
221        self,
222        method: &str,
223    ) -> Result<(RequestId, P), ExtractError<Request>> {
224        if self.method != method {
225            return Err(ExtractError::MethodMismatch(self));
226        }
227        match serde_json::from_value(self.params) {
228            Ok(params) => Ok((self.id, params)),
229            Err(error) => Err(ExtractError::JsonError { method: self.method, error }),
230        }
231    }
232
233    pub(crate) fn is_shutdown(&self) -> bool {
234        self.method == "shutdown"
235    }
236    pub(crate) fn is_initialize(&self) -> bool {
237        self.method == "initialize"
238    }
239}
240
241impl Notification {
242    pub fn new(method: String, params: impl serde::Serialize) -> Notification {
243        Notification { method, params: serde_json::to_value(params).unwrap() }
244    }
245    pub fn extract<P: DeserializeOwned>(
246        self,
247        method: &str,
248    ) -> Result<P, ExtractError<Notification>> {
249        if self.method != method {
250            return Err(ExtractError::MethodMismatch(self));
251        }
252        match serde_json::from_value(self.params) {
253            Ok(params) => Ok(params),
254            Err(error) => Err(ExtractError::JsonError { method: self.method, error }),
255        }
256    }
257    pub(crate) fn is_exit(&self) -> bool {
258        self.method == "exit"
259    }
260    pub(crate) fn is_initialized(&self) -> bool {
261        self.method == "initialized"
262    }
263}
264
265fn read_msg_text(inp: &mut dyn BufRead) -> io::Result<Option<String>> {
266    let mut size = None;
267    let mut buf = String::new();
268    loop {
269        buf.clear();
270        if inp.read_line(&mut buf)? == 0 {
271            return Ok(None);
272        }
273        if !buf.ends_with("\r\n") {
274            return Err(invalid_data!("malformed header: {:?}", buf));
275        }
276        let buf = &buf[..buf.len() - 2];
277        if buf.is_empty() {
278            break;
279        }
280        let mut parts = buf.splitn(2, ": ");
281        let header_name = parts.next().unwrap();
282        let header_value =
283            parts.next().ok_or_else(|| invalid_data!("malformed header: {:?}", buf))?;
284        if header_name.eq_ignore_ascii_case("Content-Length") {
285            size = Some(header_value.parse::<usize>().map_err(invalid_data)?);
286        }
287    }
288    let size: usize = size.ok_or_else(|| invalid_data!("no Content-Length"))?;
289    let mut buf = buf.into_bytes();
290    buf.resize(size, 0);
291    inp.read_exact(&mut buf)?;
292    let buf = String::from_utf8(buf).map_err(invalid_data)?;
293    log::debug!("< {buf}");
294    Ok(Some(buf))
295}
296
297fn write_msg_text(out: &mut dyn Write, msg: &str) -> io::Result<()> {
298    log::debug!("> {msg}");
299    write!(out, "Content-Length: {}\r\n\r\n", msg.len())?;
300    out.write_all(msg.as_bytes())?;
301    out.flush()?;
302    Ok(())
303}
304
305#[cfg(test)]
306mod tests {
307    use super::{Message, Notification, Request, RequestId, Response};
308
309    #[test]
310    fn shutdown_with_explicit_null() {
311        let text = r#"{"jsonrpc": "2.0","id": 3,"method": "shutdown", "params": null }"#;
312        let msg: Message = serde_json::from_str(text).unwrap();
313
314        assert!(
315            matches!(msg, Message::Request(req) if req.id == 3.into() && req.method == "shutdown")
316        );
317    }
318
319    #[test]
320    fn shutdown_with_no_params() {
321        let text = r#"{"jsonrpc": "2.0","id": 3,"method": "shutdown"}"#;
322        let msg: Message = serde_json::from_str(text).unwrap();
323
324        assert!(
325            matches!(msg, Message::Request(req) if req.id == 3.into() && req.method == "shutdown")
326        );
327    }
328
329    #[test]
330    fn notification_with_explicit_null() {
331        let text = r#"{"jsonrpc": "2.0","method": "exit", "params": null }"#;
332        let msg: Message = serde_json::from_str(text).unwrap();
333
334        assert!(matches!(msg, Message::Notification(not) if not.method == "exit"));
335    }
336
337    #[test]
338    fn notification_with_no_params() {
339        let text = r#"{"jsonrpc": "2.0","method": "exit"}"#;
340        let msg: Message = serde_json::from_str(text).unwrap();
341
342        assert!(matches!(msg, Message::Notification(not) if not.method == "exit"));
343    }
344
345    #[test]
346    fn serialize_request_with_null_params() {
347        let msg = Message::Request(Request {
348            id: RequestId::from(3),
349            method: "shutdown".into(),
350            params: serde_json::Value::Null,
351        });
352        let serialized = serde_json::to_string(&msg).unwrap();
353
354        assert_eq!(r#"{"id":3,"method":"shutdown"}"#, serialized);
355    }
356
357    #[test]
358    fn serialize_notification_with_null_params() {
359        let msg = Message::Notification(Notification {
360            method: "exit".into(),
361            params: serde_json::Value::Null,
362        });
363        let serialized = serde_json::to_string(&msg).unwrap();
364
365        assert_eq!(r#"{"method":"exit"}"#, serialized);
366    }
367
368    #[test]
369    fn serialize_ok_response() {
370        let msg = Message::Response(Response::new_ok(RequestId::from(3), "success"));
371        let serialized = serde_json::to_string(&msg).unwrap();
372
373        assert_eq!(r#"{"id":3,"result":"success"}"#, serialized);
374    }
375
376    #[test]
377    fn serialize_err_response() {
378        let msg = Message::Response(Response::new_err(
379            RequestId::from(3),
380            -32600,
381            String::from("bad response message"),
382        ));
383        let serialized = serde_json::to_string(&msg).unwrap();
384
385        assert_eq!(
386            r#"{"id":3,"error":{"code":-32600,"message":"bad response message"}}"#,
387            serialized
388        );
389    }
390}