diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index c128e608d8..351997dcdb 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -54,11 +54,13 @@ struct TargetData { name: String, root: PathBuf, kind: TargetKind, + is_proc_macro: bool, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TargetKind { Bin, + /// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...). Lib, Example, Test, @@ -74,6 +76,7 @@ impl TargetKind { "test" => TargetKind::Test, "bench" => TargetKind::Bench, "example" => TargetKind::Example, + "proc-macro" => TargetKind::Lib, _ if kind.contains("lib") => TargetKind::Lib, _ => continue, }; @@ -123,6 +126,9 @@ impl Target { pub fn kind(self, ws: &CargoWorkspace) -> TargetKind { ws.targets[self].kind } + pub fn is_proc_macro(self, ws: &CargoWorkspace) -> bool { + ws.targets[self].is_proc_macro + } } impl CargoWorkspace { @@ -155,11 +161,13 @@ impl CargoWorkspace { let pkg_data = &mut packages[pkg]; pkg_by_id.insert(id, pkg); for meta_tgt in meta_pkg.targets { + let is_proc_macro = meta_tgt.kind.as_slice() == &["proc-macro"]; let tgt = targets.alloc(TargetData { pkg, name: meta_tgt.name, root: meta_tgt.src_path.clone(), kind: TargetKind::new(meta_tgt.kind.as_slice()), + is_proc_macro, }); pkg_data.targets.push(tgt); } diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 638ca2f8b9..55ff4d6efc 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -211,6 +211,8 @@ impl ProjectWorkspace { let libcore = sysroot.core().and_then(|it| sysroot_crates.get(&it).copied()); let liballoc = sysroot.alloc().and_then(|it| sysroot_crates.get(&it).copied()); let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied()); + let libproc_macro = + sysroot.proc_macro().and_then(|it| sysroot_crates.get(&it).copied()); let mut pkg_to_lib_crate = FxHashMap::default(); let mut pkg_crates = FxHashMap::default(); @@ -237,6 +239,21 @@ impl ProjectWorkspace { lib_tgt = Some(crate_id); pkg_to_lib_crate.insert(pkg, crate_id); } + if tgt.is_proc_macro(&cargo) { + if let Some(proc_macro) = libproc_macro { + if let Err(_) = crate_graph.add_dep( + crate_id, + "proc_macro".into(), + proc_macro, + ) { + log::error!( + "cyclic dependency on proc_macro for {}", + pkg.name(&cargo) + ) + } + } + } + pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); } } diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index bec9439d73..10ca391b6a 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs @@ -39,6 +39,10 @@ impl Sysroot { self.by_name("std") } + pub fn proc_macro(&self) -> Option { + self.by_name("proc_macro") + } + pub fn crates<'a>(&'a self) -> impl Iterator + ExactSizeIterator + 'a { self.crates.iter().map(|(id, _data)| id) } @@ -74,7 +78,7 @@ impl Sysroot { } } if let Some(alloc) = sysroot.by_name("alloc") { - if let Some(core) = sysroot.by_name("core") { + if let Some(core) = sysroot.core() { sysroot.crates[alloc].deps.push(core); } }