]> git.lizzy.rs Git - rust.git/commitdiff
fix: Fix completions disappearing when typing two keys in quick succession
authorLukas Wirth <lukastw97@gmail.com>
Tue, 31 May 2022 22:20:28 +0000 (00:20 +0200)
committerLukas Wirth <lukastw97@gmail.com>
Tue, 31 May 2022 22:20:47 +0000 (00:20 +0200)
crates/rust-analyzer/src/bin/main.rs
crates/rust-analyzer/src/dispatch.rs
crates/rust-analyzer/src/from_proto.rs
crates/rust-analyzer/src/lib.rs
crates/rust-analyzer/src/lsp_utils.rs
crates/rust-analyzer/src/main_loop.rs
crates/rust-analyzer/src/task_pool.rs

index df61ba8eec8466c8365b02c9157862836a1cfe40..a9e79cc7c3e7894e59936b1b5f76c3e00b0991c6 100644 (file)
@@ -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
index d208ba16cb9679419f2e104db071569b2a3af751..8c74fcaeaf5aac6690f069fcb117dca444637d57 100644 (file)
@@ -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,41 @@ 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 result = {
+            let _pctx = stdx::panic_context::enter(panic_context);
+            f(self.global_state, params)
+        };
+        match result_to_response::<R>(req.id.clone(), result) {
+            Ok(response) => self.global_state.respond(response),
+            Err(_) => self.global_state.task_pool.handle.send_retry(req),
         };
-        let _pctx = stdx::panic_context::enter(panic_context);
-
-        let result = f(self.global_state, params);
-        let response = result_to_response::<R>(id, result);
 
-        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 +79,13 @@ pub(crate) fn on_sync<R>(
             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)
+        match thread_result_to_response::<R>(req.id.clone(), result) {
+            Ok(response) => self.global_state.respond(response),
+            Err(_) => self.global_state.task_pool.handle.send_retry(req),
+        };
+
+        self
     }
 
     /// Dispatches the request onto thread pool
@@ -92,7 +98,7 @@ pub(crate) fn on<R>(
         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 +110,10 @@ pub(crate) fn on<R>(
                     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 +132,7 @@ pub(crate) fn finish(&mut self) {
         }
     }
 
-    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 +142,12 @@ fn parse<R>(&mut self) -> Option<(lsp_server::RequestId, R::Params, String)>
             _ => 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 +165,7 @@ fn parse<R>(&mut self) -> Option<(lsp_server::RequestId, R::Params, String)>
 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 +174,22 @@ fn thread_result_to_response<R>(
     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 +197,27 @@ fn thread_result_to_response<R>(
 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> {
index ffc69a419a0fca84200301ff165409401f05ca86..7bdd34d1f093a0f242bed934e1e646b45c10f4ea 100644 (file)
@@ -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) => {
index d6b37760a0ab2762245b87d0aff96a0b08a79d2d..d5bc8f65f829525ecf19ba92b0c7a01fc83d0795 100644 (file)
@@ -49,7 +49,7 @@ macro_rules! eprintln {
 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)
index 460ae4ef4daf907f38f81c692dbba35a5b8b050f..22bab8fa82047991869990429add3484a2499dda 100644 (file)
@@ -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 {
index 3c879687433d3574ec3a323277e0450a019d2350..612d1c9b704445d8f37d7e2485579e4fa4c325f9 100644 (file)
@@ -8,7 +8,7 @@
 
 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 @@
     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),
@@ -172,13 +173,13 @@ fn next_event(&self, inbox: &Receiver<lsp_server::Message>) -> Option<Event> {
                 msg.ok().map(Event::Lsp),
 
             recv(self.task_pool.receiver) -> task =>
-                Some(Event::Task(task.unwrap())),
+                task.ok().map(Event::Task),
 
             recv(self.loader.receiver) -> task =>
-                Some(Event::Vfs(task.unwrap())),
+                task.ok().map(Event::Vfs),
 
             recv(self.flycheck_receiver) -> task =>
-                Some(Event::Flycheck(task.unwrap())),
+                task.ok().map(Event::Flycheck),
         }
     }
 
@@ -196,7 +197,7 @@ fn handle_event(&mut self, event: Event) -> Result<()> {
         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 @@ fn handle_event(&mut self, event: Event) -> Result<()> {
                 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 @@ fn handle_event(&mut self, event: Event) -> Result<()> {
         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 @@ fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()>
                 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 @@ fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()>
                 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 @@ fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()>
             .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 @@ fn update_diagnostics(&mut self) {
                 .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);
                             }
                         })
index 83389373903221fae63de9f15b88336076a759a4..2c11a5f88315d39bc67f36344ae3f2dd2c65dd34 100644 (file)
@@ -2,6 +2,8 @@
 //! properly.
 use crossbeam_channel::Sender;
 
+use crate::main_loop::Task;
+
 pub(crate) struct TaskPool<T> {
     sender: Sender<T>,
     inner: threadpool::ThreadPool,
@@ -44,3 +46,9 @@ fn drop(&mut self) {
         self.inner.join()
     }
 }
+
+impl TaskPool<Task> {
+    pub(crate) fn send_retry(&self, req: lsp_server::Request) {
+        let _ = self.sender.send(Task::Retry(req));
+    }
+}