From 4ffee15a5b33d81e9fc60f693f19ebd5d2c68e57 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Tue, 7 Mar 2023 19:50:57 -0600 Subject: [PATCH] LSP: Send replies for malformed and unhandled RPC requests (#6058) Previously we did not respond to malformed or unhandled LSP requests. The JSONRPC spec says that all non-notification requests must have responses: > When a rpc call is made, the Server MUST reply with a Response, > except for in the case of Notifications (Note that Helix is the "Server" in this case. Also from the spec: "The Server is defined as the origin of Response objects and the handler of Request objects.") So this change sends error replies for requests which can't be parsed or handled. Request IDs are also now added to the log messages for unhandled requests. --- helix-term/src/application.rs | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 2487a02f831d..d56e7c884df3 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -928,24 +928,32 @@ impl Application { Call::MethodCall(helix_lsp::jsonrpc::MethodCall { method, params, id, .. }) => { - let call = match MethodCall::parse(&method, params) { - Ok(call) => call, + let reply = match MethodCall::parse(&method, params) { Err(helix_lsp::Error::Unhandled) => { - error!("Language Server: Method not found {}", method); - return; + error!( + "Language Server: Method {} not found in request {}", + method, id + ); + Err(helix_lsp::jsonrpc::Error { + code: helix_lsp::jsonrpc::ErrorCode::MethodNotFound, + message: format!("Method not found: {}", method), + data: None, + }) } Err(err) => { log::error!( - "received malformed method call from Language Server: {}: {}", + "Language Server: Received malformed method call {} in request {}: {}", method, + id, err ); - return; + Err(helix_lsp::jsonrpc::Error { + code: helix_lsp::jsonrpc::ErrorCode::ParseError, + message: format!("Malformed method call: {}", method), + data: None, + }) } - }; - - let reply = match call { - MethodCall::WorkDoneProgressCreate(params) => { + Ok(MethodCall::WorkDoneProgressCreate(params)) => { self.lsp_progress.create(server_id, params.token); let editor_view = self @@ -959,7 +967,7 @@ impl Application { Ok(serde_json::Value::Null) } - MethodCall::ApplyWorkspaceEdit(params) => { + Ok(MethodCall::ApplyWorkspaceEdit(params)) => { apply_workspace_edit( &mut self.editor, helix_lsp::OffsetEncoding::Utf8, @@ -972,13 +980,13 @@ impl Application { failed_change: None, })) } - MethodCall::WorkspaceFolders => { + Ok(MethodCall::WorkspaceFolders) => { let language_server = self.editor.language_servers.get_by_id(server_id).unwrap(); Ok(json!(language_server.workspace_folders())) } - MethodCall::WorkspaceConfiguration(params) => { + Ok(MethodCall::WorkspaceConfiguration(params)) => { let result: Vec<_> = params .items .iter()