tower_lsp/
jsonrpc.rs

1//! A subset of JSON-RPC types used by the Language Server Protocol.
2
3pub(crate) use self::error::not_initialized_error;
4pub use self::error::{Error, ErrorCode, Result};
5pub use self::request::{Request, RequestBuilder};
6pub use self::response::Response;
7pub(crate) use self::router::Router;
8pub use self::router::{FromParams, IntoResponse, Method};
9
10use std::borrow::Cow;
11use std::fmt::{self, Debug, Display, Formatter};
12
13use lsp_types::NumberOrString;
14use serde::de::{self, Deserializer};
15use serde::ser::Serializer;
16use serde::{Deserialize, Serialize};
17
18mod error;
19mod request;
20mod response;
21mod router;
22
23/// A unique ID used to correlate requests and responses together.
24#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
25#[serde(untagged)]
26pub enum Id {
27    /// Numeric ID.
28    Number(i64),
29    /// String ID.
30    String(String),
31    /// Null ID.
32    ///
33    /// While `null` is considered a valid request ID by the JSON-RPC 2.0 specification, its use is
34    /// _strongly_ discouraged because the specification also uses a `null` value to indicate an
35    /// unknown ID in the [`Response`] object.
36    Null,
37}
38
39impl Default for Id {
40    fn default() -> Self {
41        Id::Null
42    }
43}
44
45impl Display for Id {
46    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
47        match self {
48            Id::Number(id) => Display::fmt(id, f),
49            Id::String(id) => Debug::fmt(id, f),
50            Id::Null => f.write_str("null"),
51        }
52    }
53}
54
55impl From<i64> for Id {
56    fn from(n: i64) -> Self {
57        Id::Number(n)
58    }
59}
60
61impl From<&'_ str> for Id {
62    fn from(s: &'_ str) -> Self {
63        Id::String(s.to_string())
64    }
65}
66
67impl From<String> for Id {
68    fn from(s: String) -> Self {
69        Id::String(s)
70    }
71}
72
73impl From<NumberOrString> for Id {
74    fn from(num_or_str: NumberOrString) -> Self {
75        match num_or_str {
76            NumberOrString::Number(num) => Id::Number(num as i64),
77            NumberOrString::String(s) => Id::String(s),
78        }
79    }
80}
81
82#[derive(Clone, Debug, PartialEq)]
83struct Version;
84
85impl<'de> Deserialize<'de> for Version {
86    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
87    where
88        D: Deserializer<'de>,
89    {
90        #[derive(Deserialize)]
91        struct Inner<'a>(#[serde(borrow)] Cow<'a, str>);
92
93        let Inner(ver) = Inner::deserialize(deserializer)?;
94
95        match ver.as_ref() {
96            "2.0" => Ok(Version),
97            _ => Err(de::Error::custom("expected JSON-RPC version \"2.0\"")),
98        }
99    }
100}
101
102impl Serialize for Version {
103    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
104    where
105        S: Serializer,
106    {
107        serializer.serialize_str("2.0")
108    }
109}
110
111/// An incoming or outgoing JSON-RPC message.
112#[derive(Deserialize, Serialize)]
113#[cfg_attr(test, derive(Debug, PartialEq))]
114#[serde(untagged)]
115pub(crate) enum Message {
116    /// A response message.
117    Response(Response),
118    /// A request or notification message.
119    Request(Request),
120}
121
122#[cfg(test)]
123mod tests {
124    use serde_json::json;
125
126    use super::*;
127
128    #[test]
129    fn incoming_from_str_or_value() {
130        let v = json!({"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":0});
131        let from_str: Message = serde_json::from_str(&v.to_string()).unwrap();
132        let from_value: Message = serde_json::from_value(v).unwrap();
133        assert_eq!(from_str, from_value);
134    }
135
136    #[test]
137    fn outgoing_from_str_or_value() {
138        let v = json!({"jsonrpc":"2.0","result":{},"id":1});
139        let from_str: Message = serde_json::from_str(&v.to_string()).unwrap();
140        let from_value: Message = serde_json::from_value(v).unwrap();
141        assert_eq!(from_str, from_value);
142    }
143
144    #[test]
145    fn parses_incoming_message() {
146        let server_request =
147            json!({"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":0});
148        let incoming = serde_json::from_value(server_request).unwrap();
149        assert!(matches!(incoming, Message::Request(_)));
150
151        let server_notif = json!({"jsonrpc":"2.0","method":"initialized","params":{}});
152        let incoming = serde_json::from_value(server_notif).unwrap();
153        assert!(matches!(incoming, Message::Request(_)));
154
155        let client_request = json!({"jsonrpc":"2.0","id":0,"result":[null]});
156        let incoming = serde_json::from_value(client_request).unwrap();
157        assert!(matches!(incoming, Message::Response(_)));
158    }
159
160    #[test]
161    fn parses_outgoing_message() {
162        let client_request = json!({"jsonrpc":"2.0","method":"workspace/configuration","params":{"scopeUri":null,"section":"foo"},"id":0});
163        let outgoing = serde_json::from_value(client_request).unwrap();
164        assert!(matches!(outgoing, Message::Request(_)));
165
166        let client_notif = json!({"jsonrpc":"2.0","method":"window/logMessage","params":{"message":"foo","type":0}});
167        let outgoing = serde_json::from_value(client_notif).unwrap();
168        assert!(matches!(outgoing, Message::Request(_)));
169
170        let server_response = json!({"jsonrpc":"2.0","id":0,"result":[null]});
171        let outgoing = serde_json::from_value(server_response).unwrap();
172        assert!(matches!(outgoing, Message::Response(_)));
173    }
174
175    #[test]
176    fn parses_invalid_server_request() {
177        let unknown_method = json!({"jsonrpc":"2.0","method":"foo"});
178        let incoming = serde_json::from_value(unknown_method).unwrap();
179        assert!(matches!(incoming, Message::Request(_)));
180
181        let unknown_method_with_id = json!({"jsonrpc":"2.0","method":"foo","id":0});
182        let incoming = serde_json::from_value(unknown_method_with_id).unwrap();
183        assert!(matches!(incoming, Message::Request(_)));
184
185        let missing_method = json!({"jsonrpc":"2.0"});
186        let incoming = serde_json::from_value(missing_method).unwrap();
187        assert!(matches!(incoming, Message::Request(_)));
188
189        let missing_method_with_id = json!({"jsonrpc":"2.0","id":0});
190        let incoming = serde_json::from_value(missing_method_with_id).unwrap();
191        assert!(matches!(incoming, Message::Request(_)));
192    }
193
194    #[test]
195    fn accepts_null_request_id() {
196        let request_id: Id = serde_json::from_value(json!(null)).unwrap();
197        assert_eq!(request_id, Id::Null);
198    }
199
200    #[test]
201    fn accepts_negative_integer_request_id() {
202        let request_id: Id = serde_json::from_value(json!(-1)).unwrap();
203        assert_eq!(request_id, Id::Number(-1));
204    }
205}