Skip to content

Commit 3b9548e

Browse files
committed
Respond with JSON-RPC error if we failed to deserialize request
Historically, we intentinally violated JSON-RPC spec here by hard crashing. The idea was to poke both the clients and servers to fix stuff. However, this is confusing for server implementors, and falls down in one important place -- protocol extension are not always backwards compatible, which causes crashes simply due to version mismatch. We had once such case with our own extension, and one for semantic tokens. So let's be less adventerous and just err on the err side!
1 parent e7c8c60 commit 3b9548e

File tree

3 files changed

+62
-58
lines changed

3 files changed

+62
-58
lines changed

crates/rust-analyzer/src/dispatch.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,16 @@ impl<'a> RequestDispatcher<'a> {
2828
{
2929
let (id, params) = match self.parse::<R>() {
3030
Some(it) => it,
31-
None => {
32-
return Ok(self);
33-
}
31+
None => return Ok(self),
3432
};
3533
let world = panic::AssertUnwindSafe(&mut *self.global_state);
34+
3635
let response = panic::catch_unwind(move || {
3736
let _pctx = stdx::panic_context::enter(format!("request: {} {:#?}", R::METHOD, params));
3837
let result = f(world.0, params);
3938
result_to_response::<R>(id, result)
4039
})
41-
.map_err(|_| format!("sync task {:?} panicked", R::METHOD))?;
40+
.map_err(|_err| format!("sync task {:?} panicked", R::METHOD))?;
4241
self.global_state.respond(response);
4342
Ok(self)
4443
}
@@ -47,17 +46,15 @@ impl<'a> RequestDispatcher<'a> {
4746
pub(crate) fn on<R>(
4847
&mut self,
4948
f: fn(GlobalStateSnapshot, R::Params) -> Result<R::Result>,
50-
) -> Result<&mut Self>
49+
) -> &mut Self
5150
where
5251
R: lsp_types::request::Request + 'static,
5352
R::Params: DeserializeOwned + Send + fmt::Debug + 'static,
5453
R::Result: Serialize + 'static,
5554
{
5655
let (id, params) = match self.parse::<R>() {
5756
Some(it) => it,
58-
None => {
59-
return Ok(self);
60-
}
57+
None => return self,
6158
};
6259

6360
self.global_state.task_pool.handle.spawn({
@@ -71,7 +68,7 @@ impl<'a> RequestDispatcher<'a> {
7168
}
7269
});
7370

74-
Ok(self)
71+
self
7572
}
7673

7774
pub(crate) fn finish(&mut self) {
@@ -82,7 +79,7 @@ impl<'a> RequestDispatcher<'a> {
8279
lsp_server::ErrorCode::MethodNotFound as i32,
8380
"unknown request".to_string(),
8481
);
85-
self.global_state.respond(response)
82+
self.global_state.respond(response);
8683
}
8784
}
8885

@@ -91,15 +88,24 @@ impl<'a> RequestDispatcher<'a> {
9188
R: lsp_types::request::Request + 'static,
9289
R::Params: DeserializeOwned + 'static,
9390
{
94-
let req = self.req.take()?;
95-
let (id, params) = match req.extract::<R::Params>(R::METHOD) {
96-
Ok(it) => it,
97-
Err(req) => {
98-
self.req = Some(req);
91+
let req = match &self.req {
92+
Some(req) if req.method == R::METHOD => self.req.take().unwrap(),
93+
_ => return None,
94+
};
95+
96+
let res = crate::from_json(R::METHOD, req.params);
97+
match res {
98+
Ok(params) => return Some((req.id, params)),
99+
Err(err) => {
100+
let response = lsp_server::Response::new_err(
101+
req.id,
102+
lsp_server::ErrorCode::InvalidParams as i32,
103+
err.to_string(),
104+
);
105+
self.global_state.respond(response);
99106
return None;
100107
}
101-
};
102-
Some((id, params))
108+
}
103109
}
104110
}
105111

crates/rust-analyzer/src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,16 @@ mod document;
3737
pub mod lsp_ext;
3838
pub mod config;
3939

40-
use serde::de::DeserializeOwned;
41-
42-
pub type Result<T, E = Box<dyn std::error::Error + Send + Sync>> = std::result::Result<T, E>;
43-
pub use crate::{caps::server_capabilities, main_loop::main_loop};
4440
use ide::AnalysisHost;
41+
use serde::de::DeserializeOwned;
4542
use std::fmt;
4643
use vfs::Vfs;
4744

45+
pub use crate::{caps::server_capabilities, main_loop::main_loop};
46+
47+
pub type Error = Box<dyn std::error::Error + Send + Sync>;
48+
pub type Result<T, E = Error> = std::result::Result<T, E>;
49+
4850
pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> {
4951
let res = T::deserialize(&json)
5052
.map_err(|e| format!("Failed to deserialize {}: {}; {}", what, e, json))?;

crates/rust-analyzer/src/main_loop.rs

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -403,53 +403,49 @@ impl GlobalState {
403403
handlers::handle_matching_brace(s.snapshot(), p)
404404
})?
405405
.on_sync::<lsp_ext::MemoryUsage>(|s, p| handlers::handle_memory_usage(s, p))?
406-
.on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status)?
407-
.on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree)?
408-
.on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro)?
409-
.on::<lsp_ext::ParentModule>(handlers::handle_parent_module)?
410-
.on::<lsp_ext::Runnables>(handlers::handle_runnables)?
411-
.on::<lsp_ext::InlayHints>(handlers::handle_inlay_hints)?
412-
.on::<lsp_ext::CodeActionRequest>(handlers::handle_code_action)?
413-
.on::<lsp_ext::ResolveCodeActionRequest>(handlers::handle_resolve_code_action)?
414-
.on::<lsp_ext::HoverRequest>(handlers::handle_hover)?
415-
.on::<lsp_ext::ExternalDocs>(handlers::handle_open_docs)?
416-
.on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting)?
417-
.on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol)?
418-
.on::<lsp_types::request::WorkspaceSymbol>(handlers::handle_workspace_symbol)?
419-
.on::<lsp_types::request::GotoDefinition>(handlers::handle_goto_definition)?
420-
.on::<lsp_types::request::GotoImplementation>(handlers::handle_goto_implementation)?
421-
.on::<lsp_types::request::GotoTypeDefinition>(handlers::handle_goto_type_definition)?
422-
.on::<lsp_types::request::Completion>(handlers::handle_completion)?
423-
.on::<lsp_types::request::CodeLensRequest>(handlers::handle_code_lens)?
424-
.on::<lsp_types::request::CodeLensResolve>(handlers::handle_code_lens_resolve)?
425-
.on::<lsp_types::request::FoldingRangeRequest>(handlers::handle_folding_range)?
426-
.on::<lsp_types::request::SignatureHelpRequest>(handlers::handle_signature_help)?
427-
.on::<lsp_types::request::PrepareRenameRequest>(handlers::handle_prepare_rename)?
428-
.on::<lsp_types::request::Rename>(handlers::handle_rename)?
429-
.on::<lsp_types::request::References>(handlers::handle_references)?
430-
.on::<lsp_types::request::Formatting>(handlers::handle_formatting)?
431-
.on::<lsp_types::request::DocumentHighlightRequest>(
432-
handlers::handle_document_highlight,
433-
)?
434-
.on::<lsp_types::request::CallHierarchyPrepare>(
435-
handlers::handle_call_hierarchy_prepare,
436-
)?
406+
.on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status)
407+
.on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree)
408+
.on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro)
409+
.on::<lsp_ext::ParentModule>(handlers::handle_parent_module)
410+
.on::<lsp_ext::Runnables>(handlers::handle_runnables)
411+
.on::<lsp_ext::InlayHints>(handlers::handle_inlay_hints)
412+
.on::<lsp_ext::CodeActionRequest>(handlers::handle_code_action)
413+
.on::<lsp_ext::ResolveCodeActionRequest>(handlers::handle_resolve_code_action)
414+
.on::<lsp_ext::HoverRequest>(handlers::handle_hover)
415+
.on::<lsp_ext::ExternalDocs>(handlers::handle_open_docs)
416+
.on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting)
417+
.on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol)
418+
.on::<lsp_types::request::WorkspaceSymbol>(handlers::handle_workspace_symbol)
419+
.on::<lsp_types::request::GotoDefinition>(handlers::handle_goto_definition)
420+
.on::<lsp_types::request::GotoImplementation>(handlers::handle_goto_implementation)
421+
.on::<lsp_types::request::GotoTypeDefinition>(handlers::handle_goto_type_definition)
422+
.on::<lsp_types::request::Completion>(handlers::handle_completion)
423+
.on::<lsp_types::request::CodeLensRequest>(handlers::handle_code_lens)
424+
.on::<lsp_types::request::CodeLensResolve>(handlers::handle_code_lens_resolve)
425+
.on::<lsp_types::request::FoldingRangeRequest>(handlers::handle_folding_range)
426+
.on::<lsp_types::request::SignatureHelpRequest>(handlers::handle_signature_help)
427+
.on::<lsp_types::request::PrepareRenameRequest>(handlers::handle_prepare_rename)
428+
.on::<lsp_types::request::Rename>(handlers::handle_rename)
429+
.on::<lsp_types::request::References>(handlers::handle_references)
430+
.on::<lsp_types::request::Formatting>(handlers::handle_formatting)
431+
.on::<lsp_types::request::DocumentHighlightRequest>(handlers::handle_document_highlight)
432+
.on::<lsp_types::request::CallHierarchyPrepare>(handlers::handle_call_hierarchy_prepare)
437433
.on::<lsp_types::request::CallHierarchyIncomingCalls>(
438434
handlers::handle_call_hierarchy_incoming,
439-
)?
435+
)
440436
.on::<lsp_types::request::CallHierarchyOutgoingCalls>(
441437
handlers::handle_call_hierarchy_outgoing,
442-
)?
438+
)
443439
.on::<lsp_types::request::SemanticTokensFullRequest>(
444440
handlers::handle_semantic_tokens_full,
445-
)?
441+
)
446442
.on::<lsp_types::request::SemanticTokensFullDeltaRequest>(
447443
handlers::handle_semantic_tokens_full_delta,
448-
)?
444+
)
449445
.on::<lsp_types::request::SemanticTokensRangeRequest>(
450446
handlers::handle_semantic_tokens_range,
451-
)?
452-
.on::<lsp_ext::Ssr>(handlers::handle_ssr)?
447+
)
448+
.on::<lsp_ext::Ssr>(handlers::handle_ssr)
453449
.finish();
454450
Ok(())
455451
}

0 commit comments

Comments
 (0)