Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--Cargo.lock2
-rw-r--r--lib/lsp-server/Cargo.toml2
-rw-r--r--lib/lsp-server/examples/minimal_lsp.rs15
-rw-r--r--lib/lsp-server/src/lib.rs4
-rw-r--r--lib/lsp-server/src/msg.rs60
-rw-r--r--lib/lsp-server/src/req_queue.rs4
6 files changed, 53 insertions, 34 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8d9304dfaf..b2dc4ceedd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1455,7 +1455,7 @@ dependencies = [
[[package]]
name = "lsp-server"
-version = "0.9.0"
+version = "0.10.0"
dependencies = [
"anyhow",
"crossbeam-channel",
diff --git a/lib/lsp-server/Cargo.toml b/lib/lsp-server/Cargo.toml
index 06a452984f..1a179ef081 100644
--- a/lib/lsp-server/Cargo.toml
+++ b/lib/lsp-server/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lsp-server"
-version = "0.9.0"
+version = "0.10.0"
description = "Generic LSP server scaffold."
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-server"
diff --git a/lib/lsp-server/examples/minimal_lsp.rs b/lib/lsp-server/examples/minimal_lsp.rs
index eb08327455..7efe063551 100644
--- a/lib/lsp-server/examples/minimal_lsp.rs
+++ b/lib/lsp-server/examples/minimal_lsp.rs
@@ -82,9 +82,7 @@ use toolchain::command; // clippy-approved wrapper
#[allow(clippy::print_stderr, clippy::disallowed_types, clippy::disallowed_methods)]
use anyhow::{Context, Result, anyhow, bail};
-use lsp_server::{
- Connection, Message, Request as ServerRequest, RequestId, Response, ResponseKind,
-};
+use lsp_server::{Connection, Message, Request as ServerRequest, RequestId, Response};
// =====================================================================
// main
@@ -306,8 +304,7 @@ fn full_range(text: &str) -> Range {
}
fn send_ok<T: serde::Serialize>(conn: &Connection, id: RequestId, result: &T) -> Result<()> {
- let resp =
- Response { id, response_kind: ResponseKind::Ok { result: serde_json::to_value(result)? } };
+ let resp = Response { id, response_result: Ok(serde_json::to_value(result)?) };
conn.sender.send(Message::Response(resp))?;
Ok(())
}
@@ -320,9 +317,11 @@ fn send_err(
) -> Result<()> {
let resp = Response {
id,
- response_kind: ResponseKind::Err {
- error: lsp_server::ResponseError { code: code as i32, message: msg.into(), data: None },
- },
+ response_result: Err(lsp_server::ResponseError {
+ code: code as i32,
+ message: msg.into(),
+ data: None,
+ }),
};
conn.sender.send(Message::Response(resp))?;
Ok(())
diff --git a/lib/lsp-server/src/lib.rs b/lib/lsp-server/src/lib.rs
index 5eaedbb642..3f29c39c49 100644
--- a/lib/lsp-server/src/lib.rs
+++ b/lib/lsp-server/src/lib.rs
@@ -22,9 +22,7 @@ use crossbeam_channel::{Receiver, RecvError, RecvTimeoutError, Sender};
pub use crate::{
error::{ExtractError, ProtocolError},
- msg::{
- ErrorCode, Message, Notification, Request, RequestId, Response, ResponseError, ResponseKind,
- },
+ msg::{ErrorCode, Message, Notification, Request, RequestId, Response, ResponseError},
req_queue::{Incoming, Outgoing, ReqQueue},
stdio::IoThreads,
};
diff --git a/lib/lsp-server/src/msg.rs b/lib/lsp-server/src/msg.rs
index 64e2ba7509..19fc106134 100644
--- a/lib/lsp-server/src/msg.rs
+++ b/lib/lsp-server/src/msg.rs
@@ -84,15 +84,17 @@ pub struct Response {
// request id. We fail deserialization in that case, so we just
// make this field mandatory.
pub id: RequestId,
- #[serde(flatten)]
- pub response_kind: ResponseKind,
+ #[serde(flatten, with = "ResponseResult")]
+ pub response_result: Result<serde_json::Value, ResponseError>,
}
-#[derive(Debug, Serialize, Deserialize, Clone)]
-#[serde(untagged)]
-pub enum ResponseKind {
- Ok { result: serde_json::Value },
- Err { error: ResponseError },
+#[derive(Serialize, Deserialize)]
+#[serde(remote = "Result<serde_json::Value, ResponseError>")]
+enum ResponseResult {
+ #[serde(rename = "result")]
+ Ok(serde_json::Value),
+ #[serde(rename = "error")]
+ Err(ResponseError),
}
#[derive(Debug, Serialize, Deserialize, Clone)]
@@ -203,14 +205,11 @@ impl Message {
impl Response {
pub fn new_ok<R: serde::Serialize>(id: RequestId, result: R) -> Response {
- Response {
- id,
- response_kind: ResponseKind::Ok { result: serde_json::to_value(result).unwrap() },
- }
+ Response { id, response_result: Ok(serde_json::to_value(result).unwrap()) }
}
pub fn new_err(id: RequestId, code: i32, message: String) -> Response {
let error = ResponseError { code, message, data: None };
- Response { id, response_kind: ResponseKind::Err { error } }
+ Response { id, response_result: Err(error) }
}
}
@@ -305,11 +304,11 @@ fn write_msg_text(out: &mut dyn Write, msg: &str) -> io::Result<()> {
#[cfg(test)]
mod tests {
- use super::{Message, Notification, Request, RequestId};
+ use super::{Message, Notification, Request, RequestId, Response};
#[test]
fn shutdown_with_explicit_null() {
- let text = "{\"jsonrpc\": \"2.0\",\"id\": 3,\"method\": \"shutdown\", \"params\": null }";
+ let text = r#"{"jsonrpc": "2.0","id": 3,"method": "shutdown", "params": null }"#;
let msg: Message = serde_json::from_str(text).unwrap();
assert!(
@@ -319,7 +318,7 @@ mod tests {
#[test]
fn shutdown_with_no_params() {
- let text = "{\"jsonrpc\": \"2.0\",\"id\": 3,\"method\": \"shutdown\"}";
+ let text = r#"{"jsonrpc": "2.0","id": 3,"method": "shutdown"}"#;
let msg: Message = serde_json::from_str(text).unwrap();
assert!(
@@ -329,7 +328,7 @@ mod tests {
#[test]
fn notification_with_explicit_null() {
- let text = "{\"jsonrpc\": \"2.0\",\"method\": \"exit\", \"params\": null }";
+ let text = r#"{"jsonrpc": "2.0","method": "exit", "params": null }"#;
let msg: Message = serde_json::from_str(text).unwrap();
assert!(matches!(msg, Message::Notification(not) if not.method == "exit"));
@@ -337,7 +336,7 @@ mod tests {
#[test]
fn notification_with_no_params() {
- let text = "{\"jsonrpc\": \"2.0\",\"method\": \"exit\"}";
+ let text = r#"{"jsonrpc": "2.0","method": "exit"}"#;
let msg: Message = serde_json::from_str(text).unwrap();
assert!(matches!(msg, Message::Notification(not) if not.method == "exit"));
@@ -352,7 +351,7 @@ mod tests {
});
let serialized = serde_json::to_string(&msg).unwrap();
- assert_eq!("{\"id\":3,\"method\":\"shutdown\"}", serialized);
+ assert_eq!(r#"{"id":3,"method":"shutdown"}"#, serialized);
}
#[test]
@@ -363,6 +362,29 @@ mod tests {
});
let serialized = serde_json::to_string(&msg).unwrap();
- assert_eq!("{\"method\":\"exit\"}", serialized);
+ assert_eq!(r#"{"method":"exit"}"#, serialized);
+ }
+
+ #[test]
+ fn serialize_ok_response() {
+ let msg = Message::Response(Response::new_ok(RequestId::from(3), "success"));
+ let serialized = serde_json::to_string(&msg).unwrap();
+
+ assert_eq!(r#"{"id":3,"result":"success"}"#, serialized);
+ }
+
+ #[test]
+ fn serialize_err_response() {
+ let msg = Message::Response(Response::new_err(
+ RequestId::from(3),
+ -32600,
+ String::from("bad response message"),
+ ));
+ let serialized = serde_json::to_string(&msg).unwrap();
+
+ assert_eq!(
+ r#"{"id":3,"error":{"code":-32600,"message":"bad response message"}}"#,
+ serialized
+ );
}
}
diff --git a/lib/lsp-server/src/req_queue.rs b/lib/lsp-server/src/req_queue.rs
index 0c39a1dc7a..52493d1598 100644
--- a/lib/lsp-server/src/req_queue.rs
+++ b/lib/lsp-server/src/req_queue.rs
@@ -1,6 +1,6 @@
use std::collections::HashMap;
-use crate::{ErrorCode, Request, RequestId, Response, ResponseError, msg::ResponseKind};
+use crate::{ErrorCode, Request, RequestId, Response, ResponseError};
/// Manages the set of pending requests, both incoming and outgoing.
#[derive(Debug)]
@@ -47,7 +47,7 @@ impl<I> Incoming<I> {
message: "canceled by client".to_owned(),
data: None,
};
- Some(Response { id, response_kind: ResponseKind::Err { error } })
+ Some(Response { id, response_result: Err(error) })
}
pub fn complete(&mut self, id: &RequestId) -> Option<I> {