tower_lsp/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    /// The request was cancelled by the client.
32    ///
33    /// # Compatibility
34    ///
35    /// This error code is defined by the Language Server Protocol.
36    RequestCancelled,
37    /// The request was invalidated by another incoming request.
38    ///
39    /// # Compatibility
40    ///
41    /// This error code is specific to the Language Server Protocol.
42    ContentModified,
43}
44
45impl ErrorCode {
46    /// Returns the integer error code value.
47    pub const fn code(&self) -> i64 {
48        match *self {
49            ErrorCode::ParseError => -32700,
50            ErrorCode::InvalidRequest => -32600,
51            ErrorCode::MethodNotFound => -32601,
52            ErrorCode::InvalidParams => -32602,
53            ErrorCode::InternalError => -32603,
54            ErrorCode::RequestCancelled => -32800,
55            ErrorCode::ContentModified => -32801,
56            ErrorCode::ServerError(code) => code,
57        }
58    }
59
60    /// Returns a human-readable description of the error.
61    pub const fn description(&self) -> &'static str {
62        match *self {
63            ErrorCode::ParseError => "Parse error",
64            ErrorCode::InvalidRequest => "Invalid request",
65            ErrorCode::MethodNotFound => "Method not found",
66            ErrorCode::InvalidParams => "Invalid params",
67            ErrorCode::InternalError => "Internal error",
68            ErrorCode::RequestCancelled => "Canceled",
69            ErrorCode::ContentModified => "Content modified",
70            ErrorCode::ServerError(_) => "Server error",
71        }
72    }
73}
74
75impl From<i64> for ErrorCode {
76    fn from(code: i64) -> Self {
77        match code {
78            -32700 => ErrorCode::ParseError,
79            -32600 => ErrorCode::InvalidRequest,
80            -32601 => ErrorCode::MethodNotFound,
81            -32602 => ErrorCode::InvalidParams,
82            -32603 => ErrorCode::InternalError,
83            -32800 => ErrorCode::RequestCancelled,
84            -32801 => ErrorCode::ContentModified,
85            code => ErrorCode::ServerError(code),
86        }
87    }
88}
89
90impl From<ErrorCode> for i64 {
91    fn from(code: ErrorCode) -> Self {
92        code.code()
93    }
94}
95
96impl Display for ErrorCode {
97    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
98        Display::fmt(&self.code(), f)
99    }
100}
101
102/// A JSON-RPC error object.
103#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
104#[serde(deny_unknown_fields)]
105pub struct Error {
106    /// A number indicating the error type that occurred.
107    pub code: ErrorCode,
108    /// A short description of the error.
109    pub message: Cow<'static, str>,
110    /// Additional information about the error, if any.
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub data: Option<Value>,
113}
114
115impl Error {
116    /// Creates a new error from the given `ErrorCode`.
117    pub const fn new(code: ErrorCode) -> Self {
118        Error {
119            code,
120            message: Cow::Borrowed(code.description()),
121            data: None,
122        }
123    }
124
125    /// Creates a new parse error (`-32700`).
126    pub const fn parse_error() -> Self {
127        Error::new(ErrorCode::ParseError)
128    }
129
130    /// Creates a new "invalid request" error (`-32600`).
131    pub const fn invalid_request() -> Self {
132        Error::new(ErrorCode::InvalidRequest)
133    }
134
135    /// Creates a new "method not found" error (`-32601`).
136    pub const fn method_not_found() -> Self {
137        Error::new(ErrorCode::MethodNotFound)
138    }
139
140    /// Creates a new "invalid params" error (`-32602`).
141    pub fn invalid_params<M>(message: M) -> Self
142    where
143        M: Into<Cow<'static, str>>,
144    {
145        Error {
146            code: ErrorCode::InvalidParams,
147            message: message.into(),
148            data: None,
149        }
150    }
151
152    /// Creates a new internal error (`-32603`).
153    pub const fn internal_error() -> Self {
154        Error::new(ErrorCode::InternalError)
155    }
156
157    /// Creates a new "request cancelled" error (`-32800`).
158    ///
159    /// # Compatibility
160    ///
161    /// This error code is defined by the Language Server Protocol.
162    pub const fn request_cancelled() -> Self {
163        Error::new(ErrorCode::RequestCancelled)
164    }
165
166    /// Creates a new "content modified" error (`-32801`).
167    ///
168    /// # Compatibility
169    ///
170    /// This error code is defined by the Language Server Protocol.
171    pub const fn content_modified() -> Self {
172        Error::new(ErrorCode::ContentModified)
173    }
174}
175
176impl Display for Error {
177    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
178        write!(f, "{}: {}", self.code.description(), self.message)
179    }
180}
181
182impl std::error::Error for Error {}
183
184/// Error response returned for every request received before the server is initialized.
185///
186/// See [here](https://microsoft.github.io/language-server-protocol/specification#initialize)
187/// for reference.
188pub(crate) const fn not_initialized_error() -> Error {
189    Error {
190        code: ErrorCode::ServerError(-32002),
191        message: Cow::Borrowed("Server not initialized"),
192        data: None,
193    }
194}
195
196#[cfg(test)]
197mod tests {
198    use super::*;
199
200    #[test]
201    fn error_code_serializes_as_i64() {
202        let serialized = serde_json::to_string(&ErrorCode::ParseError).unwrap();
203        assert_eq!(serialized, "-32700");
204
205        let serialized = serde_json::to_string(&ErrorCode::ServerError(-12345)).unwrap();
206        assert_eq!(serialized, "-12345");
207    }
208
209    #[test]
210    fn error_code_deserializes_from_i64() {
211        let deserialized: ErrorCode = serde_json::from_str("-32700").unwrap();
212        assert_eq!(deserialized, ErrorCode::ParseError);
213
214        let deserialized: ErrorCode = serde_json::from_str("-12345").unwrap();
215        assert_eq!(deserialized, ErrorCode::ServerError(-12345));
216    }
217}