fix: allow new, subsequent rust-project.json
-based workspaces to get
proc macro expansion.
This commit is contained in:
parent
e7337fc9c3
commit
6a42d7f627
@ -672,6 +672,14 @@ impl ProjectWorkspace {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the project workspace is [`Json`].
|
||||
///
|
||||
/// [`Json`]: ProjectWorkspace::Json
|
||||
#[must_use]
|
||||
pub fn is_json(&self) -> bool {
|
||||
matches!(self, Self::Json { .. })
|
||||
}
|
||||
}
|
||||
|
||||
fn project_json_to_crate_graph(
|
||||
|
@ -296,11 +296,25 @@ impl GlobalState {
|
||||
let workspaces =
|
||||
workspaces.iter().filter_map(|res| res.as_ref().ok().cloned()).collect::<Vec<_>>();
|
||||
|
||||
let same_workspaces = workspaces.len() == self.workspaces.len()
|
||||
&& workspaces
|
||||
// `different_workspaces` is used to spawn a new proc macro server for a newly-added
|
||||
// rust workspace (most commonly sourced from a `rust-project.json`). While the algorithm
|
||||
// to find the new workspaces is quadratic, we generally expect that the number of total
|
||||
// workspaces to remain in the low single digits. the `cloned_workspace` is needed for borrowck
|
||||
// reasons.
|
||||
let cloned_workspaces = workspaces.clone();
|
||||
let different_workspaces = cloned_workspaces
|
||||
.iter()
|
||||
.zip(self.workspaces.iter())
|
||||
.all(|(l, r)| l.eq_ignore_build_data(r));
|
||||
.filter(|ws| {
|
||||
!self
|
||||
.workspaces
|
||||
.iter()
|
||||
.find(|existing_ws| ws.eq_ignore_build_data(&existing_ws))
|
||||
.is_some()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let same_workspaces = different_workspaces.is_empty();
|
||||
|
||||
tracing::debug!(current_workspaces = ?self.workspaces, new_workspaces = ?workspaces, ?same_workspaces, "comparing workspaces");
|
||||
|
||||
if same_workspaces {
|
||||
let (workspaces, build_scripts) = self.fetch_build_data_queue.last_op_result();
|
||||
@ -370,11 +384,10 @@ impl GlobalState {
|
||||
let files_config = self.config.files();
|
||||
let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
|
||||
|
||||
if self.proc_macro_clients.is_empty() {
|
||||
if self.proc_macro_clients.is_empty() || !different_workspaces.is_empty() {
|
||||
if let Some((path, path_manually_set)) = self.config.proc_macro_srv() {
|
||||
tracing::info!("Spawning proc-macro servers");
|
||||
self.proc_macro_clients = self
|
||||
.workspaces
|
||||
self.proc_macro_clients = different_workspaces
|
||||
.iter()
|
||||
.map(|ws| {
|
||||
let (path, args): (_, &[_]) = if path_manually_set {
|
||||
@ -448,7 +461,19 @@ impl GlobalState {
|
||||
};
|
||||
let mut change = Change::new();
|
||||
|
||||
if same_workspaces {
|
||||
// `self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths)` is only called in
|
||||
// when `switch_workspaces` is called _without_ changing workspaces. This typically occurs
|
||||
// when build scripts have finishing building, but when rust-analyzer is used with a
|
||||
// rust-project.json, the build scripts have already been built by the external build system
|
||||
// that generated the `rust-project.json`.
|
||||
|
||||
// Therefore, in order to allow _new_ workspaces added via rust-project.json (e.g., after
|
||||
// a workspace was already added), we check whether this is the same workspace _or_
|
||||
// if any of the new workspaces is a `rust-project.json`.
|
||||
//
|
||||
// The else branch is used to provide better diagnostics to users while procedural macros
|
||||
// are still being built.
|
||||
if same_workspaces || different_workspaces.iter().any(|ws| ws.is_json()) {
|
||||
if self.config.expand_proc_macros() {
|
||||
self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user