Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 6a42d7f

Browse files
committed
fix: allow new, subsequent rust-project.json-based workspaces to get
proc macro expansion.
1 parent e7337fc commit 6a42d7f

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

crates/project-model/src/workspace.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,14 @@ impl ProjectWorkspace {
672672
_ => false,
673673
}
674674
}
675+
676+
/// Returns `true` if the project workspace is [`Json`].
677+
///
678+
/// [`Json`]: ProjectWorkspace::Json
679+
#[must_use]
680+
pub fn is_json(&self) -> bool {
681+
matches!(self, Self::Json { .. })
682+
}
675683
}
676684

677685
fn project_json_to_crate_graph(

crates/rust-analyzer/src/reload.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,25 @@ impl GlobalState {
296296
let workspaces =
297297
workspaces.iter().filter_map(|res| res.as_ref().ok().cloned()).collect::<Vec<_>>();
298298

299-
let same_workspaces = workspaces.len() == self.workspaces.len()
300-
&& workspaces
301-
.iter()
302-
.zip(self.workspaces.iter())
303-
.all(|(l, r)| l.eq_ignore_build_data(r));
299+
// `different_workspaces` is used to spawn a new proc macro server for a newly-added
300+
// rust workspace (most commonly sourced from a `rust-project.json`). While the algorithm
301+
// to find the new workspaces is quadratic, we generally expect that the number of total
302+
// workspaces to remain in the low single digits. the `cloned_workspace` is needed for borrowck
303+
// reasons.
304+
let cloned_workspaces = workspaces.clone();
305+
let different_workspaces = cloned_workspaces
306+
.iter()
307+
.filter(|ws| {
308+
!self
309+
.workspaces
310+
.iter()
311+
.find(|existing_ws| ws.eq_ignore_build_data(&existing_ws))
312+
.is_some()
313+
})
314+
.collect::<Vec<_>>();
315+
let same_workspaces = different_workspaces.is_empty();
316+
317+
tracing::debug!(current_workspaces = ?self.workspaces, new_workspaces = ?workspaces, ?same_workspaces, "comparing workspaces");
304318

305319
if same_workspaces {
306320
let (workspaces, build_scripts) = self.fetch_build_data_queue.last_op_result();
@@ -370,11 +384,10 @@ impl GlobalState {
370384
let files_config = self.config.files();
371385
let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
372386

373-
if self.proc_macro_clients.is_empty() {
387+
if self.proc_macro_clients.is_empty() || !different_workspaces.is_empty() {
374388
if let Some((path, path_manually_set)) = self.config.proc_macro_srv() {
375389
tracing::info!("Spawning proc-macro servers");
376-
self.proc_macro_clients = self
377-
.workspaces
390+
self.proc_macro_clients = different_workspaces
378391
.iter()
379392
.map(|ws| {
380393
let (path, args): (_, &[_]) = if path_manually_set {
@@ -448,7 +461,19 @@ impl GlobalState {
448461
};
449462
let mut change = Change::new();
450463

451-
if same_workspaces {
464+
// `self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths)` is only called in
465+
// when `switch_workspaces` is called _without_ changing workspaces. This typically occurs
466+
// when build scripts have finishing building, but when rust-analyzer is used with a
467+
// rust-project.json, the build scripts have already been built by the external build system
468+
// that generated the `rust-project.json`.
469+
470+
// Therefore, in order to allow _new_ workspaces added via rust-project.json (e.g., after
471+
// a workspace was already added), we check whether this is the same workspace _or_
472+
// if any of the new workspaces is a `rust-project.json`.
473+
//
474+
// The else branch is used to provide better diagnostics to users while procedural macros
475+
// are still being built.
476+
if same_workspaces || different_workspaces.iter().any(|ws| ws.is_json()) {
452477
if self.config.expand_proc_macros() {
453478
self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths);
454479
}

0 commit comments

Comments
 (0)