on master help sign in
Don't panic on LSP parsing errors
7ae6cadBlaž Hrastnik
helix-lsp/src/lib.rs+15−34
@@ -40,6 +40,8 @@ pub enum Error {
40 StreamClosed,
40 StreamClosed,
41 #[error("LSP not defined")]
41 #[error("LSP not defined")]
42 LspNotDefined,
42 LspNotDefined,
43+ #[error("Unhandled")]
44+ Unhandled,
43 #[error(transparent)]
45 #[error(transparent)]
44 Other(#[from] anyhow::Error),
46 Other(#[from] anyhow::Error),
45}
47}
@@ -226,34 +228,27 @@ pub enum MethodCall {
226}
228}
227
229
228impl MethodCall {
230impl MethodCall {
229− pub fn parse(method: &str, params: jsonrpc::Params) -> Option<MethodCall> {
231+ pub fn parse(method: &str, params: jsonrpc::Params) -> Result<MethodCall> {
230 use lsp::request::Request;
232 use lsp::request::Request;
231 let request = match method {
233 let request = match method {
232 lsp::request::WorkDoneProgressCreate::METHOD => {
234 lsp::request::WorkDoneProgressCreate::METHOD => {
233− let params: lsp::WorkDoneProgressCreateParams = params
235+ let params: lsp::WorkDoneProgressCreateParams = params.parse()?;
234− .parse()
235− .expect("Failed to parse WorkDoneCreate params");
236 Self::WorkDoneProgressCreate(params)
236 Self::WorkDoneProgressCreate(params)
237 }
237 }
238 lsp::request::ApplyWorkspaceEdit::METHOD => {
238 lsp::request::ApplyWorkspaceEdit::METHOD => {
239− let params: lsp::ApplyWorkspaceEditParams = params
239+ let params: lsp::ApplyWorkspaceEditParams = params.parse()?;
240− .parse()
241− .expect("Failed to parse ApplyWorkspaceEdit params");
242 Self::ApplyWorkspaceEdit(params)
240 Self::ApplyWorkspaceEdit(params)
243 }
241 }
244 lsp::request::WorkspaceFoldersRequest::METHOD => Self::WorkspaceFolders,
242 lsp::request::WorkspaceFoldersRequest::METHOD => Self::WorkspaceFolders,
245 lsp::request::WorkspaceConfiguration::METHOD => {
243 lsp::request::WorkspaceConfiguration::METHOD => {
246− let params: lsp::ConfigurationParams = params
244+ let params: lsp::ConfigurationParams = params.parse()?;
247− .parse()
248− .expect("Failed to parse WorkspaceConfiguration params");
249 Self::WorkspaceConfiguration(params)
245 Self::WorkspaceConfiguration(params)
250 }
246 }
251 _ => {
247 _ => {
252− log::warn!("unhandled lsp request: {}", method);
248+ return Err(Error::Unhandled);
253− return None;
254 }
249 }
255 };
250 };
256− Some(request)
251+ Ok(request)
257 }
252 }
258}
253}
259
254
@@ -268,48 +263,34 @@ pub enum Notification {
268}
263}
269
264
270impl Notification {
265impl Notification {
271− pub fn parse(method: &str, params: jsonrpc::Params) -> Option<Notification> {
266+ pub fn parse(method: &str, params: jsonrpc::Params) -> Result<Notification> {
272 use lsp::notification::Notification as _;
267 use lsp::notification::Notification as _;
273
268
274 let notification = match method {
269 let notification = match method {
275 lsp::notification::Initialized::METHOD => Self::Initialized,
270 lsp::notification::Initialized::METHOD => Self::Initialized,
276 lsp::notification::PublishDiagnostics::METHOD => {
271 lsp::notification::PublishDiagnostics::METHOD => {
277− let params: lsp::PublishDiagnosticsParams = params
272+ let params: lsp::PublishDiagnosticsParams = params.parse()?;
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
288 Self::PublishDiagnostics(params)
273 Self::PublishDiagnostics(params)
289 }
274 }
290
275
291 lsp::notification::ShowMessage::METHOD => {
276 lsp::notification::ShowMessage::METHOD => {
292− let params: lsp::ShowMessageParams = params.parse().ok()?;
277+ let params: lsp::ShowMessageParams = params.parse()?;
293−
294 Self::ShowMessage(params)
278 Self::ShowMessage(params)
295 }
279 }
296 lsp::notification::LogMessage::METHOD => {
280 lsp::notification::LogMessage::METHOD => {
297− let params: lsp::LogMessageParams = params.parse().ok()?;
281+ let params: lsp::LogMessageParams = params.parse()?;
298−
299 Self::LogMessage(params)
282 Self::LogMessage(params)
300 }
283 }
301 lsp::notification::Progress::METHOD => {
284 lsp::notification::Progress::METHOD => {
302− let params: lsp::ProgressParams = params.parse().ok()?;
285+ let params: lsp::ProgressParams = params.parse()?;
303−
304 Self::ProgressMessage(params)
286 Self::ProgressMessage(params)
305 }
287 }
306 _ => {
288 _ => {
307− log::error!("unhandled LSP notification: {}", method);
289+ return Err(Error::Unhandled);
308− return None;
309 }
290 }
310 };
291 };
311
292
312− Some(notification)
293+ Ok(notification)
313 }
294 }
314}
295}
315
296
helix-term/src/application.rs+19−5
@@ -399,8 +399,14 @@ impl Application {
399 match call {
399 match call {
400 Call::Notification(helix_lsp::jsonrpc::Notification { method, params, .. }) => {
400 Call::Notification(helix_lsp::jsonrpc::Notification { method, params, .. }) => {
401 let notification = match Notification::parse(&method, params) {
401 let notification = match Notification::parse(&method, params) {
402− Some(notification) => notification,
402+ Ok(notification) => notification,
403+ Err(err) => {
404+ log::error!(
405+ "received malformed notification from Language Server: {}",
406+ err
407+ );
403− None => return,
408+ return;
409+ }
404 };
410 };
405
411
406 match notification {
412 match notification {
@@ -613,9 +619,17 @@ impl Application {
613 method, params, id, ..
619 method, params, id, ..
614 }) => {
620 }) => {
615 let call = match MethodCall::parse(&method, params) {
621 let call = match MethodCall::parse(&method, params) {
616− Some(call) => call,
622+ Ok(call) => call,
617− None => {
623+ Err(helix_lsp::Error::Unhandled) => {
618− error!("Method not found {}", method);
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+ );
619 return;
633 return;
620 }
634 }
621 };
635 };