Skip to main content

lsp_max/jsonrpc/
error.rs

1//! Error types defined by the JSON-RPC specification.
2
3use std::borrow::Cow;
4use std::fmt::{self, Display, Formatter};
5
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8
9/// A specialized [`Result`] error type for JSON-RPC handlers.
10///
11/// [`Result`]: enum@std::result::Result
12pub type Result<T> = std::result::Result<T, Error>;
13
14/// A list of numeric error codes used in JSON-RPC responses.
15#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
16#[serde(into = "i64", from = "i64")]
17pub enum ErrorCode {
18    /// Invalid JSON was received by the server.
19    ParseError,
20    /// The JSON sent is not a valid Request object.
21    InvalidRequest,
22    /// The method does not exist / is not available.
23    MethodNotFound,
24    /// Invalid method parameter(s).
25    InvalidParams,
26    /// Internal JSON-RPC error.
27    InternalError,
28    /// Reserved for implementation-defined server errors.
29    ServerError(i64),
30
31    /// Error response returned for every request received before the server is initialized.
32    ///
33    /// # Compatibility
34    ///
35    /// This error code is defined by the Language Server Protocol.
36    ServerNotInitialized,
37    /// The request was cancelled by the client.
38    ///
39    /// # Compatibility
40    ///
41    /// This error code is defined by the Language Server Protocol.
42    RequestCancelled,
43    /// The request was invalidated by another incoming request.
44    ///
45    /// # Compatibility
46    ///
47    /// This error code is specific to the Language Server Protocol.
48    ContentModified,
49    /// The request failed for some reason.
50    ///
51    /// # Compatibility
52    ///
53    /// This error code is defined by the Language Server Protocol.
54    RequestFailed,
55    /// The server cancelled the request for some reason.
56    ///
57    /// # Compatibility
58    ///
59    /// This error code is defined by the Language Server Protocol.
60    ServerCancelled,
61}
62
63impl ErrorCode {
64    /// Returns the integer error code value.
65    pub const fn code(&self) -> i64 {
66        match *self {
67            ErrorCode::ParseError => -32700,
68            ErrorCode::InvalidRequest => -32600,
69            ErrorCode::MethodNotFound => -32601,
70            ErrorCode::InvalidParams => -32602,
71            ErrorCode::InternalError => -32603,
72            ErrorCode::ServerNotInitialized => -32002,
73            ErrorCode::RequestCancelled => -32800,
74            ErrorCode::ContentModified => -32801,
75            ErrorCode::ServerCancelled => -32802,
76            ErrorCode::RequestFailed => -32803,
77            ErrorCode::ServerError(code) => code,
78        }
79    }
80
81    /// Returns a human-readable description of the error.
82    pub const fn description(&self) -> &'static str {
83        match *self {
84            ErrorCode::ParseError => "Parse error",
85            ErrorCode::InvalidRequest => "Invalid request",
86            ErrorCode::MethodNotFound => "Method not found",
87            ErrorCode::InvalidParams => "Invalid params",
88            ErrorCode::InternalError => "Internal error",
89            ErrorCode::ServerNotInitialized => "Server not initialized",
90            ErrorCode::RequestCancelled => "Canceled",
91            ErrorCode::ContentModified => "Content modified",
92            ErrorCode::ServerCancelled => "Server cancelled",
93            ErrorCode::RequestFailed => "Request failed",
94            ErrorCode::ServerError(_) => "Server error",
95        }
96    }
97}
98
99impl From<i64> for ErrorCode {
100    fn from(code: i64) -> Self {
101        match code {
102            -32700 => ErrorCode::ParseError,
103            -32600 => ErrorCode::InvalidRequest,
104            -32601 => ErrorCode::MethodNotFound,
105            -32602 => ErrorCode::InvalidParams,
106            -32603 => ErrorCode::InternalError,
107            -32002 => ErrorCode::ServerNotInitialized,
108            -32800 => ErrorCode::RequestCancelled,
109            -32801 => ErrorCode::ContentModified,
110            -32802 => ErrorCode::ServerCancelled,
111            -32803 => ErrorCode::RequestFailed,
112            code => ErrorCode::ServerError(code),
113        }
114    }
115}
116
117impl From<ErrorCode> for i64 {
118    fn from(code: ErrorCode) -> Self {
119        code.code()
120    }
121}
122
123impl Display for ErrorCode {
124    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
125        Display::fmt(&self.code(), f)
126    }
127}
128
129/// A JSON-RPC error object.
130#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
131#[serde(deny_unknown_fields)]
132pub struct Error {
133    /// A number indicating the error type that occurred.
134    pub code: ErrorCode,
135    /// A short description of the error.
136    pub message: Cow<'static, str>,
137    /// Additional information about the error, if any.
138    #[serde(skip_serializing_if = "Option::is_none")]
139    pub data: Option<Value>,
140}
141
142impl Error {
143    /// Creates a new error from the given `ErrorCode`.
144    pub const fn new(code: ErrorCode) -> Self {
145        Error {
146            code,
147            message: Cow::Borrowed(code.description()),
148            data: None,
149        }
150    }
151
152    /// Creates a new parse error (`-32700`).
153    pub const fn parse_error() -> Self {
154        Error::new(ErrorCode::ParseError)
155    }
156
157    /// Creates a new "invalid request" error (`-32600`).
158    pub const fn invalid_request() -> Self {
159        Error::new(ErrorCode::InvalidRequest)
160    }
161
162    /// Creates a new "method not found" error (`-32601`).
163    pub const fn method_not_found() -> Self {
164        Error::new(ErrorCode::MethodNotFound)
165    }
166
167    /// Creates a new "invalid params" error (`-32602`).
168    pub fn invalid_params<M>(message: M) -> Self
169    where
170        M: Into<Cow<'static, str>>,
171    {
172        Error {
173            code: ErrorCode::InvalidParams,
174            message: message.into(),
175            data: None,
176        }
177    }
178
179    /// Creates a new internal error (`-32603`).
180    pub const fn internal_error() -> Self {
181        Error::new(ErrorCode::InternalError)
182    }
183
184    /// Creates a new "server not initialized" error (`-32002`).
185    ///
186    /// # Compatibility
187    ///
188    /// This error code is defined by the Language Server Protocol.
189    pub const fn server_not_initialized() -> Self {
190        Error::new(ErrorCode::ServerNotInitialized)
191    }
192
193    /// Creates a new "request cancelled" error (`-32800`).
194    ///
195    /// # Compatibility
196    ///
197    /// This error code is defined by the Language Server Protocol.
198    pub const fn request_cancelled() -> Self {
199        Error::new(ErrorCode::RequestCancelled)
200    }
201
202    /// Creates a new "content modified" error (`-32801`).
203    ///
204    /// # Compatibility
205    ///
206    /// This error code is defined by the Language Server Protocol.
207    pub const fn content_modified() -> Self {
208        Error::new(ErrorCode::ContentModified)
209    }
210
211    /// Creates a new "server cancelled" error (`-32802`).
212    ///
213    /// # Compatibility
214    ///
215    /// This error code is defined by the Language Server Protocol.
216    pub const fn server_cancelled() -> Self {
217        Error::new(ErrorCode::ServerCancelled)
218    }
219
220    /// Creates a new "request failed" server error (`-32803`).
221    ///
222    /// Used to propagate runtime dispatch failures from the autonomic mesh.
223    pub fn request_failed<M>(message: M) -> Self
224    where
225        M: Into<Cow<'static, str>>,
226    {
227        Error {
228            code: ErrorCode::RequestFailed,
229            message: message.into(),
230            data: None,
231        }
232    }
233}
234
235impl Display for Error {
236    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
237        write!(f, "{}: {}", self.code.description(), self.message)
238    }
239}
240
241impl std::error::Error for Error {}
242
243/// Error response returned for every request received before the server is initialized.
244///
245/// See [here](https://microsoft.github.io/language-server-protocol/specification#initialize)
246/// for reference.
247pub(crate) const fn not_initialized_error() -> Error {
248    Error::server_not_initialized()
249}
250
251#[cfg(test)]
252mod tests {
253    use super::*;
254
255    #[test]
256    fn error_code_serializes_as_i64() {
257        let serialized = serde_json::to_string(&ErrorCode::ParseError).unwrap();
258        assert_eq!(serialized, "-32700");
259
260        let serialized = serde_json::to_string(&ErrorCode::ServerError(-12345)).unwrap();
261        assert_eq!(serialized, "-12345");
262    }
263
264    #[test]
265    fn error_code_deserializes_from_i64() {
266        let deserialized: ErrorCode = serde_json::from_str("-32700").unwrap();
267        assert_eq!(deserialized, ErrorCode::ParseError);
268
269        let deserialized: ErrorCode = serde_json::from_str("-12345").unwrap();
270        assert_eq!(deserialized, ErrorCode::ServerError(-12345));
271    }
272}