1use std::{
5 fmt,
6 ops::Div as _,
7 panic::AssertUnwindSafe,
8 time::{Duration, Instant},
9};
10
11use crossbeam_channel::{Receiver, never, select};
12use ide_db::base_db::{SourceDatabase, VfsPath};
13use lsp_server::{Connection, Notification, Request};
14use lsp_types::{Notification as _, TextDocumentIdentifier};
15use stdx::thread::ThreadIntent;
16use tracing::{Level, error, span};
17use vfs::{AbsPathBuf, FileId, loader::LoadingProgress};
18
19use crate::{
20 config::Config,
21 diagnostics::{DiagnosticsGeneration, NativeDiagnosticsFetchKind, fetch_native_diagnostics},
22 discover::{DiscoverArgument, DiscoverCommand, DiscoverProjectMessage},
23 flycheck::{self, ClearDiagnosticsKind, ClearScope, FlycheckMessage},
24 global_state::{
25 FetchBuildDataResponse, FetchWorkspaceRequest, FetchWorkspaceResponse, GlobalState,
26 file_id_to_url, url_to_file_id,
27 },
28 handlers::{
29 dispatch::{NotificationDispatcher, RequestDispatcher},
30 request::empty_diagnostic_report,
31 },
32 lsp::{
33 from_proto, to_proto,
34 utils::{Progress, notification_is},
35 },
36 lsp_ext,
37 reload::{BuildDataProgress, ProcMacroProgress, ProjectWorkspaceProgress},
38 test_runner::{CargoTestMessage, CargoTestOutput, TestState},
39};
40
41pub fn main_loop(config: Config, connection: Connection) -> anyhow::Result<()> {
42 tracing::info!("initial config: {:#?}", config);
43
44 #[cfg(windows)]
56 unsafe {
57 use windows_sys::Win32::System::Threading::*;
58 let thread = GetCurrentThread();
59 let thread_priority_above_normal = 1;
60 SetThreadPriority(thread, thread_priority_above_normal);
61 }
62
63 #[cfg(feature = "dhat")]
64 {
65 if let Some(dhat_output_file) = config.dhat_output_file() {
66 *crate::DHAT_PROFILER.lock().unwrap() =
67 Some(dhat::Profiler::builder().file_name(&dhat_output_file).build());
68 }
69 }
70
71 GlobalState::new(connection.sender, config).run(connection.receiver)
72}
73
74enum Event {
75 Lsp(lsp_server::Message),
76 Task(Task),
77 DeferredTask(DeferredTask),
78 Vfs(vfs::loader::Message),
79 Flycheck(FlycheckMessage),
80 TestResult(CargoTestMessage),
81 DiscoverProject(DiscoverProjectMessage),
82 FetchWorkspaces(FetchWorkspaceRequest),
83}
84
85impl fmt::Display for Event {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 match self {
88 Event::Lsp(_) => write!(f, "Event::Lsp"),
89 Event::Task(_) => write!(f, "Event::Task"),
90 Event::Vfs(_) => write!(f, "Event::Vfs"),
91 Event::Flycheck(_) => write!(f, "Event::Flycheck"),
92 Event::DeferredTask(_) => write!(f, "Event::DeferredTask"),
93 Event::TestResult(_) => write!(f, "Event::TestResult"),
94 Event::DiscoverProject(_) => write!(f, "Event::DiscoverProject"),
95 Event::FetchWorkspaces(_) => write!(f, "Event::FetchWorkspaces"),
96 }
97 }
98}
99
100#[derive(Debug)]
101pub(crate) enum DeferredTask {
102 CheckIfIndexed(lsp_types::Uri),
103 CheckProcMacroSources(Vec<FileId>),
104}
105
106#[derive(Debug)]
107pub(crate) enum DiagnosticsTaskKind {
108 Syntax(DiagnosticsGeneration, Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
109 Semantic(DiagnosticsGeneration, Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
110}
111
112#[derive(Debug)]
113pub(crate) enum Task {
114 Response(lsp_server::Response),
115 DiscoverLinkedProjects(DiscoverProjectParam),
116 Retry(lsp_server::Request),
117 Diagnostics(DiagnosticsTaskKind),
118 DiscoverTest(lsp_ext::DiscoverTestResults),
119 PrimeCaches(PrimeCachesProgress),
120 FetchWorkspace(ProjectWorkspaceProgress),
121 FetchBuildData(BuildDataProgress),
122 LoadProcMacros(ProcMacroProgress),
123 BuildDepsHaveChanged,
125}
126
127#[derive(Debug)]
128pub(crate) enum DiscoverProjectParam {
129 Buildfile(AbsPathBuf),
130 Path(AbsPathBuf),
131}
132
133#[derive(Debug)]
134pub(crate) enum PrimeCachesProgress {
135 Begin,
136 Report(ide::ParallelPrimeCachesProgress),
137 End { cancelled: bool },
138}
139
140impl fmt::Debug for Event {
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 let debug_non_verbose = |not: &Notification, f: &mut fmt::Formatter<'_>| {
143 f.debug_struct("Notification").field("method", ¬.method).finish()
144 };
145
146 match self {
147 Event::Lsp(lsp_server::Message::Notification(not))
148 if (notification_is::<lsp_types::DidOpenTextDocumentNotification>(not)
149 || notification_is::<lsp_types::DidChangeTextDocumentNotification>(not)) =>
150 {
151 return debug_non_verbose(not, f);
152 }
153 Event::Task(Task::Response(resp)) => {
154 return f
155 .debug_struct("Response")
156 .field("id", &resp.id)
157 .field("error", &resp.error)
158 .finish();
159 }
160 _ => (),
161 }
162
163 match self {
164 Event::Lsp(it) => fmt::Debug::fmt(it, f),
165 Event::Task(it) => fmt::Debug::fmt(it, f),
166 Event::DeferredTask(it) => fmt::Debug::fmt(it, f),
167 Event::Vfs(it) => fmt::Debug::fmt(it, f),
168 Event::Flycheck(it) => fmt::Debug::fmt(it, f),
169 Event::TestResult(it) => fmt::Debug::fmt(it, f),
170 Event::DiscoverProject(it) => fmt::Debug::fmt(it, f),
171 Event::FetchWorkspaces(it) => fmt::Debug::fmt(it, f),
172 }
173 }
174}
175
176impl GlobalState {
177 fn run(mut self, inbox: Receiver<lsp_server::Message>) -> anyhow::Result<()> {
178 self.update_status_or_notify();
179
180 if self.config.did_save_text_document_dynamic_registration() {
181 let additional_patterns = self
182 .config
183 .discover_workspace_config()
184 .map(|cfg| cfg.files_to_watch.clone().into_iter())
185 .into_iter()
186 .flatten()
187 .map(|f| format!("**/{f}"));
188 self.register_did_save_capability(additional_patterns);
189 }
190
191 if self.config.discover_workspace_config().is_none() {
192 self.fetch_workspaces_queue.request_op(
193 "startup".to_owned(),
194 FetchWorkspaceRequest { path: None, force_crate_graph_reload: false },
195 );
196 if let Some((cause, FetchWorkspaceRequest { path, force_crate_graph_reload })) =
197 self.fetch_workspaces_queue.should_start_op()
198 {
199 self.fetch_workspaces(cause, path, force_crate_graph_reload);
200 }
201 }
202
203 while let Ok(event) = self.next_event(&inbox) {
204 let Some(event) = event else {
205 anyhow::bail!("client exited without proper shutdown sequence");
206 };
207 if matches!(
208 &event,
209 Event::Lsp(lsp_server::Message::Notification(Notification { method, .. }))
210 if method == lsp_types::ExitNotification::METHOD.as_str()
211 ) {
212 return Ok(());
213 }
214 self.handle_event(event);
215 }
216
217 Err(anyhow::anyhow!("A receiver has been dropped, something panicked!"))
218 }
219
220 fn register_did_save_capability(&mut self, additional_patterns: impl Iterator<Item = String>) {
221 let additional_filters = additional_patterns.map(|pattern| {
222 lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern(
223 lsp_types::TextDocumentFilterPattern {
224 language: None,
225 scheme: None,
226 pattern: pattern.into(),
227 },
228 ))
229 });
230
231 let mut selectors = vec![
232 lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern(
233 lsp_types::TextDocumentFilterPattern {
234 language: None,
235 scheme: None,
236 pattern: "**/*.rs".to_owned().into(),
237 },
238 )),
239 lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern(
240 lsp_types::TextDocumentFilterPattern {
241 language: None,
242 scheme: None,
243 pattern: "**/Cargo.toml".to_owned().into(),
244 },
245 )),
246 lsp_types::DocumentFilter::TextDocumentFilter(lsp_types::TextDocumentFilter::Pattern(
247 lsp_types::TextDocumentFilterPattern {
248 language: None,
249 scheme: None,
250 pattern: "**/Cargo.lock".to_owned().into(),
251 },
252 )),
253 ];
254 selectors.extend(additional_filters);
255
256 let save_registration_options = lsp_types::TextDocumentSaveRegistrationOptions {
257 save_options: lsp_types::SaveOptions { include_text: Some(false) },
258 text_document_registration_options: lsp_types::TextDocumentRegistrationOptions {
259 document_selector: Some(selectors),
260 },
261 };
262
263 let registration = lsp_types::Registration {
264 id: "textDocument/didSave".to_owned(),
265 method: "textDocument/didSave".to_owned(),
266 register_options: Some(serde_json::to_value(save_registration_options).unwrap()),
267 };
268 self.send_request::<lsp_types::RegistrationRequest>(
269 lsp_types::RegistrationParams { registrations: vec![registration] },
270 |_, _| (),
271 );
272 }
273
274 fn next_event(
275 &mut self,
276 inbox: &Receiver<lsp_server::Message>,
277 ) -> Result<Option<Event>, crossbeam_channel::RecvError> {
278 if let Ok(task) = self.fmt_pool.receiver.try_recv() {
280 return Ok(Some(Event::Task(task)));
281 }
282
283 select! {
284 recv(inbox) -> msg =>
285 return Ok(msg.ok().map(Event::Lsp)),
286
287 recv(self.task_pool.receiver) -> task =>
288 task.map(Event::Task),
289
290 recv(self.deferred_task_queue.receiver) -> task =>
291 task.map(Event::DeferredTask),
292
293 recv(self.fmt_pool.receiver) -> task =>
294 task.map(Event::Task),
295
296 recv(self.loader.receiver) -> task =>
297 task.map(Event::Vfs),
298
299 recv(self.flycheck_receiver) -> task =>
300 task.map(Event::Flycheck),
301
302 recv(self.test_run_receiver) -> task =>
303 task.map(Event::TestResult),
304
305 recv(self.discover_receiver) -> task =>
306 task.map(Event::DiscoverProject),
307
308 recv(self.fetch_ws_receiver.as_ref().map_or(&never(), |(chan, _)| chan)) -> _instant => {
309 Ok(Event::FetchWorkspaces(self.fetch_ws_receiver.take().unwrap().1))
310 },
311 }
312 .map(Some)
313 }
314
315 fn handle_event(&mut self, event: Event) {
316 let loop_start = Instant::now();
317 let _p = tracing::info_span!("GlobalState::handle_event", event = %event).entered();
318
319 let event_dbg_msg = format!("{event:?}");
320 tracing::debug!(?event, "handle_event");
321
322 let was_quiescent = self.is_quiescent();
323
324 let mut cancellation_time = None;
325 match event {
326 Event::Lsp(msg) => match msg {
327 lsp_server::Message::Request(req) => self.on_new_request(loop_start, req),
328 lsp_server::Message::Notification(not) => self.on_notification(not),
329 lsp_server::Message::Response(resp) => self.complete_request(resp),
330 },
331 Event::DeferredTask(task) => {
332 let _p = tracing::info_span!("GlobalState::handle_event/queued_task").entered();
333 self.handle_deferred_task(task);
334 while loop_start.elapsed() < Duration::from_millis(50)
336 && let Ok(task) = self.deferred_task_queue.receiver.try_recv()
337 {
338 self.handle_deferred_task(task);
339 }
340 }
341 Event::Task(task) => {
342 let _p = tracing::info_span!("GlobalState::handle_event/task").entered();
343 let mut prime_caches_progress = Vec::new();
344
345 cancellation_time = self.handle_task(&mut prime_caches_progress, task);
346 while loop_start.elapsed() < Duration::from_millis(50)
348 && let Ok(task) = self.task_pool.receiver.try_recv()
349 {
350 self.handle_task(&mut prime_caches_progress, task);
351 }
352
353 let title = "Indexing";
354 let cancel_token = || Some("rustAnalyzer/cachePriming".to_owned());
355
356 let mut last_report = None;
357 for progress in prime_caches_progress {
358 match progress {
359 PrimeCachesProgress::Begin => {
360 self.report_progress(
361 title,
362 Progress::Begin,
363 None,
364 Some(0.0),
365 cancel_token(),
366 );
367 }
368 PrimeCachesProgress::Report(report) => {
369 let message = match &*report.crates_currently_indexing {
370 [crate_name] => Some(format!(
371 "{}/{} ({})",
372 report.crates_done,
373 report.crates_total,
374 crate_name.as_str(),
375 )),
376 [crate_name, rest @ ..] => Some(format!(
377 "{}/{} ({} + {} more)",
378 report.crates_done,
379 report.crates_total,
380 crate_name.as_str(),
381 rest.len()
382 )),
383 _ => None,
384 };
385
386 last_report = Some((
389 message,
390 Progress::fraction(report.crates_done, report.crates_total),
391 report.work_type,
392 ));
393 }
394 PrimeCachesProgress::End { cancelled } => {
395 self.analysis_host.trigger_garbage_collection();
396 self.prime_caches_queue.op_completed(());
397 if cancelled {
398 self.prime_caches_queue
399 .request_op("restart after cancellation".to_owned(), ());
400 } else if self.config.check_on_save(None)
401 && self.config.flycheck_workspace(None)
402 && !self.fetch_build_data_queue.op_requested()
403 {
404 self.flycheck
408 .iter()
409 .for_each(|flycheck| flycheck.restart_workspace(None));
410 }
411 if let Some((message, fraction, title)) = last_report.take() {
412 self.report_progress(
413 title,
414 Progress::Report,
415 message,
416 Some(fraction),
417 cancel_token(),
418 );
419 }
420 self.report_progress(
421 title,
422 Progress::End,
423 None,
424 Some(1.0),
425 cancel_token(),
426 );
427 }
428 };
429 }
430 if let Some((message, fraction, title)) = last_report.take() {
431 self.report_progress(
432 title,
433 Progress::Report,
434 message,
435 Some(fraction),
436 cancel_token(),
437 );
438 }
439 }
440 Event::Vfs(message) => {
441 let _p = tracing::info_span!("GlobalState::handle_event/vfs").entered();
442 let mut last_progress_report = None;
443 self.handle_vfs_msg(message, &mut last_progress_report);
444 while loop_start.elapsed() < Duration::from_millis(50)
446 && let Ok(message) = self.loader.receiver.try_recv()
447 {
448 self.handle_vfs_msg(message, &mut last_progress_report);
449 }
450 if let Some((message, fraction)) = last_progress_report {
451 self.report_progress(
452 "Roots Scanned",
453 Progress::Report,
454 Some(message),
455 Some(fraction),
456 None,
457 );
458 }
459 }
460 Event::Flycheck(message) => {
461 let mut cargo_finished = false;
462 self.handle_flycheck_msg(message, &mut cargo_finished);
463 while loop_start.elapsed() < Duration::from_millis(50)
465 && let Ok(message) = self.flycheck_receiver.try_recv()
466 {
467 self.handle_flycheck_msg(message, &mut cargo_finished);
468 }
469 if cargo_finished {
470 self.send_request::<lsp_types::DiagnosticRefreshRequest>((), |_, _| ());
471 }
472 }
473 Event::TestResult(message) => {
474 let _p = tracing::info_span!("GlobalState::handle_event/test_result").entered();
475 self.handle_cargo_test_msg(message);
476 while loop_start.elapsed() < Duration::from_millis(50)
478 && let Ok(message) = self.test_run_receiver.try_recv()
479 {
480 self.handle_cargo_test_msg(message);
481 }
482 }
483 Event::DiscoverProject(message) => {
484 self.handle_discover_msg(message);
485 while loop_start.elapsed() < Duration::from_millis(50)
487 && let Ok(message) = self.discover_receiver.try_recv()
488 {
489 self.handle_discover_msg(message);
490 }
491 }
492 Event::FetchWorkspaces(req) => {
493 self.fetch_workspaces_queue.request_op("project structure change".to_owned(), req)
494 }
495 }
496 let event_handling_duration = loop_start.elapsed();
497 let ((state_changed, changes_cancellation_time), memdocs_added_or_removed) =
498 if self.vfs_done {
499 if let Some(cause) = self.wants_to_switch.take() {
500 cancellation_time = match (cancellation_time, self.switch_workspaces(cause)) {
501 (Some(a), Some(b)) => Some(a + b),
502 (Some(d), None) | (None, Some(d)) => Some(d),
503 (None, None) => None,
504 };
505 }
506 (self.process_changes(), self.mem_docs.take_changes())
507 } else {
508 ((false, None), false)
509 };
510 cancellation_time = match (cancellation_time, changes_cancellation_time) {
511 (Some(a), Some(b)) => Some(a + b),
512 (Some(d), None) | (None, Some(d)) => Some(d),
513 (None, None) => None,
514 };
515
516 let mut gc_elapsed = None;
517 if self.is_quiescent() {
518 let became_quiescent = !was_quiescent;
519 if became_quiescent {
520 let proc_macros_loaded = self.config.prefill_caches()
522 && (!self.config.expand_proc_macros()
523 || self.fetch_proc_macros_queue.last_op_result().copied().unwrap_or(false));
524 if proc_macros_loaded {
525 self.prime_caches_queue.request_op("became quiescent".to_owned(), ());
526 }
527 if self.config.check_on_save(None)
528 && self.config.flycheck_workspace(None)
529 && !self.fetch_build_data_queue.op_requested()
530 {
531 if !self.config.prefill_caches() {
532 self.flycheck.iter().for_each(|flycheck| flycheck.restart_workspace(None));
533 } else if proc_macros_loaded
534 && !self.prime_caches_queue.op_in_progress()
535 && !self.prime_caches_queue.op_requested()
536 {
537 self.flycheck.iter().for_each(|flycheck| flycheck.restart_workspace(None));
538 }
539 }
540 }
541
542 let client_refresh = became_quiescent || state_changed;
543 if client_refresh {
544 if self.config.semantic_tokens_refresh() {
546 self.semantic_tokens_cache.lock().clear();
547 self.send_request::<lsp_types::SemanticTokensRefreshRequest>((), |_, _| ());
548 }
549
550 if self.config.code_lens_refresh() {
552 self.send_request::<lsp_types::CodeLensRefreshRequest>((), |_, _| ());
553 }
554
555 if self.config.inlay_hints_refresh() {
557 self.send_request::<lsp_types::InlayHintRefreshRequest>((), |_, _| ());
558 }
559
560 if self.config.diagnostics_refresh() {
561 self.send_request::<lsp_types::DiagnosticRefreshRequest>((), |_, _| ());
562 }
563 }
564
565 let project_or_mem_docs_changed =
566 became_quiescent || state_changed || memdocs_added_or_removed;
567 if project_or_mem_docs_changed
568 && !self.config.text_document_diagnostic()
569 && self.config.publish_diagnostics(None)
570 {
571 self.update_diagnostics();
572 }
573 if project_or_mem_docs_changed && self.config.test_explorer() {
574 self.update_tests();
575 }
576
577 let current_revision = self.analysis_host.raw_database().nonce_and_revision().1;
578 if self.task_pool.handle.is_empty()
580 && self.fmt_pool.handle.is_empty()
581 && current_revision != self.last_gc_revision
582 {
583 let gc_start = Instant::now();
584 self.analysis_host.trigger_garbage_collection();
585 self.last_gc_revision = self.analysis_host.raw_database().nonce_and_revision().1;
586 gc_elapsed = Some(gc_start.elapsed());
587 }
588 }
589
590 self.cleanup_discover_handles();
591
592 if let Some(diagnostic_changes) = self.diagnostics.take_changes() {
593 for file_id in diagnostic_changes {
594 let uri = file_id_to_url(&self.vfs.read().0, file_id);
595 let version = from_proto::vfs_path(&uri)
596 .ok()
597 .and_then(|path| self.mem_docs.get(&path).map(|it| it.version));
598
599 let diagnostics =
600 self.diagnostics.diagnostics_for(file_id).cloned().collect::<Vec<_>>();
601 self.publish_diagnostics(uri, version, diagnostics);
602 }
603 }
604
605 if (self.config.cargo_autoreload_config(None)
606 || self.config.discover_workspace_config().is_some())
607 && let Some((cause, FetchWorkspaceRequest { path, force_crate_graph_reload })) =
608 self.fetch_workspaces_queue.should_start_op()
609 {
610 self.fetch_workspaces(cause, path, force_crate_graph_reload);
611 }
612
613 if !self.fetch_workspaces_queue.op_in_progress() {
614 if let Some((cause, ())) = self.fetch_build_data_queue.should_start_op() {
615 self.fetch_build_data(cause);
616 } else if let Some((cause, (change, paths))) =
617 self.fetch_proc_macros_queue.should_start_op()
618 {
619 self.fetch_proc_macros(cause, change, paths);
620 }
621 }
622
623 if let Some((cause, ())) = self.prime_caches_queue.should_start_op() {
624 self.prime_caches(cause);
625 }
626
627 self.update_status_or_notify();
628
629 let loop_duration = loop_start.elapsed();
630 if loop_duration > Duration::from_millis(100) && was_quiescent {
631 tracing::warn!(
632 "overly long loop turn took {loop_duration:?}:\n\
633 (event handling took {event_handling_duration:?}): {event_dbg_msg}\n\
634 (cancellation took {cancellation_time:?})
635 (garbage collection took {gc_elapsed:?})"
636 );
637 self.poke_ra_ap_rust_analyzer_developer(format!(
638 "overly long loop turn took {loop_duration:?}:\n\
639 (event handling took {event_handling_duration:?}): {event_dbg_msg}\n\
640 (cancellation took {cancellation_time:?})
641 (garbage collection took {gc_elapsed:?})"
642 ));
643 }
644 }
645
646 fn prime_caches(&mut self, cause: String) {
647 tracing::debug!(%cause, "will prime caches");
648 let num_worker_threads = self.config.prime_caches_num_threads();
649
650 self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, {
651 let analysis = AssertUnwindSafe(self.snapshot().analysis);
652 move |sender| {
653 sender.send(Task::PrimeCaches(PrimeCachesProgress::Begin)).unwrap();
654 let res = analysis.parallel_prime_caches(num_worker_threads, |progress| {
655 let report = PrimeCachesProgress::Report(progress);
656 sender.send(Task::PrimeCaches(report)).unwrap();
657 });
658 sender
659 .send(Task::PrimeCaches(PrimeCachesProgress::End { cancelled: res.is_err() }))
660 .unwrap();
661 }
662 });
663 }
664
665 fn update_diagnostics(&mut self) {
666 let db = self.analysis_host.raw_database();
667 let generation = self.diagnostics.next_generation();
668 let subscriptions = {
669 let vfs = &self.vfs.read().0;
670 self.mem_docs
671 .iter()
672 .map(|path| vfs.file_id(path).unwrap())
673 .filter_map(|(file_id, excluded)| {
674 (excluded == vfs::FileExcluded::No).then_some(file_id)
675 })
676 .filter(|&file_id| {
677 let source_root_id = db.file_source_root(file_id).source_root_id(db);
678 let source_root = db.source_root(source_root_id).source_root(db);
679 !source_root.is_library
685 })
686 .collect::<std::sync::Arc<_>>()
687 };
688 tracing::trace!("updating notifications for {:?}", subscriptions);
689 let max_tasks = self.config.main_loop_num_threads().div(4).max(1);
692 let chunk_length = subscriptions.len() / max_tasks;
693 let remainder = subscriptions.len() % max_tasks;
694
695 let mut start = 0;
696 for task_idx in 0..max_tasks {
697 let extra = if task_idx < remainder { 1 } else { 0 };
698 let end = start + chunk_length + extra;
699 let slice = start..end;
700 if slice.is_empty() {
701 break;
702 }
703 let snapshot = self.snapshot();
706 self.task_pool.handle.spawn_with_sender(ThreadIntent::LatencySensitive, {
707 let subscriptions = subscriptions.clone();
708 let fetch_semantic = self.vfs_done
717 && self.fetch_workspaces_queue.last_op_result().is_some()
718 && (!self.config.run_build_scripts(None)
719 || (self.fetch_build_data_queue.last_op_result().is_none()
720 && !self.fetch_build_data_queue.op_in_progress()))
721 && (!self.config.expand_proc_macros()
722 || (self.fetch_proc_macros_queue.last_op_result().is_none()
723 && !self.fetch_proc_macros_queue.op_in_progress()));
724 move |sender| {
725 let snapshot = AssertUnwindSafe(&snapshot);
727 let diags = std::panic::catch_unwind(|| {
728 fetch_native_diagnostics(
729 &snapshot,
730 subscriptions.clone(),
731 slice.clone(),
732 NativeDiagnosticsFetchKind::Syntax,
733 )
734 })
735 .unwrap_or_else(|_| {
736 subscriptions.iter().map(|&id| (id, Vec::new())).collect::<Vec<_>>()
737 });
738 sender
739 .send(Task::Diagnostics(DiagnosticsTaskKind::Syntax(generation, diags)))
740 .unwrap();
741
742 if fetch_semantic {
743 let diags = std::panic::catch_unwind(|| {
744 fetch_native_diagnostics(
745 &snapshot,
746 subscriptions.clone(),
747 slice.clone(),
748 NativeDiagnosticsFetchKind::Semantic,
749 )
750 })
751 .unwrap_or_else(|_| {
752 subscriptions.iter().map(|&id| (id, Vec::new())).collect::<Vec<_>>()
753 });
754 sender
755 .send(Task::Diagnostics(DiagnosticsTaskKind::Semantic(
756 generation, diags,
757 )))
758 .unwrap();
759 }
760 }
761 });
762 start = end;
763 }
764 }
765
766 fn update_tests(&mut self) {
767 if !self.vfs_done {
768 return;
769 }
770 let db = self.analysis_host.raw_database();
771 let subscriptions = self
772 .mem_docs
773 .iter()
774 .map(|path| self.vfs.read().0.file_id(path).unwrap())
775 .filter_map(|(file_id, excluded)| {
776 (excluded == vfs::FileExcluded::No).then_some(file_id)
777 })
778 .filter(|&file_id| {
779 let source_root_id = db.file_source_root(file_id).source_root_id(db);
780 let source_root = db.source_root(source_root_id).source_root(db);
781 !source_root.is_library
782 })
783 .collect::<Vec<_>>();
784 tracing::trace!("updating tests for {:?}", subscriptions);
785
786 self.task_pool.handle.spawn(ThreadIntent::LatencySensitive, {
789 let snapshot = self.snapshot();
790 move || {
791 let tests = subscriptions
792 .iter()
793 .copied()
794 .filter_map(|f| snapshot.analysis.discover_tests_in_file(f).ok())
795 .flatten()
796 .collect::<Vec<_>>();
797
798 Task::DiscoverTest(lsp_ext::DiscoverTestResults {
799 tests: tests
800 .into_iter()
801 .filter_map(|t| {
802 let line_index = t.file.and_then(|f| snapshot.file_line_index(f).ok());
803 to_proto::test_item(&snapshot, t, line_index.as_ref())
804 })
805 .collect(),
806 scope: None,
807 scope_file: Some(
808 subscriptions
809 .into_iter()
810 .map(|f| TextDocumentIdentifier { uri: to_proto::url(&snapshot, f) })
811 .collect(),
812 ),
813 })
814 }
815 });
816 }
817
818 fn update_status_or_notify(&mut self) {
819 let status = self.current_status();
820 if self.last_reported_status != status {
821 self.last_reported_status = status.clone();
822
823 if self.config.server_status_notification() {
824 self.send_notification::<lsp_ext::ServerStatusNotification>(status);
825 } else if let (
826 health @ (lsp_ext::Health::Warning | lsp_ext::Health::Error),
827 Some(message),
828 ) = (status.health, &status.message)
829 {
830 let open_log_button = tracing::enabled!(tracing::Level::ERROR)
831 && (self.fetch_build_data_error().is_err()
832 || self.fetch_workspace_error().is_err());
833 self.show_message(
834 match health {
835 lsp_ext::Health::Ok => lsp_types::MessageType::Info,
836 lsp_ext::Health::Warning => lsp_types::MessageType::Warning,
837 lsp_ext::Health::Error => lsp_types::MessageType::Error,
838 },
839 message.clone(),
840 open_log_button,
841 );
842 }
843 }
844 }
845
846 fn handle_task(
847 &mut self,
848 prime_caches_progress: &mut Vec<PrimeCachesProgress>,
849 task: Task,
850 ) -> Option<Duration> {
851 let mut cancellation_time = None;
852 match task {
853 Task::Response(response) => self.respond(response),
854 Task::Retry(req) if !self.is_completed(&req) => self.on_request(req),
856 Task::Retry(_) => (),
857 Task::Diagnostics(kind) => {
858 self.diagnostics.set_native_diagnostics(kind);
859 }
860 Task::PrimeCaches(progress) => match progress {
861 PrimeCachesProgress::Begin => prime_caches_progress.push(progress),
862 PrimeCachesProgress::Report(_) => {
863 match prime_caches_progress.last_mut() {
864 Some(last @ PrimeCachesProgress::Report(_)) => {
865 *last = progress;
867 }
868 _ => prime_caches_progress.push(progress),
869 }
870 }
871 PrimeCachesProgress::End { .. } => prime_caches_progress.push(progress),
872 },
873 Task::FetchWorkspace(progress) => {
874 let (state, msg) = match progress {
875 ProjectWorkspaceProgress::Begin => (Progress::Begin, None),
876 ProjectWorkspaceProgress::Report(msg) => (Progress::Report, Some(msg)),
877 ProjectWorkspaceProgress::End(workspaces, force_crate_graph_reload) => {
878 let resp = FetchWorkspaceResponse { workspaces, force_crate_graph_reload };
879 self.fetch_workspaces_queue.op_completed(resp);
880 if let Err(e) = self.fetch_workspace_error() {
881 error!("FetchWorkspaceError: {e}");
882 }
883 self.wants_to_switch = Some("fetched workspace".to_owned());
884 self.diagnostics.clear_check_all();
885 (Progress::End, None)
886 }
887 };
888
889 self.report_progress("Fetching", state, msg, None, None);
890 }
891 Task::DiscoverLinkedProjects(arg) => {
892 if let Some(cfg) = self.config.discover_workspace_config() {
893 let command = cfg.command.clone();
894 let discover = DiscoverCommand::new(self.discover_sender.clone(), command);
895
896 let discover_path = match &arg {
897 DiscoverProjectParam::Buildfile(it) => it,
898 DiscoverProjectParam::Path(it) => it,
899 };
900 let current_dir =
901 self.config.workspace_root_for(discover_path.as_path()).clone();
902
903 let arg = match arg {
904 DiscoverProjectParam::Buildfile(it) => DiscoverArgument::Buildfile(it),
905 DiscoverProjectParam::Path(it) => DiscoverArgument::Path(it),
906 };
907
908 match discover.spawn(arg, current_dir.as_ref()) {
909 Ok(handle) => {
910 if self.discover_jobs_active == 0 {
911 let title = &cfg.progress_label.clone();
912 self.report_progress(title, Progress::Begin, None, None, None);
913 }
914 self.discover_jobs_active += 1;
915 self.discover_handles.push(handle)
916 }
917 Err(e) => self.show_message(
918 lsp_types::MessageType::Error,
919 format!("Failed to spawn project discovery command: {e:#}"),
920 false,
921 ),
922 }
923 }
924 }
925 Task::FetchBuildData(progress) => {
926 let (state, msg) = match progress {
927 BuildDataProgress::Begin => (Some(Progress::Begin), None),
928 BuildDataProgress::Report(msg) => (Some(Progress::Report), Some(msg)),
929 BuildDataProgress::End((workspaces, build_scripts)) => {
930 let resp = FetchBuildDataResponse { workspaces, build_scripts };
931 self.fetch_build_data_queue.op_completed(resp);
932
933 if let Err(e) = self.fetch_build_data_error() {
934 error!("FetchBuildDataError: {e}");
935 }
936
937 if self.wants_to_switch.is_none() {
938 self.wants_to_switch = Some("fetched build data".to_owned());
939 }
940 (Some(Progress::End), None)
941 }
942 };
943
944 if let Some(state) = state {
945 self.report_progress("Building compile-time-deps", state, msg, None, None);
946 }
947 }
948 Task::LoadProcMacros(progress) => {
949 let (state, msg) = match progress {
950 ProcMacroProgress::Begin => (Some(Progress::Begin), None),
951 ProcMacroProgress::Report(msg) => (Some(Progress::Report), Some(msg)),
952 ProcMacroProgress::End(change) => {
953 self.fetch_proc_macros_queue.op_completed(true);
954 cancellation_time = Some(self.analysis_host.apply_change(change));
955 _ = self.finish_loading_crate_graph();
957 (Some(Progress::End), None)
958 }
959 };
960
961 if let Some(state) = state {
962 self.report_progress("Loading proc-macros", state, msg, None, None);
963 }
964 }
965 Task::BuildDepsHaveChanged => self.build_deps_changed = true,
966 Task::DiscoverTest(tests) => {
967 self.send_notification::<lsp_ext::DiscoveredTestsNotification>(tests);
968 }
969 }
970 cancellation_time
971 }
972
973 fn handle_vfs_msg(
974 &mut self,
975 message: vfs::loader::Message,
976 last_progress_report: &mut Option<(String, f64)>,
977 ) {
978 let _p = tracing::info_span!("GlobalState::handle_vfs_msg").entered();
979 let is_changed = matches!(message, vfs::loader::Message::Changed { .. });
980 match message {
981 vfs::loader::Message::Changed { files } | vfs::loader::Message::Loaded { files } => {
982 let _p = tracing::info_span!("GlobalState::handle_vfs_msg{changed/load}").entered();
983 self.debounce_workspace_fetch();
984 let vfs = &mut self.vfs.write().0;
985 for (path, contents) in files {
986 if matches!(path.name_and_extension(), Some(("minicore", Some("rs")))) {
987 self.minicore.minicore_text = contents
989 .as_ref()
990 .and_then(|contents| str::from_utf8(contents).ok())
991 .map(triomphe::Arc::from);
992 }
993
994 let path = VfsPath::from(path);
995 if !self.mem_docs.contains(&path)
998 && (is_changed || vfs.file_id(&path).is_none())
999 {
1000 vfs.set_file_contents(path, contents);
1001 }
1002 }
1003 }
1004 vfs::loader::Message::Progress { n_total, n_done, dir, config_version } => {
1005 let _p = span!(Level::INFO, "GlobalState::handle_vfs_msg/progress").entered();
1006 stdx::always!(config_version <= self.vfs_config_version);
1007
1008 let (n_done, state) = match n_done {
1009 LoadingProgress::Started => {
1010 self.vfs_span =
1011 Some(span!(Level::INFO, "vfs_load", total = n_total).entered());
1012 (0, Progress::Begin)
1013 }
1014 LoadingProgress::Progress(n_done) => (n_done.min(n_total), Progress::Report),
1015 LoadingProgress::Finished => {
1016 self.vfs_span = None;
1017 (n_total, Progress::End)
1018 }
1019 };
1020
1021 self.vfs_progress_config_version = config_version;
1022 self.vfs_done = state == Progress::End;
1023
1024 let mut message = format!("{n_done}/{n_total}");
1025 if let Some(dir) = dir {
1026 message += &format!(
1027 ": {}",
1028 match dir.strip_prefix(self.config.workspace_root_for(&dir)) {
1029 Some(relative_path) => relative_path.as_utf8_path(),
1030 None => dir.as_ref(),
1031 }
1032 );
1033 }
1034
1035 match state {
1036 Progress::Begin => self.report_progress(
1037 "Roots Scanned",
1038 state,
1039 Some(message),
1040 Some(Progress::fraction(n_done, n_total)),
1041 None,
1042 ),
1043 Progress::Report => {
1046 if last_progress_report.is_none() {
1047 self.report_progress(
1048 "Roots Scanned",
1049 state,
1050 Some(message.clone()),
1051 Some(Progress::fraction(n_done, n_total)),
1052 None,
1053 );
1054 }
1055
1056 *last_progress_report =
1057 Some((message, Progress::fraction(n_done, n_total)));
1058 }
1059 Progress::End => {
1060 last_progress_report.take();
1061 self.report_progress(
1062 "Roots Scanned",
1063 state,
1064 Some(message),
1065 Some(Progress::fraction(n_done, n_total)),
1066 None,
1067 )
1068 }
1069 }
1070 }
1071 }
1072 }
1073
1074 fn handle_deferred_task(&mut self, task: DeferredTask) {
1075 match task {
1076 DeferredTask::CheckIfIndexed(uri) => {
1077 let snap = self.snapshot();
1078
1079 self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, move |sender| {
1080 let _p = tracing::info_span!("GlobalState::check_if_indexed").entered();
1081 tracing::debug!(?uri, "handling uri");
1082 let Some(id) = from_proto::file_id(&snap, &uri).expect("unable to get FileId")
1083 else {
1084 return;
1085 };
1086 if let Ok(crates) = &snap.analysis.crates_for(id) {
1087 if crates.is_empty() {
1088 if snap.config.discover_workspace_config().is_some() {
1089 let path =
1090 from_proto::abs_path(&uri).expect("Unable to get AbsPath");
1091 let arg = DiscoverProjectParam::Path(path);
1092 sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
1093 }
1094 } else {
1095 tracing::debug!(?uri, "is indexed");
1096 }
1097 }
1098 });
1099 }
1100 DeferredTask::CheckProcMacroSources(modified_rust_files) => {
1101 let analysis = AssertUnwindSafe(self.snapshot().analysis);
1102 self.task_pool.handle.spawn_with_sender(stdx::thread::ThreadIntent::Worker, {
1103 move |sender| {
1104 if modified_rust_files.into_iter().any(|file_id| {
1105 match analysis.crates_for(file_id) {
1107 Ok(crates) => crates.iter().any(|&krate| {
1108 analysis.is_proc_macro_crate(krate).is_ok_and(|it| it)
1109 }),
1110 _ => false,
1111 }
1112 }) {
1113 sender.send(Task::BuildDepsHaveChanged).unwrap();
1114 }
1115 }
1116 });
1117 }
1118 }
1119 }
1120
1121 fn handle_discover_msg(&mut self, message: DiscoverProjectMessage) {
1122 let title = self
1123 .config
1124 .discover_workspace_config()
1125 .map(|cfg| cfg.progress_label.clone())
1126 .expect("No title could be found; this is a bug");
1127 match message {
1128 DiscoverProjectMessage::Finished { project, buildfile } => {
1129 self.discover_jobs_active = self.discover_jobs_active.saturating_sub(1);
1130 if self.discover_jobs_active == 0 {
1131 self.report_progress(&title, Progress::End, None, None, None);
1132 }
1133
1134 let mut config = Config::clone(&*self.config);
1135 config.add_discovered_project_from_command(project, buildfile);
1136 self.update_configuration(config);
1137 }
1138 DiscoverProjectMessage::Progress { message } => {
1139 if self.discover_jobs_active > 0 {
1140 self.report_progress(&title, Progress::Report, Some(message), None, None)
1141 }
1142 }
1143 DiscoverProjectMessage::Error { error, source } => {
1144 let message = format!("Project discovery failed: {error}");
1145 self.show_and_log_error(message.clone(), source);
1146
1147 self.discover_jobs_active = self.discover_jobs_active.saturating_sub(1);
1148 if self.discover_jobs_active == 0 {
1149 self.report_progress(&title, Progress::End, Some(message), None, None)
1150 }
1151 }
1152 }
1153 }
1154
1155 fn cleanup_discover_handles(&mut self) {
1158 let mut active_handles = vec![];
1159
1160 for mut discover_handle in self.discover_handles.drain(..) {
1161 if !discover_handle.handle.has_exited() {
1162 active_handles.push(discover_handle);
1163 }
1164 }
1165 self.discover_handles = active_handles;
1166 }
1167
1168 fn handle_cargo_test_msg(&mut self, message: CargoTestMessage) {
1169 match message.output {
1170 CargoTestOutput::Test { name, state } => {
1171 let state = match state {
1172 TestState::Started => lsp_ext::TestState::Started,
1173 TestState::Ignored => lsp_ext::TestState::Skipped,
1174 TestState::Ok => lsp_ext::TestState::Passed,
1175 TestState::Failed { stdout } => lsp_ext::TestState::Failed { message: stdout },
1176 };
1177
1178 let test_id = format!("{}::{name}", message.target.target.replace('-', "_"));
1180
1181 self.send_notification::<lsp_ext::ChangeTestStateNotification>(
1182 lsp_ext::ChangeTestStateParams { test_id, state },
1183 );
1184 }
1185 CargoTestOutput::Suite => (),
1186 CargoTestOutput::Finished => {
1187 self.test_run_remaining_jobs = self.test_run_remaining_jobs.saturating_sub(1);
1188 if self.test_run_remaining_jobs == 0 {
1189 self.send_notification::<lsp_ext::EndRunTestNotification>(());
1190 self.test_run_session = None;
1191 }
1192 }
1193 CargoTestOutput::Custom { text } => {
1194 self.send_notification::<lsp_ext::AppendOutputToRunTestNotification>(text);
1195 }
1196 }
1197 }
1198
1199 fn handle_flycheck_msg(&mut self, message: FlycheckMessage, cargo_finished: &mut bool) {
1200 match message {
1201 FlycheckMessage::AddDiagnostic {
1202 id,
1203 generation,
1204 workspace_root,
1205 diagnostic,
1206 package_id,
1207 } => {
1208 let snap = self.snapshot();
1209 let diagnostics = crate::diagnostics::flycheck_to_proto::map_rust_diagnostic_to_lsp(
1210 &self.config.diagnostics_map(None),
1211 diagnostic,
1212 &workspace_root,
1213 &snap,
1214 );
1215 for diag in diagnostics {
1216 match url_to_file_id(&self.vfs.read().0, &diag.url) {
1217 Ok(Some(file_id)) => self.diagnostics.add_check_diagnostic(
1218 id,
1219 generation,
1220 &package_id,
1221 file_id,
1222 diag.diagnostic,
1223 diag.fix,
1224 ),
1225 Ok(None) => {}
1226 Err(err) => {
1227 error!(
1228 "flycheck {id}: File with cargo diagnostic not found in VFS: {}",
1229 err
1230 );
1231 }
1232 };
1233 }
1234 }
1235 FlycheckMessage::ClearDiagnostics {
1236 id,
1237 kind: ClearDiagnosticsKind::All(ClearScope::Workspace),
1238 } => self.diagnostics.clear_check(id),
1239 FlycheckMessage::ClearDiagnostics {
1240 id,
1241 kind: ClearDiagnosticsKind::All(ClearScope::Package(package_id)),
1242 } => self.diagnostics.clear_check_for_package(id, package_id),
1243 FlycheckMessage::ClearDiagnostics {
1244 id,
1245 kind: ClearDiagnosticsKind::OlderThan(generation, ClearScope::Workspace),
1246 } => self.diagnostics.clear_check_older_than(id, generation),
1247 FlycheckMessage::ClearDiagnostics {
1248 id,
1249 kind: ClearDiagnosticsKind::OlderThan(generation, ClearScope::Package(package_id)),
1250 } => self.diagnostics.clear_check_older_than_for_package(id, package_id, generation),
1251 FlycheckMessage::Progress { id, progress } => {
1252 let format_with_id = |user_facing_command: String| {
1253 if self.flycheck.len() == 1 {
1256 user_facing_command
1257 } else {
1258 format!("{user_facing_command} (#{})", id + 1)
1259 }
1260 };
1261
1262 self.flycheck_formatted_commands
1263 .resize_with(self.flycheck.len().max(id + 1), || {
1264 format_with_id(self.config.flycheck(None).to_string())
1265 });
1266
1267 let (state, message) = match progress {
1268 flycheck::Progress::DidStart { user_facing_command } => {
1269 self.flycheck_formatted_commands[id] = format_with_id(user_facing_command);
1270 (Progress::Begin, None)
1271 }
1272 flycheck::Progress::DidCheckCrate(target) => (Progress::Report, Some(target)),
1273 flycheck::Progress::DidCancel => {
1274 self.last_flycheck_error = None;
1275 *cargo_finished = true;
1276 (Progress::End, None)
1277 }
1278 flycheck::Progress::DidFailToRestart(err) => {
1279 self.last_flycheck_error =
1280 Some(format!("cargo check failed to start: {err}"));
1281 return;
1282 }
1283 flycheck::Progress::DidFinish(result) => {
1284 self.last_flycheck_error =
1285 result.err().map(|err| format!("cargo check failed to start: {err}"));
1286 *cargo_finished = true;
1287 (Progress::End, None)
1288 }
1289 };
1290
1291 let title = self.flycheck_formatted_commands[id].clone();
1293 self.report_progress(
1294 &title,
1295 state,
1296 message,
1297 None,
1298 Some(format!("rust-analyzer/flycheck/{id}")),
1299 );
1300 }
1301 }
1302 }
1303
1304 fn on_new_request(&mut self, request_received: Instant, req: Request) {
1306 let _p =
1307 span!(Level::INFO, "GlobalState::on_new_request", req.method = ?req.method).entered();
1308 self.register_request(&req, request_received);
1309 self.on_request(req);
1310 }
1311
1312 fn on_request(&mut self, req: Request) {
1314 let mut dispatcher = RequestDispatcher { req: Some(req), global_state: self };
1315 dispatcher.on_sync_mut::<lsp_types::ShutdownRequest>(|s, ()| {
1316 s.shutdown_requested = true;
1317 s.proc_macro_clients =
1318 std::iter::repeat_with(|| None).take(s.proc_macro_clients.len()).collect();
1319 s.flycheck.iter().for_each(|handle| handle.cancel());
1320 s.discover_handles.clear();
1321 Ok(())
1322 });
1323
1324 match &mut dispatcher {
1325 RequestDispatcher { req: Some(req), global_state: this } if this.shutdown_requested => {
1326 this.respond(lsp_server::Response::new_err(
1327 req.id.clone(),
1328 lsp_server::ErrorCode::InvalidRequest as i32,
1329 "Shutdown already requested.".to_owned(),
1330 ));
1331 return;
1332 }
1333 _ => (),
1334 }
1335
1336 use crate::handlers::request as handlers;
1337
1338 const RETRY: bool = true;
1339 const NO_RETRY: bool = false;
1340
1341 #[rustfmt::skip]
1342 dispatcher
1343 .on_sync_mut::<lsp_ext::ReloadWorkspaceRequest>(handlers::handle_workspace_reload)
1346 .on_sync_mut::<lsp_ext::RebuildProcMacrosRequest>(handlers::handle_proc_macros_rebuild)
1347 .on_sync_mut::<lsp_ext::MemoryUsageRequest>(handlers::handle_memory_usage)
1348 .on_sync_mut::<lsp_ext::RunTestRequest>(handlers::handle_run_test)
1349 .on_sync::<lsp_ext::JoinLinesRequest>(handlers::handle_join_lines)
1352 .on_sync::<lsp_ext::OnEnterRequest>(handlers::handle_on_enter)
1353 .on_sync::<lsp_types::SelectionRangeRequest>(handlers::handle_selection_range)
1354 .on_sync::<lsp_ext::MatchingBraceRequest>(handlers::handle_matching_brace)
1355 .on_sync::<lsp_ext::DocumentOnTypeFormattingRequest>(handlers::handle_on_type_formatting)
1356 .on_fmt_thread::<lsp_types::DocumentFormattingRequest>(handlers::handle_formatting)
1361 .on_fmt_thread::<lsp_types::DocumentRangeFormattingRequest>(handlers::handle_range_formatting)
1362 .on_latency_sensitive::<RETRY, lsp_types::CompletionRequest>(handlers::handle_completion)
1368 .on_latency_sensitive::<RETRY, lsp_types::CompletionResolveRequest>(handlers::handle_completion_resolve)
1370 .on_latency_sensitive::<RETRY, lsp_types::SemanticTokensRequest>(handlers::handle_semantic_tokens_full)
1371 .on_latency_sensitive::<RETRY, lsp_types::SemanticTokensDeltaRequest>(handlers::handle_semantic_tokens_full_delta)
1372 .on_latency_sensitive::<NO_RETRY, lsp_types::SemanticTokensRangeRequest>(handlers::handle_semantic_tokens_range)
1373 .on_with_vfs_default::<lsp_types::DocumentDiagnosticRequest>(handlers::handle_document_diagnostics, empty_diagnostic_report, || lsp_server::ResponseError {
1376 code: lsp_server::ErrorCode::ServerCancelled as i32,
1377 message: "server cancelled the request".to_owned(),
1378 data: serde_json::to_value(lsp_types::DiagnosticServerCancellationData {
1379 retrigger_request: true
1380 }).ok(),
1381 })
1382 .on::<RETRY, lsp_types::DocumentSymbolRequest>(handlers::handle_document_symbol)
1383 .on::<RETRY, lsp_types::FoldingRangeRequest>(handlers::handle_folding_range)
1384 .on::<NO_RETRY, lsp_types::SignatureHelpRequest>(handlers::handle_signature_help)
1385 .on::<RETRY, lsp_types::WillRenameFilesRequest>(handlers::handle_will_rename_files)
1386 .on::<NO_RETRY, lsp_types::DefinitionRequest>(handlers::handle_goto_definition)
1387 .on::<NO_RETRY, lsp_types::DeclarationRequest>(handlers::handle_goto_declaration)
1388 .on::<NO_RETRY, lsp_types::ImplementationRequest>(handlers::handle_goto_implementation)
1389 .on::<NO_RETRY, lsp_types::TypeDefinitionRequest>(handlers::handle_goto_type_definition)
1390 .on::<NO_RETRY, lsp_types::InlayHintRequest>(handlers::handle_inlay_hints)
1391 .on_identity::<NO_RETRY, lsp_types::InlayHintResolveRequest, _>(handlers::handle_inlay_hints_resolve)
1392 .on::<NO_RETRY, lsp_types::CodeLensRequest>(handlers::handle_code_lens)
1393 .on_identity::<NO_RETRY, lsp_types::CodeLensResolveRequest, _>(handlers::handle_code_lens_resolve)
1394 .on::<NO_RETRY, lsp_types::PrepareRenameRequest>(handlers::handle_prepare_rename)
1395 .on::<NO_RETRY, lsp_types::RenameRequest>(handlers::handle_rename)
1396 .on::<NO_RETRY, lsp_types::ReferencesRequest>(handlers::handle_references)
1397 .on::<NO_RETRY, lsp_types::DocumentHighlightRequest>(handlers::handle_document_highlight)
1398 .on::<NO_RETRY, lsp_types::CallHierarchyPrepareRequest>(handlers::handle_call_hierarchy_prepare)
1399 .on::<NO_RETRY, lsp_types::CallHierarchyIncomingCallsRequest>(handlers::handle_call_hierarchy_incoming)
1400 .on::<NO_RETRY, lsp_types::CallHierarchyOutgoingCallsRequest>(handlers::handle_call_hierarchy_outgoing)
1401 .on::<RETRY, lsp_ext::FetchDependencyListRequest>(handlers::fetch_dependency_list)
1403 .on::<RETRY, lsp_ext::AnalyzerStatusRequest>(handlers::handle_analyzer_status)
1404 .on::<RETRY, lsp_ext::ViewFileTextRequest>(handlers::handle_view_file_text)
1405 .on::<RETRY, lsp_ext::ViewCrateGraphRequest>(handlers::handle_view_crate_graph)
1406 .on::<RETRY, lsp_ext::ViewItemTreeRequest>(handlers::handle_view_item_tree)
1407 .on::<RETRY, lsp_ext::DiscoverTestRequest>(handlers::handle_discover_test)
1408 .on::<RETRY, lsp_ext::WorkspaceSymbolRequest>(handlers::handle_workspace_symbol)
1409 .on::<NO_RETRY, lsp_ext::SsrRequest>(handlers::handle_ssr)
1410 .on::<NO_RETRY, lsp_ext::ViewRecursiveMemoryLayoutRequest>(handlers::handle_view_recursive_memory_layout)
1411 .on::<NO_RETRY, lsp_ext::ViewSyntaxTreeRequest>(handlers::handle_view_syntax_tree)
1412 .on::<NO_RETRY, lsp_ext::ViewHirRequest>(handlers::handle_view_hir)
1413 .on::<NO_RETRY, lsp_ext::ViewMirRequest>(handlers::handle_view_mir)
1414 .on::<NO_RETRY, lsp_ext::InterpretFunctionRequest>(handlers::handle_interpret_function)
1415 .on::<NO_RETRY, lsp_ext::ExpandMacroRequest>(handlers::handle_expand_macro)
1416 .on::<NO_RETRY, lsp_ext::ParentModuleRequest>(handlers::handle_parent_module)
1417 .on::<NO_RETRY, lsp_ext::ChildModulesRequest>(handlers::handle_child_modules)
1418 .on::<NO_RETRY, lsp_ext::RunnablesRequest>(handlers::handle_runnables)
1419 .on::<NO_RETRY, lsp_ext::RelatedTestsRequest>(handlers::handle_related_tests)
1420 .on::<NO_RETRY, lsp_ext::CodeActionRequest>(handlers::handle_code_action)
1421 .on_identity::<RETRY, lsp_ext::CodeActionResolveRequest, _>(handlers::handle_code_action_resolve)
1422 .on::<NO_RETRY, lsp_ext::HoverRequest>(handlers::handle_hover)
1423 .on::<NO_RETRY, lsp_ext::ExternalDocsRequest>(handlers::handle_open_docs)
1424 .on::<NO_RETRY, lsp_ext::OpenCargoTomlRequest>(handlers::handle_open_cargo_toml)
1425 .on::<NO_RETRY, lsp_ext::MoveItemRequest>(handlers::handle_move_item)
1426 .on::<NO_RETRY, lsp_ext::InternalTestingFetchConfigRequest>(handlers::internal_testing_fetch_config)
1428 .on::<RETRY, lsp_ext::EvaluatePredicateRequest>(handlers::handle_evaluate_predicate)
1429 .on::<RETRY, lsp_ext::GetFailedObligationsRequest>(handlers::get_failed_obligations)
1430 .finish();
1431 }
1432
1433 fn on_notification(&mut self, not: Notification) {
1435 let _p =
1436 span!(Level::INFO, "GlobalState::on_notification", not.method = ?not.method).entered();
1437 use crate::handlers::notification as handlers;
1438
1439 NotificationDispatcher { not: Some(not), global_state: self }
1440 .on_sync_mut::<lsp_types::CancelNotification>(handlers::handle_cancel)
1441 .on_sync_mut::<lsp_types::WorkDoneProgressCancelNotification>(
1442 handlers::handle_work_done_progress_cancel,
1443 )
1444 .on_sync_mut::<lsp_types::DidOpenTextDocumentNotification>(
1445 handlers::handle_did_open_text_document,
1446 )
1447 .on_sync_mut::<lsp_types::DidChangeTextDocumentNotification>(
1448 handlers::handle_did_change_text_document,
1449 )
1450 .on_sync_mut::<lsp_types::DidCloseTextDocumentNotification>(
1451 handlers::handle_did_close_text_document,
1452 )
1453 .on_sync_mut::<lsp_types::DidSaveTextDocumentNotification>(
1454 handlers::handle_did_save_text_document,
1455 )
1456 .on_sync_mut::<lsp_types::DidChangeConfigurationNotification>(
1457 handlers::handle_did_change_configuration,
1458 )
1459 .on_sync_mut::<lsp_types::DidChangeWorkspaceFoldersNotification>(
1460 handlers::handle_did_change_workspace_folders,
1461 )
1462 .on_sync_mut::<lsp_types::DidChangeWatchedFilesNotification>(
1463 handlers::handle_did_change_watched_files,
1464 )
1465 .on_sync_mut::<lsp_ext::CancelFlycheckNotification>(handlers::handle_cancel_flycheck)
1466 .on_sync_mut::<lsp_ext::ClearFlycheckNotification>(handlers::handle_clear_flycheck)
1467 .on_sync_mut::<lsp_ext::RunFlycheckNotification>(handlers::handle_run_flycheck)
1468 .on_sync_mut::<lsp_ext::AbortRunTestNotification>(handlers::handle_abort_run_test)
1469 .finish();
1470 }
1471}