Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/rust-analyzer/src/bin/main.rs2
-rw-r--r--crates/rust-analyzer/src/dispatch.rs93
-rw-r--r--crates/rust-analyzer/src/from_proto.rs2
-rw-r--r--crates/rust-analyzer/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/lsp_utils.rs7
-rw-r--r--crates/rust-analyzer/src/main_loop.rs35
6 files changed, 70 insertions, 71 deletions
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index df61ba8eec..a9e79cc7c3 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -157,7 +157,7 @@ fn run_server() -> Result<()> {
let (initialize_id, initialize_params) = connection.initialize_start()?;
tracing::info!("InitializeParams: {}", initialize_params);
let initialize_params =
- from_json::<lsp_types::InitializeParams>("InitializeParams", initialize_params)?;
+ from_json::<lsp_types::InitializeParams>("InitializeParams", &initialize_params)?;
let root_path = match initialize_params
.root_uri
diff --git a/crates/rust-analyzer/src/dispatch.rs b/crates/rust-analyzer/src/dispatch.rs
index d208ba16cb..4d94630a56 100644
--- a/crates/rust-analyzer/src/dispatch.rs
+++ b/crates/rust-analyzer/src/dispatch.rs
@@ -1,12 +1,12 @@
//! See [RequestDispatcher].
use std::{fmt, panic, thread};
+use ide::Cancelled;
use lsp_server::ExtractError;
use serde::{de::DeserializeOwned, Serialize};
use crate::{
global_state::{GlobalState, GlobalStateSnapshot},
- lsp_utils::is_cancelled,
main_loop::Task,
LspError, Result,
};
@@ -37,38 +37,40 @@ impl<'a> RequestDispatcher<'a> {
pub(crate) fn on_sync_mut<R>(
&mut self,
f: fn(&mut GlobalState, R::Params) -> Result<R::Result>,
- ) -> Result<&mut Self>
+ ) -> &mut Self
where
R: lsp_types::request::Request,
R::Params: DeserializeOwned + panic::UnwindSafe + fmt::Debug,
R::Result: Serialize,
{
- let (id, params, panic_context) = match self.parse::<R>() {
+ let (req, params, panic_context) = match self.parse::<R>() {
Some(it) => it,
- None => return Ok(self),
+ None => return self,
};
- let _pctx = stdx::panic_context::enter(panic_context);
-
- let result = f(self.global_state, params);
- let response = result_to_response::<R>(id, result);
+ let result = {
+ let _pctx = stdx::panic_context::enter(panic_context);
+ f(self.global_state, params)
+ };
+ if let Ok(response) = result_to_response::<R>(req.id.clone(), result) {
+ self.global_state.respond(response);
+ }
- self.global_state.respond(response);
- Ok(self)
+ self
}
/// Dispatches the request onto the current thread.
pub(crate) fn on_sync<R>(
&mut self,
f: fn(GlobalStateSnapshot, R::Params) -> Result<R::Result>,
- ) -> Result<&mut Self>
+ ) -> &mut Self
where
- R: lsp_types::request::Request + 'static,
+ R: lsp_types::request::Request,
R::Params: DeserializeOwned + panic::UnwindSafe + fmt::Debug,
R::Result: Serialize,
{
- let (id, params, panic_context) = match self.parse::<R>() {
+ let (req, params, panic_context) = match self.parse::<R>() {
Some(it) => it,
- None => return Ok(self),
+ None => return self,
};
let global_state_snapshot = self.global_state.snapshot();
@@ -76,10 +78,12 @@ impl<'a> RequestDispatcher<'a> {
let _pctx = stdx::panic_context::enter(panic_context);
f(global_state_snapshot, params)
});
- let response = thread_result_to_response::<R>(id, result);
- self.global_state.respond(response);
- Ok(self)
+ if let Ok(response) = thread_result_to_response::<R>(req.id.clone(), result) {
+ self.global_state.respond(response);
+ }
+
+ self
}
/// Dispatches the request onto thread pool
@@ -92,7 +96,7 @@ impl<'a> RequestDispatcher<'a> {
R::Params: DeserializeOwned + panic::UnwindSafe + Send + fmt::Debug,
R::Result: Serialize,
{
- let (id, params, panic_context) = match self.parse::<R>() {
+ let (req, params, panic_context) = match self.parse::<R>() {
Some(it) => it,
None => return self,
};
@@ -104,8 +108,10 @@ impl<'a> RequestDispatcher<'a> {
let _pctx = stdx::panic_context::enter(panic_context);
f(world, params)
});
- let response = thread_result_to_response::<R>(id, result);
- Task::Response(response)
+ match thread_result_to_response::<R>(req.id.clone(), result) {
+ Ok(response) => Task::Response(response),
+ Err(_) => Task::Retry(req),
+ }
}
});
@@ -124,7 +130,7 @@ impl<'a> RequestDispatcher<'a> {
}
}
- fn parse<R>(&mut self) -> Option<(lsp_server::RequestId, R::Params, String)>
+ fn parse<R>(&mut self) -> Option<(lsp_server::Request, R::Params, String)>
where
R: lsp_types::request::Request,
R::Params: DeserializeOwned + fmt::Debug,
@@ -134,12 +140,12 @@ impl<'a> RequestDispatcher<'a> {
_ => return None,
};
- let res = crate::from_json(R::METHOD, req.params);
+ let res = crate::from_json(R::METHOD, &req.params);
match res {
Ok(params) => {
let panic_context =
format!("\nversion: {}\nrequest: {} {:#?}", env!("REV"), R::METHOD, params);
- Some((req.id, params, panic_context))
+ Some((req, params, panic_context))
}
Err(err) => {
let response = lsp_server::Response::new_err(
@@ -157,7 +163,7 @@ impl<'a> RequestDispatcher<'a> {
fn thread_result_to_response<R>(
id: lsp_server::RequestId,
result: thread::Result<Result<R::Result>>,
-) -> lsp_server::Response
+) -> Result<lsp_server::Response, Cancelled>
where
R: lsp_types::request::Request,
R::Params: DeserializeOwned,
@@ -166,19 +172,22 @@ where
match result {
Ok(result) => result_to_response::<R>(id, result),
Err(panic) => {
- let mut message = "request handler panicked".to_string();
-
let panic_message = panic
.downcast_ref::<String>()
.map(String::as_str)
.or_else(|| panic.downcast_ref::<&str>().copied());
+ let mut message = "request handler panicked".to_string();
if let Some(panic_message) = panic_message {
message.push_str(": ");
message.push_str(panic_message)
};
- lsp_server::Response::new_err(id, lsp_server::ErrorCode::InternalError as i32, message)
+ Ok(lsp_server::Response::new_err(
+ id,
+ lsp_server::ErrorCode::InternalError as i32,
+ message,
+ ))
}
}
}
@@ -186,33 +195,27 @@ where
fn result_to_response<R>(
id: lsp_server::RequestId,
result: Result<R::Result>,
-) -> lsp_server::Response
+) -> Result<lsp_server::Response, Cancelled>
where
R: lsp_types::request::Request,
R::Params: DeserializeOwned,
R::Result: Serialize,
{
- match result {
+ let res = match result {
Ok(resp) => lsp_server::Response::new_ok(id, &resp),
Err(e) => match e.downcast::<LspError>() {
Ok(lsp_error) => lsp_server::Response::new_err(id, lsp_error.code, lsp_error.message),
- Err(e) => {
- if is_cancelled(&*e) {
- lsp_server::Response::new_err(
- id,
- lsp_server::ErrorCode::ContentModified as i32,
- "content modified".to_string(),
- )
- } else {
- lsp_server::Response::new_err(
- id,
- lsp_server::ErrorCode::InternalError as i32,
- e.to_string(),
- )
- }
- }
+ Err(e) => match e.downcast::<Cancelled>() {
+ Ok(cancelled) => return Err(*cancelled),
+ Err(e) => lsp_server::Response::new_err(
+ id,
+ lsp_server::ErrorCode::InternalError as i32,
+ e.to_string(),
+ ),
+ },
},
- }
+ };
+ Ok(res)
}
pub(crate) struct NotificationDispatcher<'a> {
diff --git a/crates/rust-analyzer/src/from_proto.rs b/crates/rust-analyzer/src/from_proto.rs
index ffc69a419a..7bdd34d1f0 100644
--- a/crates/rust-analyzer/src/from_proto.rs
+++ b/crates/rust-analyzer/src/from_proto.rs
@@ -91,7 +91,7 @@ pub(crate) fn annotation(
) -> Result<Annotation> {
let data =
code_lens.data.ok_or_else(|| invalid_params_error("code lens without data".to_string()))?;
- let resolve = from_json::<lsp_ext::CodeLensResolveData>("CodeLensResolveData", data)?;
+ let resolve = from_json::<lsp_ext::CodeLensResolveData>("CodeLensResolveData", &data)?;
match resolve {
lsp_ext::CodeLensResolveData::Impls(params) => {
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs
index d6b37760a0..d5bc8f65f8 100644
--- a/crates/rust-analyzer/src/lib.rs
+++ b/crates/rust-analyzer/src/lib.rs
@@ -49,7 +49,7 @@ pub use crate::{caps::server_capabilities, main_loop::main_loop};
pub type Error = Box<dyn std::error::Error + Send + Sync>;
pub type Result<T, E = Error> = std::result::Result<T, E>;
-pub fn from_json<T: DeserializeOwned>(what: &'static str, json: serde_json::Value) -> Result<T> {
+pub fn from_json<T: DeserializeOwned>(what: &'static str, json: &serde_json::Value) -> Result<T> {
let res = serde_json::from_value(json.clone())
.map_err(|e| format!("Failed to deserialize {}: {}; {}", what, e, json))?;
Ok(res)
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs
index 460ae4ef4d..22bab8fa82 100644
--- a/crates/rust-analyzer/src/lsp_utils.rs
+++ b/crates/rust-analyzer/src/lsp_utils.rs
@@ -1,7 +1,6 @@
//! Utilities for LSP-related boilerplate code.
-use std::{error::Error, ops::Range, sync::Arc};
+use std::{ops::Range, sync::Arc};
-use ide_db::base_db::Cancelled;
use lsp_server::Notification;
use crate::{
@@ -15,10 +14,6 @@ pub(crate) fn invalid_params_error(message: String) -> LspError {
LspError { code: lsp_server::ErrorCode::InvalidParams as i32, message }
}
-pub(crate) fn is_cancelled(e: &(dyn Error + 'static)) -> bool {
- e.downcast_ref::<Cancelled>().is_some()
-}
-
pub(crate) fn notification_is<N: lsp_types::notification::Notification>(
notification: &Notification,
) -> bool {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 3c87968743..0fc5fd9dfa 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -8,7 +8,7 @@ use std::{
use always_assert::always;
use crossbeam_channel::{select, Receiver};
-use ide_db::base_db::{SourceDatabaseExt, VfsPath};
+use ide_db::base_db::{Cancelled, SourceDatabaseExt, VfsPath};
use lsp_server::{Connection, Notification, Request};
use lsp_types::notification::Notification as _;
use vfs::{ChangeKind, FileId};
@@ -19,7 +19,7 @@ use crate::{
from_proto,
global_state::{file_id_to_url, url_to_file_id, GlobalState},
handlers, lsp_ext,
- lsp_utils::{apply_document_changes, is_cancelled, notification_is, Progress},
+ lsp_utils::{apply_document_changes, notification_is, Progress},
mem_docs::DocumentData,
reload::{self, BuildDataProgress, ProjectWorkspaceProgress},
Result,
@@ -60,6 +60,7 @@ enum Event {
#[derive(Debug)]
pub(crate) enum Task {
Response(lsp_server::Response),
+ Retry(lsp_server::Request),
Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
PrimeCaches(PrimeCachesProgress),
FetchWorkspace(ProjectWorkspaceProgress),
@@ -196,7 +197,7 @@ impl GlobalState {
let was_quiescent = self.is_quiescent();
match event {
Event::Lsp(msg) => match msg {
- lsp_server::Message::Request(req) => self.on_request(loop_start, req)?,
+ lsp_server::Message::Request(req) => self.on_request(loop_start, req),
lsp_server::Message::Notification(not) => {
self.on_notification(not)?;
}
@@ -208,6 +209,7 @@ impl GlobalState {
loop {
match task {
Task::Response(response) => self.respond(response),
+ Task::Retry(req) => self.on_request(loop_start, req),
Task::Diagnostics(diagnostics_per_file) => {
for (file_id, diagnostics) in diagnostics_per_file {
self.diagnostics.set_native_diagnostics(file_id, diagnostics)
@@ -553,7 +555,7 @@ impl GlobalState {
Ok(())
}
- fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> {
+ fn on_request(&mut self, request_received: Instant, req: Request) {
self.register_request(&req, request_received);
if self.shutdown_requested {
@@ -562,8 +564,7 @@ impl GlobalState {
lsp_server::ErrorCode::InvalidRequest as i32,
"Shutdown already requested.".to_owned(),
));
-
- return Ok(());
+ return;
}
// Avoid flashing a bunch of unresolved references during initial load.
@@ -573,21 +574,21 @@ impl GlobalState {
lsp_server::ErrorCode::ContentModified as i32,
"waiting for cargo metadata or cargo check".to_owned(),
));
- return Ok(());
+ return;
}
RequestDispatcher { req: Some(req), global_state: self }
.on_sync_mut::<lsp_types::request::Shutdown>(|s, ()| {
s.shutdown_requested = true;
Ok(())
- })?
- .on_sync_mut::<lsp_ext::ReloadWorkspace>(handlers::handle_workspace_reload)?
- .on_sync_mut::<lsp_ext::MemoryUsage>(handlers::handle_memory_usage)?
- .on_sync_mut::<lsp_ext::ShuffleCrateGraph>(handlers::handle_shuffle_crate_graph)?
- .on_sync::<lsp_ext::JoinLines>(handlers::handle_join_lines)?
- .on_sync::<lsp_ext::OnEnter>(handlers::handle_on_enter)?
- .on_sync::<lsp_types::request::SelectionRangeRequest>(handlers::handle_selection_range)?
- .on_sync::<lsp_ext::MatchingBrace>(handlers::handle_matching_brace)?
+ })
+ .on_sync_mut::<lsp_ext::ReloadWorkspace>(handlers::handle_workspace_reload)
+ .on_sync_mut::<lsp_ext::MemoryUsage>(handlers::handle_memory_usage)
+ .on_sync_mut::<lsp_ext::ShuffleCrateGraph>(handlers::handle_shuffle_crate_graph)
+ .on_sync::<lsp_ext::JoinLines>(handlers::handle_join_lines)
+ .on_sync::<lsp_ext::OnEnter>(handlers::handle_on_enter)
+ .on_sync::<lsp_types::request::SelectionRangeRequest>(handlers::handle_selection_range)
+ .on_sync::<lsp_ext::MatchingBrace>(handlers::handle_matching_brace)
.on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status)
.on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree)
.on::<lsp_ext::ViewHir>(handlers::handle_view_hir)
@@ -644,8 +645,8 @@ impl GlobalState {
.on::<lsp_types::request::WillRenameFiles>(handlers::handle_will_rename_files)
.on::<lsp_ext::Ssr>(handlers::handle_ssr)
.finish();
- Ok(())
}
+
fn on_notification(&mut self, not: Notification) -> Result<()> {
NotificationDispatcher { not: Some(not), global_state: self }
.on::<lsp_types::notification::Cancel>(|this, params| {
@@ -792,7 +793,7 @@ impl GlobalState {
.filter_map(|file_id| {
handlers::publish_diagnostics(&snapshot, file_id)
.map_err(|err| {
- if !is_cancelled(&*err) {
+ if err.is::<Cancelled>() {
tracing::error!("failed to compute diagnostics: {:?}", err);
}
})