Skip to content

Commit 491f69a

Browse files
committed
internal: make project loading lazy
1 parent 3723e59 commit 491f69a

File tree

5 files changed

+46
-47
lines changed

5 files changed

+46
-47
lines changed

crates/rust-analyzer/src/bin/main.rs

-7
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,6 @@ fn run_server() -> anyhow::Result<()> {
268268
return Err(e.into());
269269
}
270270

271-
if config.discover_workspace_config().is_none()
272-
&& !config.has_linked_projects()
273-
&& config.detached_files().is_empty()
274-
{
275-
config.rediscover_workspaces();
276-
}
277-
278271
// If the io_threads have an error, there's usually an error on the main
279272
// loop too because the channels are closed. Ensure we report both errors.
280273
match (rust_analyzer::main_loop(config, connection), io_threads.join()) {

crates/rust-analyzer/src/discover.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ pub(crate) const ARG_PLACEHOLDER: &str = "{arg}";
1515
/// A command wrapper for getting a `rust-project.json`.
1616
///
1717
/// This is analogous to discovering a cargo project + running `cargo-metadata` on it, but for non-Cargo build systems.
18-
pub(crate) struct DiscoverCommand {
18+
#[derive(Debug, Clone)]
19+
pub(crate) struct DiscoverProjectJson {
1920
command: Vec<String>,
2021
sender: Sender<DiscoverProjectMessage>,
2122
}
@@ -27,15 +28,7 @@ pub(crate) enum DiscoverArgument {
2728
Buildfile(#[serde(serialize_with = "serialize_abs_pathbuf")] AbsPathBuf),
2829
}
2930

30-
fn serialize_abs_pathbuf<S>(path: &AbsPathBuf, se: S) -> Result<S::Ok, S::Error>
31-
where
32-
S: serde::Serializer,
33-
{
34-
let path: &Utf8Path = path.as_ref();
35-
se.serialize_str(path.as_str())
36-
}
37-
38-
impl DiscoverCommand {
31+
impl DiscoverProjectJson {
3932
/// Create a new [DiscoverCommand].
4033
pub(crate) fn new(sender: Sender<DiscoverProjectMessage>, command: Vec<String>) -> Self {
4134
Self { sender, command }
@@ -126,6 +119,14 @@ impl ParseFromLine for DiscoverProjectMessage {
126119
}
127120
}
128121

122+
fn serialize_abs_pathbuf<S>(path: &AbsPathBuf, se: S) -> Result<S::Ok, S::Error>
123+
where
124+
S: serde::Serializer,
125+
{
126+
let path: &Utf8Path = path.as_ref();
127+
se.serialize_str(path.as_str())
128+
}
129+
129130
#[test]
130131
fn test_deserialization() {
131132
let message = r#"

crates/rust-analyzer/src/handlers/notification.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,11 @@ pub(crate) fn handle_did_open_text_document(
7474

7575
tracing::info!("New file content set {:?}", params.text_document.text);
7676
state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
77-
if state.config.discover_workspace_config().is_some() {
78-
tracing::debug!("queuing task");
79-
let _ = state
80-
.deferred_task_queue
81-
.sender
82-
.send(crate::main_loop::QueuedTask::CheckIfIndexed(params.text_document.uri));
83-
}
77+
tracing::debug!("queuing task");
78+
let _ = state
79+
.deferred_task_queue
80+
.sender
81+
.send(crate::main_loop::QueuedTask::CheckIfIndexed(params.text_document.uri));
8482
}
8583
Ok(())
8684
}

crates/rust-analyzer/src/lsp/ext.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ impl Notification for ServerStatusNotification {
515515
const METHOD: &'static str = "experimental/serverStatus";
516516
}
517517

518-
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone)]
518+
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone, Debug)]
519519
#[serde(rename_all = "camelCase")]
520520
pub struct ServerStatusParams {
521521
pub health: Health,

crates/rust-analyzer/src/main_loop.rs

+29-22
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ use lsp_server::{Connection, Notification, Request};
1414
use lsp_types::{notification::Notification as _, TextDocumentIdentifier};
1515
use stdx::thread::ThreadIntent;
1616
use tracing::{error, span, Level};
17+
use triomphe::Arc;
1718
use vfs::{loader::LoadingProgress, AbsPathBuf, FileId};
1819

1920
use crate::{
2021
config::Config,
2122
diagnostics::{fetch_native_diagnostics, DiagnosticsGeneration, NativeDiagnosticsFetchKind},
22-
discover::{DiscoverArgument, DiscoverCommand, DiscoverProjectMessage},
23+
discover::{DiscoverArgument, DiscoverProjectJson, DiscoverProjectMessage},
2324
flycheck::{self, FlycheckMessage},
2425
global_state::{file_id_to_url, url_to_file_id, FetchWorkspaceRequest, GlobalState},
2526
hack_recover_crate_name,
@@ -113,6 +114,7 @@ pub(crate) enum Task {
113114
pub(crate) enum DiscoverProjectParam {
114115
Buildfile(AbsPathBuf),
115116
Path(AbsPathBuf),
117+
ClassicOnDisk,
116118
}
117119

118120
#[derive(Debug)]
@@ -159,8 +161,6 @@ impl fmt::Debug for Event {
159161

160162
impl GlobalState {
161163
fn run(mut self, inbox: Receiver<lsp_server::Message>) -> anyhow::Result<()> {
162-
self.update_status_or_notify();
163-
164164
if self.config.did_save_text_document_dynamic_registration() {
165165
let additional_patterns = self
166166
.config
@@ -172,17 +172,7 @@ impl GlobalState {
172172
self.register_did_save_capability(additional_patterns);
173173
}
174174

175-
if self.config.discover_workspace_config().is_none() {
176-
self.fetch_workspaces_queue.request_op(
177-
"startup".to_owned(),
178-
FetchWorkspaceRequest { path: None, force_crate_graph_reload: false },
179-
);
180-
if let Some((cause, FetchWorkspaceRequest { path, force_crate_graph_reload })) =
181-
self.fetch_workspaces_queue.should_start_op()
182-
{
183-
self.fetch_workspaces(cause, path, force_crate_graph_reload);
184-
}
185-
}
175+
self.discover_workspace_queue.request_op("startup".to_owned(), ());
186176

187177
while let Ok(event) = self.next_event(&inbox) {
188178
let Some(event) = event else {
@@ -699,13 +689,14 @@ impl GlobalState {
699689
self.report_progress("Fetching", state, msg, None, None);
700690
}
701691
Task::DiscoverLinkedProjects(arg) => {
702-
if let Some(cfg) = self.config.discover_workspace_config() {
703-
if !self.discover_workspace_queue.op_in_progress() {
692+
if !self.discover_workspace_queue.op_in_progress() {
693+
if let Some(cfg) = self.config.discover_workspace_config() {
704694
// the clone is unfortunately necessary to avoid a borrowck error when
705695
// `self.report_progress` is called later
706696
let title = &cfg.progress_label.clone();
707697
let command = cfg.command.clone();
708-
let discover = DiscoverCommand::new(self.discover_sender.clone(), command);
698+
let discover =
699+
DiscoverProjectJson::new(self.discover_sender.clone(), command);
709700

710701
self.report_progress(title, Progress::Begin, None, None, None);
711702
self.discover_workspace_queue
@@ -715,10 +706,19 @@ impl GlobalState {
715706
let arg = match arg {
716707
DiscoverProjectParam::Buildfile(it) => DiscoverArgument::Buildfile(it),
717708
DiscoverProjectParam::Path(it) => DiscoverArgument::Path(it),
709+
_ => return, // this is a bug; the arg should not be sent if `discover_workspace_config` is set
718710
};
719711

720712
let handle = discover.spawn(arg).unwrap();
721713
self.discover_handle = Some(handle);
714+
} else {
715+
let config = Arc::make_mut(&mut self.config);
716+
config.rediscover_workspaces();
717+
718+
let req =
719+
FetchWorkspaceRequest { path: None, force_crate_graph_reload: false };
720+
self.fetch_workspaces_queue
721+
.request_op("workspaces have been discovered".to_owned(), req);
722722
}
723723
}
724724
}
@@ -829,11 +829,18 @@ impl GlobalState {
829829
let id = from_proto::file_id(&snap, &uri).expect("unable to get FileId");
830830
if let Ok(crates) = &snap.analysis.crates_for(id) {
831831
if crates.is_empty() {
832-
if snap.config.discover_workspace_config().is_some() {
833-
let path =
834-
from_proto::abs_path(&uri).expect("Unable to get AbsPath");
835-
let arg = DiscoverProjectParam::Path(path);
836-
sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
832+
match snap.config.discover_workspace_config() {
833+
Some(_) => {
834+
let path =
835+
from_proto::abs_path(&uri).expect("Unable to get AbsPath");
836+
let arg = DiscoverProjectParam::Path(path);
837+
sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
838+
}
839+
// default behavior; do standard discovery
840+
None => {
841+
let arg = DiscoverProjectParam::ClassicOnDisk;
842+
sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
843+
}
837844
}
838845
} else {
839846
tracing::debug!(?uri, "is indexed");

0 commit comments

Comments
 (0)