From c19390992ca2a3bc1d182798e59d56c8b477702d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 1 Sep 2023 21:42:51 +0200 Subject: [PATCH] Reduce semantic token cache lock scopes --- crates/rust-analyzer/src/handlers/request.rs | 20 ++++--- crates/rust-analyzer/src/main_loop.rs | 59 ++++++++++---------- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 5f1f731cff..85ac690a41 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -1569,18 +1569,21 @@ pub(crate) fn handle_semantic_tokens_full_delta( snap.config.highlighting_non_standard_tokens(), ); - let mut cache = snap.semantic_tokens_cache.lock(); - let cached_tokens = cache.entry(params.text_document.uri).or_default(); + let cached_tokens = snap.semantic_tokens_cache.lock().remove(¶ms.text_document.uri); - if let Some(prev_id) = &cached_tokens.result_id { + if let Some(cached_tokens @ lsp_types::SemanticTokens { result_id: Some(prev_id), .. }) = + &cached_tokens + { if *prev_id == params.previous_result_id { let delta = to_proto::semantic_token_delta(cached_tokens, &semantic_tokens); - *cached_tokens = semantic_tokens; + snap.semantic_tokens_cache.lock().insert(params.text_document.uri, semantic_tokens); return Ok(Some(delta.into())); } } - *cached_tokens = semantic_tokens.clone(); + // Clone first to keep the lock short + let semantic_tokens_clone = semantic_tokens.clone(); + snap.semantic_tokens_cache.lock().insert(params.text_document.uri, semantic_tokens_clone); Ok(Some(semantic_tokens.into())) } @@ -1879,12 +1882,15 @@ fn run_rustfmt( // Determine the edition of the crate the file belongs to (if there's multiple, we pick the // highest edition). - let editions = snap + let Ok(editions) = snap .analysis .relevant_crates_for(file_id)? .into_iter() .map(|crate_id| snap.analysis.crate_edition(crate_id)) - .collect::, _>>()?; + .collect::, _>>() + else { + return Ok(None); + }; let edition = editions.iter().copied().max(); let line_index = snap.file_line_index(file_id)?; diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 74036710fa..effa24c937 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -670,6 +670,7 @@ impl GlobalState { } use crate::handlers::request as handlers; + use lsp_types::request as lsp_request; dispatcher // Request handlers that must run on the main thread @@ -682,30 +683,30 @@ impl GlobalState { // are run on the main thread to reduce latency: .on_sync::(handlers::handle_join_lines) .on_sync::(handlers::handle_on_enter) - .on_sync::(handlers::handle_selection_range) + .on_sync::(handlers::handle_selection_range) .on_sync::(handlers::handle_matching_brace) .on_sync::(handlers::handle_on_type_formatting) // Formatting should be done immediately as the editor might wait on it, but we can't // put it on the main thread as we do not want the main thread to block on rustfmt. // So we have an extra thread just for formatting requests to make sure it gets handled // as fast as possible. - .on_fmt_thread::(handlers::handle_formatting) - .on_fmt_thread::(handlers::handle_range_formatting) + .on_fmt_thread::(handlers::handle_formatting) + .on_fmt_thread::(handlers::handle_range_formatting) // We can’t run latency-sensitive request handlers which do semantic // analysis on the main thread because that would block other // requests. Instead, we run these request handlers on higher priority // threads in the threadpool. - .on_latency_sensitive::(handlers::handle_completion) - .on_latency_sensitive::( + .on_latency_sensitive::(handlers::handle_completion) + .on_latency_sensitive::( handlers::handle_completion_resolve, ) - .on_latency_sensitive::( + .on_latency_sensitive::( handlers::handle_semantic_tokens_full, ) - .on_latency_sensitive::( + .on_latency_sensitive::( handlers::handle_semantic_tokens_full_delta, ) - .on_latency_sensitive::( + .on_latency_sensitive::( handlers::handle_semantic_tokens_range, ) // All other request handlers @@ -729,29 +730,25 @@ impl GlobalState { .on::(handlers::handle_open_cargo_toml) .on::(handlers::handle_move_item) .on::(handlers::handle_workspace_symbol) - .on::(handlers::handle_document_symbol) - .on::(handlers::handle_goto_definition) - .on::(handlers::handle_goto_declaration) - .on::(handlers::handle_goto_implementation) - .on::(handlers::handle_goto_type_definition) - .on_no_retry::(handlers::handle_inlay_hints) - .on::(handlers::handle_inlay_hints_resolve) - .on::(handlers::handle_code_lens) - .on::(handlers::handle_code_lens_resolve) - .on::(handlers::handle_folding_range) - .on::(handlers::handle_signature_help) - .on::(handlers::handle_prepare_rename) - .on::(handlers::handle_rename) - .on::(handlers::handle_references) - .on::(handlers::handle_document_highlight) - .on::(handlers::handle_call_hierarchy_prepare) - .on::( - handlers::handle_call_hierarchy_incoming, - ) - .on::( - handlers::handle_call_hierarchy_outgoing, - ) - .on::(handlers::handle_will_rename_files) + .on::(handlers::handle_document_symbol) + .on::(handlers::handle_goto_definition) + .on::(handlers::handle_goto_declaration) + .on::(handlers::handle_goto_implementation) + .on::(handlers::handle_goto_type_definition) + .on_no_retry::(handlers::handle_inlay_hints) + .on::(handlers::handle_inlay_hints_resolve) + .on::(handlers::handle_code_lens) + .on::(handlers::handle_code_lens_resolve) + .on::(handlers::handle_folding_range) + .on::(handlers::handle_signature_help) + .on::(handlers::handle_prepare_rename) + .on::(handlers::handle_rename) + .on::(handlers::handle_references) + .on::(handlers::handle_document_highlight) + .on::(handlers::handle_call_hierarchy_prepare) + .on::(handlers::handle_call_hierarchy_incoming) + .on::(handlers::handle_call_hierarchy_outgoing) + .on::(handlers::handle_will_rename_files) .on::(handlers::handle_ssr) .on::(handlers::handle_view_recursive_memory_layout) .finish();