on master help sign in
Don't panic on LSP parsing errors

This made sense initially when the implementation was still new (so we got user reports more frequently), but a parsing error now generally signifies a language server isn't properly implementing the spec.

commit7ae6cad52ed001a903577e30fb71e346fd831af7 authorBlaž Hrastnik <blaz@mxxn.io> dateWed 11 May 2022, 11:00 (4 years ago) parent8b1a03a
2 files changed+34−39
helix-lsp/src/lib.rs+15−34 helix-term/src/application.rs+19−5
helix-lsp/src/lib.rs+15−34
@@ -40,6 +40,8 @@ pub enum Error {
4040 StreamClosed,
4141 #[error("LSP not defined")]
4242 LspNotDefined,
43+ #[error("Unhandled")]
44+ Unhandled,
4345 #[error(transparent)]
4446 Other(#[from] anyhow::Error),
4547}
@@ -226,34 +228,27 @@ pub enum MethodCall {
226228}
227229
228230impl MethodCall {
229− pub fn parse(method: &str, params: jsonrpc::Params) -> Option<MethodCall> {
231+ pub fn parse(method: &str, params: jsonrpc::Params) -> Result<MethodCall> {
230232 use lsp::request::Request;
231233 let request = match method {
232234 lsp::request::WorkDoneProgressCreate::METHOD => {
233− let params: lsp::WorkDoneProgressCreateParams = params
234− .parse()
235− .expect("Failed to parse WorkDoneCreate params");
235+ let params: lsp::WorkDoneProgressCreateParams = params.parse()?;
236236 Self::WorkDoneProgressCreate(params)
237237 }
238238 lsp::request::ApplyWorkspaceEdit::METHOD => {
239− let params: lsp::ApplyWorkspaceEditParams = params
240− .parse()
241− .expect("Failed to parse ApplyWorkspaceEdit params");
239+ let params: lsp::ApplyWorkspaceEditParams = params.parse()?;
242240 Self::ApplyWorkspaceEdit(params)
243241 }
244242 lsp::request::WorkspaceFoldersRequest::METHOD => Self::WorkspaceFolders,
245243 lsp::request::WorkspaceConfiguration::METHOD => {
246− let params: lsp::ConfigurationParams = params
247− .parse()
248− .expect("Failed to parse WorkspaceConfiguration params");
244+ let params: lsp::ConfigurationParams = params.parse()?;
249245 Self::WorkspaceConfiguration(params)
250246 }
251247 _ => {
252− log::warn!("unhandled lsp request: {}", method);
253− return None;
248+ return Err(Error::Unhandled);
254249 }
255250 };
256− Some(request)
251+ Ok(request)
257252 }
258253}
259254
@@ -268,48 +263,34 @@ pub enum Notification {
268263}
269264
270265impl Notification {
271− pub fn parse(method: &str, params: jsonrpc::Params) -> Option<Notification> {
266+ pub fn parse(method: &str, params: jsonrpc::Params) -> Result<Notification> {
272267 use lsp::notification::Notification as _;
273268
274269 let notification = match method {
275270 lsp::notification::Initialized::METHOD => Self::Initialized,
276271 lsp::notification::PublishDiagnostics::METHOD => {
277− let params: lsp::PublishDiagnosticsParams = params
278− .parse()
279− .map_err(|err| {
280− log::error!(
281− "received malformed PublishDiagnostic from Language Server: {}",
282− err
283− )
284− })
285− .ok()?;
286−
287− // TODO: need to loop over diagnostics and distinguish them by URI
272+ let params: lsp::PublishDiagnosticsParams = params.parse()?;
288273 Self::PublishDiagnostics(params)
289274 }
290275
291276 lsp::notification::ShowMessage::METHOD => {
292− let params: lsp::ShowMessageParams = params.parse().ok()?;
293−
277+ let params: lsp::ShowMessageParams = params.parse()?;
294278 Self::ShowMessage(params)
295279 }
296280 lsp::notification::LogMessage::METHOD => {
297− let params: lsp::LogMessageParams = params.parse().ok()?;
298−
281+ let params: lsp::LogMessageParams = params.parse()?;
299282 Self::LogMessage(params)
300283 }
301284 lsp::notification::Progress::METHOD => {
302− let params: lsp::ProgressParams = params.parse().ok()?;
303−
285+ let params: lsp::ProgressParams = params.parse()?;
304286 Self::ProgressMessage(params)
305287 }
306288 _ => {
307− log::error!("unhandled LSP notification: {}", method);
308− return None;
289+ return Err(Error::Unhandled);
309290 }
310291 };
311292
312− Some(notification)
293+ Ok(notification)
313294 }
314295}
315296
helix-term/src/application.rs+19−5
@@ -399,8 +399,14 @@ impl Application {
399399 match call {
400400 Call::Notification(helix_lsp::jsonrpc::Notification { method, params, .. }) => {
401401 let notification = match Notification::parse(&method, params) {
402− Some(notification) => notification,
403− None => return,
402+ Ok(notification) => notification,
403+ Err(err) => {
404+ log::error!(
405+ "received malformed notification from Language Server: {}",
406+ err
407+ );
408+ return;
409+ }
404410 };
405411
406412 match notification {
@@ -613,9 +619,17 @@ impl Application {
613619 method, params, id, ..
614620 }) => {
615621 let call = match MethodCall::parse(&method, params) {
616− Some(call) => call,
617− None => {
618− error!("Method not found {}", method);
622+ Ok(call) => call,
623+ Err(helix_lsp::Error::Unhandled) => {
624+ error!("Language Server: Method not found {}", method);
625+ return;
626+ }
627+ Err(err) => {
628+ log::error!(
629+ "received malformed method call from Language Server: {}: {}",
630+ method,
631+ err
632+ );
619633 return;
620634 }
621635 };