Skip to content

Commit 3792720

Browse files
committed
Auto merge of rust-lang#12947 - Veykril:switch-workspace, r=Veykril
Don't switch workspace on vfs file changes from libraries When r-a starts up, it starts switching the workspace before all vfs events have been processed which causes us to switch workspace multiple times until all vfs changes have been processed. This scales with the size of the project and its dependencies. If workspace files from dependencies as well as the sysroot get loaded, we shouldn't switch the workspace as those have no impact on the project workspace.
2 parents 97038e5 + 6a17372 commit 3792720

File tree

3 files changed

+47
-36
lines changed

3 files changed

+47
-36
lines changed

crates/rust-analyzer/src/global_state.rs

+21-13
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{sync::Arc, time::Instant};
88
use crossbeam_channel::{unbounded, Receiver, Sender};
99
use flycheck::FlycheckHandle;
1010
use ide::{Analysis, AnalysisHost, Cancellable, Change, FileId};
11-
use ide_db::base_db::{CrateId, FileLoader, SourceDatabase};
11+
use ide_db::base_db::{CrateId, FileLoader, SourceDatabase, SourceDatabaseExt};
1212
use lsp_types::{SemanticTokens, Url};
1313
use parking_lot::{Mutex, RwLock};
1414
use proc_macro_api::ProcMacroServer;
@@ -176,7 +176,7 @@ impl GlobalState {
176176

177177
pub(crate) fn process_changes(&mut self) -> bool {
178178
let _p = profile::span("GlobalState::process_changes");
179-
let mut fs_changes = Vec::new();
179+
let mut fs_refresh_changes = Vec::new();
180180
// A file was added or deleted
181181
let mut has_structure_changes = false;
182182

@@ -192,11 +192,8 @@ impl GlobalState {
192192
if let Some(path) = vfs.file_path(file.file_id).as_path() {
193193
let path = path.to_path_buf();
194194
if reload::should_refresh_for_change(&path, file.change_kind) {
195-
tracing::warn!("fetch-fiel_change");
196-
self.fetch_workspaces_queue
197-
.request_op(format!("vfs file change: {}", path.display()));
195+
fs_refresh_changes.push((path, file.file_id));
198196
}
199-
fs_changes.push((path, file.change_kind));
200197
if file.is_created_or_deleted() {
201198
has_structure_changes = true;
202199
}
@@ -228,14 +225,25 @@ impl GlobalState {
228225

229226
self.analysis_host.apply_change(change);
230227

231-
let raw_database = &self.analysis_host.raw_database();
232-
self.proc_macro_changed =
233-
changed_files.iter().filter(|file| !file.is_created_or_deleted()).any(|file| {
234-
let crates = raw_database.relevant_crates(file.file_id);
235-
let crate_graph = raw_database.crate_graph();
228+
{
229+
let raw_database = self.analysis_host.raw_database();
230+
let workspace_structure_change =
231+
fs_refresh_changes.into_iter().find(|&(_, file_id)| {
232+
!raw_database.source_root(raw_database.file_source_root(file_id)).is_library
233+
});
234+
if let Some((path, _)) = workspace_structure_change {
235+
self.fetch_workspaces_queue
236+
.request_op(format!("workspace vfs file change: {}", path.display()));
237+
}
238+
self.proc_macro_changed =
239+
changed_files.iter().filter(|file| !file.is_created_or_deleted()).any(|file| {
240+
let crates = raw_database.relevant_crates(file.file_id);
241+
let crate_graph = raw_database.crate_graph();
242+
243+
crates.iter().any(|&krate| crate_graph[krate].is_proc_macro)
244+
});
245+
}
236246

237-
crates.iter().any(|&krate| crate_graph[krate].is_proc_macro)
238-
});
239247
true
240248
}
241249

crates/rust-analyzer/src/reload.rs

+20-22
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,7 @@ impl GlobalState {
196196
}
197197

198198
if let Err(error) = self.fetch_build_data_error() {
199-
self.show_and_log_error(
200-
"rust-analyzer failed to run build scripts".to_string(),
201-
Some(error),
202-
);
199+
self.show_and_log_error("failed to run build scripts".to_string(), Some(error));
203200
}
204201

205202
let workspaces = self
@@ -308,6 +305,7 @@ impl GlobalState {
308305

309306
if self.proc_macro_clients.is_empty() {
310307
if let Some((path, args)) = self.config.proc_macro_srv() {
308+
tracing::info!("Spawning proc-macro servers");
311309
self.proc_macro_clients = self
312310
.workspaces
313311
.iter()
@@ -316,35 +314,31 @@ impl GlobalState {
316314
let mut path = path.clone();
317315

318316
if let ProjectWorkspace::Cargo { sysroot, .. } = ws {
319-
tracing::info!("Found a cargo workspace...");
317+
tracing::debug!("Found a cargo workspace...");
320318
if let Some(sysroot) = sysroot.as_ref() {
321-
tracing::info!("Found a cargo workspace with a sysroot...");
319+
tracing::debug!("Found a cargo workspace with a sysroot...");
322320
let server_path =
323321
sysroot.root().join("libexec").join(&standalone_server_name);
324322
if std::fs::metadata(&server_path).is_ok() {
325-
tracing::info!(
323+
tracing::debug!(
326324
"And the server exists at {}",
327325
server_path.display()
328326
);
329327
path = server_path;
330328
args = vec![];
331329
} else {
332-
tracing::info!(
330+
tracing::debug!(
333331
"And the server does not exist at {}",
334332
server_path.display()
335333
);
336334
}
337335
}
338336
}
339337

340-
tracing::info!(
341-
"Using proc-macro server at {} with args {:?}",
342-
path.display(),
343-
args
344-
);
338+
tracing::info!(?args, "Using proc-macro server at {}", path.display(),);
345339
ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|err| {
346340
let error = format!(
347-
"Failed to run proc_macro_srv from path {}, error: {:?}",
341+
"Failed to run proc-macro server from path {}, error: {:?}",
348342
path.display(),
349343
err
350344
);
@@ -684,22 +678,26 @@ pub(crate) fn load_proc_macro(
684678
pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind) -> bool {
685679
const IMPLICIT_TARGET_FILES: &[&str] = &["build.rs", "src/main.rs", "src/lib.rs"];
686680
const IMPLICIT_TARGET_DIRS: &[&str] = &["src/bin", "examples", "tests", "benches"];
687-
let file_name = path.file_name().unwrap_or_default();
688681

689-
if file_name == "Cargo.toml" || file_name == "Cargo.lock" {
682+
let file_name = match path.file_name().unwrap_or_default().to_str() {
683+
Some(it) => it,
684+
None => return false,
685+
};
686+
687+
if let "Cargo.toml" | "Cargo.lock" = file_name {
690688
return true;
691689
}
692690
if change_kind == ChangeKind::Modify {
693691
return false;
694692
}
693+
694+
// .cargo/config{.toml}
695695
if path.extension().unwrap_or_default() != "rs" {
696-
if (file_name == "config.toml" || file_name == "config")
697-
&& path.parent().map(|parent| parent.as_ref().ends_with(".cargo")) == Some(true)
698-
{
699-
return true;
700-
}
701-
return false;
696+
let is_cargo_config = matches!(file_name, "config.toml" | "config")
697+
&& path.parent().map(|parent| parent.as_ref().ends_with(".cargo")).unwrap_or(false);
698+
return is_cargo_config;
702699
}
700+
703701
if IMPLICIT_TARGET_FILES.iter().any(|it| path.as_ref().ends_with(it)) {
704702
return true;
705703
}

crates/vfs-notify/src/lib.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,15 @@ impl loader::Handle for NotifyHandle {
4040
.expect("failed to spawn thread");
4141
NotifyHandle { sender, _thread: thread }
4242
}
43+
4344
fn set_config(&mut self, config: loader::Config) {
4445
self.sender.send(Message::Config(config)).unwrap();
4546
}
47+
4648
fn invalidate(&mut self, path: AbsPathBuf) {
4749
self.sender.send(Message::Invalidate(path)).unwrap();
4850
}
51+
4952
fn load_sync(&mut self, path: &AbsPath) -> Option<Vec<u8>> {
5053
read(path)
5154
}
@@ -70,16 +73,18 @@ impl NotifyActor {
7073
fn new(sender: loader::Sender) -> NotifyActor {
7174
NotifyActor { sender, watched_entries: Vec::new(), watcher: None }
7275
}
76+
7377
fn next_event(&self, receiver: &Receiver<Message>) -> Option<Event> {
7478
let watcher_receiver = self.watcher.as_ref().map(|(_, receiver)| receiver);
7579
select! {
7680
recv(receiver) -> it => it.ok().map(Event::Message),
7781
recv(watcher_receiver.unwrap_or(&never())) -> it => Some(Event::NotifyEvent(it.unwrap())),
7882
}
7983
}
84+
8085
fn run(mut self, inbox: Receiver<Message>) {
8186
while let Some(event) = self.next_event(&inbox) {
82-
tracing::debug!("vfs-notify event: {:?}", event);
87+
tracing::debug!(?event, "vfs-notify event");
8388
match event {
8489
Event::Message(msg) => match msg {
8590
Message::Config(config) => {

0 commit comments

Comments
 (0)