lsp: Correctly serialize errors for LSP requests + improve handling of unrecognized methods (#35738)
We used to not respond at all to requests that we didn't have a handler for, which is yuck. It may have left the language server waiting for the response for no good reason. The other (worse) finding is that we did not have a full definition of an Error type for LSP, which made it so that a spec-compliant language server would fail to deserialize our response (with an error). This then could lead to all sorts of funkiness, including hangs and crashes on the language server's part. Co-authored-by: Lukas <lukas@zed.dev> Co-authored-by: Remco Smits <djsmits12@gmail.com> Co-authored-by: Anthony Eid <hello@anthonyeid.me> Closes #ISSUE Release Notes: - Improved reporting of errors to language servers, which should improve the stability of LSPs ran by Zed. --------- Co-authored-by: Lukas <lukas@zed.dev> Co-authored-by: Remco Smits <djsmits12@gmail.com> Co-authored-by: Anthony Eid <hello@anthonyeid.me>
This commit is contained in:
parent
794098e5c9
commit
fb1f9d1212
2 changed files with 57 additions and 24 deletions
|
@ -13,14 +13,15 @@ use parking_lot::Mutex;
|
|||
use smol::io::BufReader;
|
||||
|
||||
use crate::{
|
||||
AnyNotification, AnyResponse, CONTENT_LEN_HEADER, IoHandler, IoKind, RequestId, ResponseHandler,
|
||||
AnyResponse, CONTENT_LEN_HEADER, IoHandler, IoKind, NotificationOrRequest, RequestId,
|
||||
ResponseHandler,
|
||||
};
|
||||
|
||||
const HEADER_DELIMITER: &[u8; 4] = b"\r\n\r\n";
|
||||
/// Handler for stdout of language server.
|
||||
pub struct LspStdoutHandler {
|
||||
pub(super) loop_handle: Task<Result<()>>,
|
||||
pub(super) notifications_channel: UnboundedReceiver<AnyNotification>,
|
||||
pub(super) incoming_messages: UnboundedReceiver<NotificationOrRequest>,
|
||||
}
|
||||
|
||||
async fn read_headers<Stdout>(reader: &mut BufReader<Stdout>, buffer: &mut Vec<u8>) -> Result<()>
|
||||
|
@ -54,13 +55,13 @@ impl LspStdoutHandler {
|
|||
let loop_handle = cx.spawn(Self::handler(stdout, tx, response_handlers, io_handlers));
|
||||
Self {
|
||||
loop_handle,
|
||||
notifications_channel,
|
||||
incoming_messages: notifications_channel,
|
||||
}
|
||||
}
|
||||
|
||||
async fn handler<Input>(
|
||||
stdout: Input,
|
||||
notifications_sender: UnboundedSender<AnyNotification>,
|
||||
notifications_sender: UnboundedSender<NotificationOrRequest>,
|
||||
response_handlers: Arc<Mutex<Option<HashMap<RequestId, ResponseHandler>>>>,
|
||||
io_handlers: Arc<Mutex<HashMap<i32, IoHandler>>>,
|
||||
) -> anyhow::Result<()>
|
||||
|
@ -96,7 +97,7 @@ impl LspStdoutHandler {
|
|||
}
|
||||
}
|
||||
|
||||
if let Ok(msg) = serde_json::from_slice::<AnyNotification>(&buffer) {
|
||||
if let Ok(msg) = serde_json::from_slice::<NotificationOrRequest>(&buffer) {
|
||||
notifications_sender.unbounded_send(msg)?;
|
||||
} else if let Ok(AnyResponse {
|
||||
id, error, result, ..
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue