Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22753 from ribru17/response_typing
fix!: make lsp-server `Response` type closer aligned to JSON-RPC
Lukas Wirth 5 weeks ago
parent 6f89f1d · parent 87d1736 · commit b7f5154
-rw-r--r--Cargo.lock2
-rw-r--r--lib/lsp-server/Cargo.toml2
-rw-r--r--lib/lsp-server/examples/minimal_lsp.rs16
-rw-r--r--lib/lsp-server/src/lib.rs4
-rw-r--r--lib/lsp-server/src/msg.rs20
-rw-r--r--lib/lsp-server/src/req_queue.rs4
6 files changed, 29 insertions, 19 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e0f051908c..8d9304dfaf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1455,7 +1455,7 @@ dependencies = [
[[package]]
name = "lsp-server"
-version = "0.8.0"
+version = "0.9.0"
dependencies = [
"anyhow",
"crossbeam-channel",
diff --git a/lib/lsp-server/Cargo.toml b/lib/lsp-server/Cargo.toml
index 285f58e7fc..06a452984f 100644
--- a/lib/lsp-server/Cargo.toml
+++ b/lib/lsp-server/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lsp-server"
-version = "0.8.0"
+version = "0.9.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 3558a6c3bf..eb08327455 100644
--- a/lib/lsp-server/examples/minimal_lsp.rs
+++ b/lib/lsp-server/examples/minimal_lsp.rs
@@ -82,7 +82,9 @@ 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};
+use lsp_server::{
+ Connection, Message, Request as ServerRequest, RequestId, Response, ResponseKind,
+};
// =====================================================================
// main
@@ -304,7 +306,8 @@ fn full_range(text: &str) -> Range {
}
fn send_ok<T: serde::Serialize>(conn: &Connection, id: RequestId, result: &T) -> Result<()> {
- let resp = Response { id, result: Some(serde_json::to_value(result)?), error: None };
+ let resp =
+ Response { id, response_kind: ResponseKind::Ok { result: serde_json::to_value(result)? } };
conn.sender.send(Message::Response(resp))?;
Ok(())
}
@@ -317,12 +320,9 @@ fn send_err(
) -> Result<()> {
let resp = Response {
id,
- result: None,
- error: Some(lsp_server::ResponseError {
- code: code as i32,
- message: msg.into(),
- data: None,
- }),
+ response_kind: ResponseKind::Err {
+ error: 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 3f29c39c49..5eaedbb642 100644
--- a/lib/lsp-server/src/lib.rs
+++ b/lib/lsp-server/src/lib.rs
@@ -22,7 +22,9 @@ use crossbeam_channel::{Receiver, RecvError, RecvTimeoutError, Sender};
pub use crate::{
error::{ExtractError, ProtocolError},
- msg::{ErrorCode, Message, Notification, Request, RequestId, Response, ResponseError},
+ msg::{
+ ErrorCode, Message, Notification, Request, RequestId, Response, ResponseError, ResponseKind,
+ },
req_queue::{Incoming, Outgoing, ReqQueue},
stdio::IoThreads,
};
diff --git a/lib/lsp-server/src/msg.rs b/lib/lsp-server/src/msg.rs
index 305008e69a..64e2ba7509 100644
--- a/lib/lsp-server/src/msg.rs
+++ b/lib/lsp-server/src/msg.rs
@@ -84,10 +84,15 @@ pub struct Response {
// request id. We fail deserialization in that case, so we just
// make this field mandatory.
pub id: RequestId,
- #[serde(skip_serializing_if = "Option::is_none", default)]
- pub result: Option<serde_json::Value>,
- #[serde(skip_serializing_if = "Option::is_none", default)]
- pub error: Option<ResponseError>,
+ #[serde(flatten)]
+ pub response_kind: ResponseKind,
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+#[serde(untagged)]
+pub enum ResponseKind {
+ Ok { result: serde_json::Value },
+ Err { error: ResponseError },
}
#[derive(Debug, Serialize, Deserialize, Clone)]
@@ -198,11 +203,14 @@ impl Message {
impl Response {
pub fn new_ok<R: serde::Serialize>(id: RequestId, result: R) -> Response {
- Response { id, result: Some(serde_json::to_value(result).unwrap()), error: None }
+ Response {
+ id,
+ response_kind: ResponseKind::Ok { result: 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, result: None, error: Some(error) }
+ Response { id, response_kind: ResponseKind::Err { error } }
}
}
diff --git a/lib/lsp-server/src/req_queue.rs b/lib/lsp-server/src/req_queue.rs
index 84748bbca8..0c39a1dc7a 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};
+use crate::{ErrorCode, Request, RequestId, Response, ResponseError, msg::ResponseKind};
/// 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, result: None, error: Some(error) })
+ Some(Response { id, response_kind: ResponseKind::Err { error } })
}
pub fn complete(&mut self, id: &RequestId) -> Option<I> {