Skip to content

Commit

Permalink
Don't panic on LSP parsing errors
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
archseer committed May 11, 2022
1 parent 8b1a03a commit 7ae6cad
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 39 deletions.
49 changes: 15 additions & 34 deletions helix-lsp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub enum Error {
StreamClosed,
#[error("LSP not defined")]
LspNotDefined,
#[error("Unhandled")]
Unhandled,
#[error(transparent)]
Other(#[from] anyhow::Error),
}
Expand Down Expand Up @@ -226,34 +228,27 @@ pub enum MethodCall {
}

impl MethodCall {
pub fn parse(method: &str, params: jsonrpc::Params) -> Option<MethodCall> {
pub fn parse(method: &str, params: jsonrpc::Params) -> Result<MethodCall> {
use lsp::request::Request;
let request = match method {
lsp::request::WorkDoneProgressCreate::METHOD => {
let params: lsp::WorkDoneProgressCreateParams = params
.parse()
.expect("Failed to parse WorkDoneCreate params");
let params: lsp::WorkDoneProgressCreateParams = params.parse()?;
Self::WorkDoneProgressCreate(params)
}
lsp::request::ApplyWorkspaceEdit::METHOD => {
let params: lsp::ApplyWorkspaceEditParams = params
.parse()
.expect("Failed to parse ApplyWorkspaceEdit params");
let params: lsp::ApplyWorkspaceEditParams = params.parse()?;
Self::ApplyWorkspaceEdit(params)
}
lsp::request::WorkspaceFoldersRequest::METHOD => Self::WorkspaceFolders,
lsp::request::WorkspaceConfiguration::METHOD => {
let params: lsp::ConfigurationParams = params
.parse()
.expect("Failed to parse WorkspaceConfiguration params");
let params: lsp::ConfigurationParams = params.parse()?;
Self::WorkspaceConfiguration(params)
}
_ => {
log::warn!("unhandled lsp request: {}", method);
return None;
return Err(Error::Unhandled);
}
};
Some(request)
Ok(request)
}
}

Expand All @@ -268,48 +263,34 @@ pub enum Notification {
}

impl Notification {
pub fn parse(method: &str, params: jsonrpc::Params) -> Option<Notification> {
pub fn parse(method: &str, params: jsonrpc::Params) -> Result<Notification> {
use lsp::notification::Notification as _;

let notification = match method {
lsp::notification::Initialized::METHOD => Self::Initialized,
lsp::notification::PublishDiagnostics::METHOD => {
let params: lsp::PublishDiagnosticsParams = params
.parse()
.map_err(|err| {
log::error!(
"received malformed PublishDiagnostic from Language Server: {}",
err
)
})
.ok()?;

// TODO: need to loop over diagnostics and distinguish them by URI
let params: lsp::PublishDiagnosticsParams = params.parse()?;
Self::PublishDiagnostics(params)
}

lsp::notification::ShowMessage::METHOD => {
let params: lsp::ShowMessageParams = params.parse().ok()?;

let params: lsp::ShowMessageParams = params.parse()?;
Self::ShowMessage(params)
}
lsp::notification::LogMessage::METHOD => {
let params: lsp::LogMessageParams = params.parse().ok()?;

let params: lsp::LogMessageParams = params.parse()?;
Self::LogMessage(params)
}
lsp::notification::Progress::METHOD => {
let params: lsp::ProgressParams = params.parse().ok()?;

let params: lsp::ProgressParams = params.parse()?;
Self::ProgressMessage(params)
}
_ => {
log::error!("unhandled LSP notification: {}", method);
return None;
return Err(Error::Unhandled);
}
};

Some(notification)
Ok(notification)
}
}

Expand Down
24 changes: 19 additions & 5 deletions helix-term/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,14 @@ impl Application {
match call {
Call::Notification(helix_lsp::jsonrpc::Notification { method, params, .. }) => {
let notification = match Notification::parse(&method, params) {
Some(notification) => notification,
None => return,
Ok(notification) => notification,
Err(err) => {
log::error!(
"received malformed notification from Language Server: {}",
err
);
return;
}
};

match notification {
Expand Down Expand Up @@ -613,9 +619,17 @@ impl Application {
method, params, id, ..
}) => {
let call = match MethodCall::parse(&method, params) {
Some(call) => call,
None => {
error!("Method not found {}", method);
Ok(call) => call,
Err(helix_lsp::Error::Unhandled) => {
error!("Language Server: Method not found {}", method);
return;
}
Err(err) => {
log::error!(
"received malformed method call from Language Server: {}: {}",
method,
err
);
return;
}
};
Expand Down

0 comments on commit 7ae6cad

Please sign in to comment.