diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index 1526e16129..4e040a8a7e 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -19,6 +19,7 @@ use project::{InlayHint, ResolveState}; use collections::{hash_map, HashMap, HashSet}; use language::language_settings::InlayHintSettings; +use smol::lock::Semaphore; use sum_tree::Bias; use text::ToOffset; use util::post_inc; @@ -29,6 +30,7 @@ pub struct InlayHintCache { version: usize, pub(super) enabled: bool, update_tasks: HashMap, + lsp_request_limiter: Arc, } #[derive(Debug)] @@ -258,6 +260,7 @@ impl InlayHintCache { hints: HashMap::default(), update_tasks: HashMap::default(), version: 0, + lsp_request_limiter: Arc::new(Semaphore::new(MAX_CONCURRENT_LSP_REQUESTS)), } } @@ -629,6 +632,7 @@ fn spawn_new_update_tasks( buffer_snapshot.clone(), Arc::clone(&visible_hints), cached_excerpt_hints, + Arc::clone(&editor.inlay_hint_cache.lsp_request_limiter), cx, ) }; @@ -733,6 +737,7 @@ fn determine_query_ranges( }) } +const MAX_CONCURRENT_LSP_REQUESTS: usize = 5; const INVISIBLE_RANGES_HINTS_REQUEST_DELAY_MILLIS: u64 = 400; fn new_update_task( @@ -742,6 +747,7 @@ fn new_update_task( buffer_snapshot: BufferSnapshot, visible_hints: Arc>, cached_excerpt_hints: Option>>, + lsp_request_limiter: Arc, cx: &mut ViewContext<'_, '_, Editor>, ) -> Task<()> { cx.spawn(|editor, mut cx| async move { @@ -756,6 +762,7 @@ fn new_update_task( query, invalidate, range, + Arc::clone(&lsp_request_limiter), closure_cx.clone(), ) }; @@ -826,10 +833,41 @@ async fn fetch_and_update_hints( query: ExcerptQuery, invalidate: bool, fetch_range: Range, + lsp_request_limiter: Arc, mut cx: gpui::AsyncAppContext, ) -> anyhow::Result<()> { + let (lsp_request_guard, got_throttled) = if query.invalidate.should_invalidate() { + (None, false) + } else { + match lsp_request_limiter.try_acquire() { + Some(guard) => (Some(guard), false), + None => (Some(lsp_request_limiter.acquire().await), true), + } + }; let inlay_hints_fetch_task = editor .update(&mut cx, |editor, cx| { + if got_throttled { + if let Some((_, _, current_visible_range)) = editor + .excerpt_visible_offsets(None, cx) + .remove(&query.excerpt_id) + { + let visible_offset_length = current_visible_range.len(); + let double_visible_range = current_visible_range + .start + .saturating_sub(visible_offset_length) + ..current_visible_range + .end + .saturating_add(visible_offset_length) + .min(buffer_snapshot.len()); + if !double_visible_range + .contains(&fetch_range.start.to_offset(&buffer_snapshot)) + && !double_visible_range + .contains(&fetch_range.end.to_offset(&buffer_snapshot)) + { + return None; + } + } + } editor .buffer() .read(cx) @@ -847,6 +885,8 @@ async fn fetch_and_update_hints( Some(task) => task.await.context("inlay hint fetch task")?, None => return Ok(()), }; + drop(lsp_request_guard); + let background_task_buffer_snapshot = buffer_snapshot.clone(); let backround_fetch_range = fetch_range.clone(); let new_update = cx