diff --git a/crates/cairo-lang-language-server/src/lang/db/swapper.rs b/crates/cairo-lang-language-server/src/lang/db/swapper.rs index c2d97290851..a206fcab30f 100644 --- a/crates/cairo-lang-language-server/src/lang/db/swapper.rs +++ b/crates/cairo-lang-language-server/src/lang/db/swapper.rs @@ -1,4 +1,5 @@ use std::collections::HashSet; +use std::panic::{AssertUnwindSafe, catch_unwind}; use std::sync::Arc; use std::time::{Duration, SystemTime}; @@ -11,7 +12,6 @@ use tracing::{error, warn}; use crate::lang::db::AnalysisDatabase; use crate::lang::lsp::LsProtoGroup; -use crate::server::panic::ls_catch_unwind; use crate::{Tricks, env_config}; /// Swaps entire [`AnalysisDatabase`] with empty one periodically. @@ -65,11 +65,11 @@ impl AnalysisDatabaseSwapper { return; } - let Ok(new_db) = ls_catch_unwind(|| { + let Ok(new_db) = catch_unwind(AssertUnwindSafe(|| { let mut new_db = AnalysisDatabase::new(tricks); ensure_exists_in_db(&mut new_db, db, open_files.iter()); new_db - }) else { + })) else { error!("caught panic when preparing new db for swap"); return; }; diff --git a/crates/cairo-lang-language-server/src/server/panic.rs b/crates/cairo-lang-language-server/src/server/panic.rs index 100aa79a767..85bac995a7f 100644 --- a/crates/cairo-lang-language-server/src/server/panic.rs +++ b/crates/cairo-lang-language-server/src/server/panic.rs @@ -1,29 +1,9 @@ use std::any::Any; -use std::panic::{AssertUnwindSafe, catch_unwind}; -use anyhow::anyhow; -use lsp_server::ErrorCode; use salsa::Cancelled; -use tracing::{debug, error}; - -use crate::lsp::result::{LSPError, LSPResult}; - -/// Invokes a closure, capturing the cause of an unwinding panic if one occurs and builds -/// [`LSPResult`] out of it. -pub fn ls_catch_unwind(f: impl FnOnce() -> T) -> LSPResult { - catch_unwind(AssertUnwindSafe(f)).map_err(|err| { - if is_cancelled(&err) { - debug!("LSP worker thread was cancelled"); - LSPError::new(anyhow!("LSP worker thread was cancelled"), ErrorCode::ServerCancelled) - } else { - error!("caught panic in LSP worker thread"); - LSPError::new(anyhow!("caught panic in LSP worker thread"), ErrorCode::InternalError) - } - }) -} /// Checks if the panic was caused by Salsa cancellation. -fn is_cancelled(err: &(dyn Any + Send)) -> bool { +pub fn is_cancelled(err: &(dyn Any + Send)) -> bool { // Salsa is broken and sometimes when cancelled throws regular assert instead of `Cancelled`. err.is::() || err.downcast_ref::<&str>().is_some_and(|msg| { diff --git a/crates/cairo-lang-language-server/src/server/routing/mod.rs b/crates/cairo-lang-language-server/src/server/routing/mod.rs index c181f0d780a..125930d98aa 100644 --- a/crates/cairo-lang-language-server/src/server/routing/mod.rs +++ b/crates/cairo-lang-language-server/src/server/routing/mod.rs @@ -5,6 +5,9 @@ // | Commit: 46a457318d8d259376a2b458b3f814b9b795fe69 | // +------------------------------------------------------------+ +use std::panic::{AssertUnwindSafe, catch_unwind}; + +use anyhow::anyhow; use lsp_server::{ErrorCode, ExtractError, Notification, Request, RequestId}; use lsp_types::notification::{ Cancel, DidChangeConfiguration, DidChangeTextDocument, DidChangeWatchedFiles, @@ -15,12 +18,12 @@ use lsp_types::request::{ CodeActionRequest, Completion, ExecuteCommand, Formatting, GotoDefinition, HoverRequest, Request as RequestTrait, SemanticTokensFullRequest, }; -use tracing::{error, warn}; +use tracing::{debug, error, warn}; use super::client::Responder; use crate::lsp::ext::{ExpandMacro, ProvideVirtualFile, ViewAnalyzedCrates}; use crate::lsp::result::{LSPError, LSPResult, LSPResultEx}; -use crate::server::panic::ls_catch_unwind; +use crate::server::panic::is_cancelled; use crate::server::schedule::{BackgroundSchedule, Task}; use crate::state::State; @@ -122,8 +125,25 @@ fn background_request_task<'a, R: traits::BackgroundDocumentRequestHandler>( Ok(Task::background(schedule, move |state: &State| { let state_snapshot = state.snapshot(); Box::new(move |notifier, responder| { - let result = ls_catch_unwind(|| R::run_with_snapshot(state_snapshot, notifier, params)) - .and_then(|res| res); + let result = catch_unwind(AssertUnwindSafe(|| { + R::run_with_snapshot(state_snapshot, notifier, params) + })) + .map_err(|err| { + if is_cancelled(&err) { + debug!("LSP worker thread was cancelled"); + LSPError::new( + anyhow!("LSP worker thread was cancelled"), + ErrorCode::ServerCancelled, + ) + } else { + error!("caught panic in LSP worker thread"); + LSPError::new( + anyhow!("caught panic in LSP worker thread"), + ErrorCode::InternalError, + ) + } + }) + .and_then(|res| res); respond::(id, result, &responder); }) }))