diff options
Diffstat (limited to 'crates/project_model')
-rw-r--r-- | crates/project_model/Cargo.toml | 10 | ||||
-rw-r--r-- | crates/project_model/src/build_data.rs | 23 | ||||
-rw-r--r-- | crates/project_model/src/cargo_workspace.rs | 32 | ||||
-rw-r--r-- | crates/project_model/src/workspace.rs | 138 |
4 files changed, 131 insertions, 72 deletions
diff --git a/crates/project_model/Cargo.toml b/crates/project_model/Cargo.toml index 293cb5bfe..fe3258332 100644 --- a/crates/project_model/Cargo.toml +++ b/crates/project_model/Cargo.toml | |||
@@ -12,7 +12,7 @@ doctest = false | |||
12 | [dependencies] | 12 | [dependencies] |
13 | log = "0.4.8" | 13 | log = "0.4.8" |
14 | rustc-hash = "1.1.0" | 14 | rustc-hash = "1.1.0" |
15 | cargo_metadata = "0.12.2" | 15 | cargo_metadata = "0.13" |
16 | serde = { version = "1.0.106", features = ["derive"] } | 16 | serde = { version = "1.0.106", features = ["derive"] } |
17 | serde_json = "1.0.48" | 17 | serde_json = "1.0.48" |
18 | anyhow = "1.0.26" | 18 | anyhow = "1.0.26" |
@@ -22,7 +22,7 @@ la-arena = { version = "0.2.0", path = "../../lib/arena" } | |||
22 | cfg = { path = "../cfg", version = "0.0.0" } | 22 | cfg = { path = "../cfg", version = "0.0.0" } |
23 | base_db = { path = "../base_db", version = "0.0.0" } | 23 | base_db = { path = "../base_db", version = "0.0.0" } |
24 | toolchain = { path = "../toolchain", version = "0.0.0" } | 24 | toolchain = { path = "../toolchain", version = "0.0.0" } |
25 | proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" } | 25 | proc_macro_api = { path = "../proc_macro_api", version = "0.0.0" } |
26 | paths = { path = "../paths", version = "0.0.0" } | 26 | paths = { path = "../paths", version = "0.0.0" } |
27 | stdx = { path = "../stdx", version = "0.0.0" } | 27 | stdx = { path = "../stdx", version = "0.0.0" } |
28 | profile = { path = "../profile", version = "0.0.0" } | 28 | profile = { path = "../profile", version = "0.0.0" } |
diff --git a/crates/project_model/src/build_data.rs b/crates/project_model/src/build_data.rs index 295b5f8ef..728a258ea 100644 --- a/crates/project_model/src/build_data.rs +++ b/crates/project_model/src/build_data.rs | |||
@@ -1,14 +1,14 @@ | |||
1 | //! Handles build script specific information | 1 | //! Handles build script specific information |
2 | 2 | ||
3 | use std::{ | 3 | use std::{ |
4 | ffi::OsStr, | ||
5 | io::BufReader, | 4 | io::BufReader, |
6 | path::{Path, PathBuf}, | 5 | path::PathBuf, |
7 | process::{Command, Stdio}, | 6 | process::{Command, Stdio}, |
8 | sync::Arc, | 7 | sync::Arc, |
9 | }; | 8 | }; |
10 | 9 | ||
11 | use anyhow::Result; | 10 | use anyhow::Result; |
11 | use cargo_metadata::camino::Utf8Path; | ||
12 | use cargo_metadata::{BuildScript, Message}; | 12 | use cargo_metadata::{BuildScript, Message}; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
14 | use paths::{AbsPath, AbsPathBuf}; | 14 | use paths::{AbsPath, AbsPathBuf}; |
@@ -162,8 +162,8 @@ fn collect_from_workspace( | |||
162 | let res = res.entry(package_id.repr.clone()).or_default(); | 162 | let res = res.entry(package_id.repr.clone()).or_default(); |
163 | // cargo_metadata crate returns default (empty) path for | 163 | // cargo_metadata crate returns default (empty) path for |
164 | // older cargos, which is not absolute, so work around that. | 164 | // older cargos, which is not absolute, so work around that. |
165 | if out_dir != PathBuf::default() { | 165 | if !out_dir.as_str().is_empty() { |
166 | let out_dir = AbsPathBuf::assert(out_dir); | 166 | let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir.into_os_string())); |
167 | res.out_dir = Some(out_dir); | 167 | res.out_dir = Some(out_dir); |
168 | res.cfgs = cfgs; | 168 | res.cfgs = cfgs; |
169 | } | 169 | } |
@@ -178,7 +178,7 @@ fn collect_from_workspace( | |||
178 | // Skip rmeta file | 178 | // Skip rmeta file |
179 | if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name)) | 179 | if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name)) |
180 | { | 180 | { |
181 | let filename = AbsPathBuf::assert(filename.clone()); | 181 | let filename = AbsPathBuf::assert(PathBuf::from(&filename)); |
182 | let res = res.entry(package_id.repr.clone()).or_default(); | 182 | let res = res.entry(package_id.repr.clone()).or_default(); |
183 | res.proc_macro_dylib_path = Some(filename); | 183 | res.proc_macro_dylib_path = Some(filename); |
184 | } | 184 | } |
@@ -187,9 +187,9 @@ fn collect_from_workspace( | |||
187 | Message::CompilerMessage(message) => { | 187 | Message::CompilerMessage(message) => { |
188 | progress(message.target.name.clone()); | 188 | progress(message.target.name.clone()); |
189 | } | 189 | } |
190 | Message::Unknown => (), | ||
191 | Message::BuildFinished(_) => {} | 190 | Message::BuildFinished(_) => {} |
192 | Message::TextLine(_) => {} | 191 | Message::TextLine(_) => {} |
192 | _ => {} | ||
193 | } | 193 | } |
194 | } | 194 | } |
195 | } | 195 | } |
@@ -209,8 +209,8 @@ fn collect_from_workspace( | |||
209 | } | 209 | } |
210 | 210 | ||
211 | // FIXME: File a better way to know if it is a dylib | 211 | // FIXME: File a better way to know if it is a dylib |
212 | fn is_dylib(path: &Path) -> bool { | 212 | fn is_dylib(path: &Utf8Path) -> bool { |
213 | match path.extension().and_then(OsStr::to_str).map(|it| it.to_string().to_lowercase()) { | 213 | match path.extension().map(|e| e.to_string().to_lowercase()) { |
214 | None => false, | 214 | None => false, |
215 | Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"), | 215 | Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"), |
216 | } | 216 | } |
@@ -227,9 +227,7 @@ fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut BuildDat | |||
227 | 227 | ||
228 | let mut manifest_dir = package.manifest_path.clone(); | 228 | let mut manifest_dir = package.manifest_path.clone(); |
229 | manifest_dir.pop(); | 229 | manifest_dir.pop(); |
230 | if let Some(cargo_manifest_dir) = manifest_dir.to_str() { | 230 | env.push(("CARGO_MANIFEST_DIR".into(), manifest_dir.into_string())); |
231 | env.push(("CARGO_MANIFEST_DIR".into(), cargo_manifest_dir.into())); | ||
232 | } | ||
233 | 231 | ||
234 | // Not always right, but works for common cases. | 232 | // Not always right, but works for common cases. |
235 | env.push(("CARGO".into(), "cargo".into())); | 233 | env.push(("CARGO".into(), "cargo".into())); |
@@ -251,7 +249,6 @@ fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut BuildDat | |||
251 | env.push(("CARGO_PKG_REPOSITORY".into(), package.repository.clone().unwrap_or_default())); | 249 | env.push(("CARGO_PKG_REPOSITORY".into(), package.repository.clone().unwrap_or_default())); |
252 | env.push(("CARGO_PKG_LICENSE".into(), package.license.clone().unwrap_or_default())); | 250 | env.push(("CARGO_PKG_LICENSE".into(), package.license.clone().unwrap_or_default())); |
253 | 251 | ||
254 | let license_file = | 252 | let license_file = package.license_file.as_ref().map(|buf| buf.to_string()).unwrap_or_default(); |
255 | package.license_file.as_ref().map(|buf| buf.display().to_string()).unwrap_or_default(); | ||
256 | env.push(("CARGO_PKG_LICENSE_FILE".into(), license_file)); | 253 | env.push(("CARGO_PKG_LICENSE_FILE".into(), license_file)); |
257 | } | 254 | } |
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index 1d8d34a0b..bc6e20341 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use std::path::PathBuf; | ||
3 | use std::{convert::TryInto, ops, process::Command, sync::Arc}; | 4 | use std::{convert::TryInto, ops, process::Command, sync::Arc}; |
4 | 5 | ||
5 | use anyhow::{Context, Result}; | 6 | use anyhow::{Context, Result}; |
@@ -8,6 +9,8 @@ use cargo_metadata::{CargoOpt, MetadataCommand}; | |||
8 | use la_arena::{Arena, Idx}; | 9 | use la_arena::{Arena, Idx}; |
9 | use paths::{AbsPath, AbsPathBuf}; | 10 | use paths::{AbsPath, AbsPathBuf}; |
10 | use rustc_hash::FxHashMap; | 11 | use rustc_hash::FxHashMap; |
12 | use serde::Deserialize; | ||
13 | use serde_json::from_value; | ||
11 | 14 | ||
12 | use crate::build_data::BuildDataConfig; | 15 | use crate::build_data::BuildDataConfig; |
13 | use crate::utf8_stdout; | 16 | use crate::utf8_stdout; |
@@ -103,6 +106,13 @@ pub struct PackageData { | |||
103 | pub active_features: Vec<String>, | 106 | pub active_features: Vec<String>, |
104 | // String representation of package id | 107 | // String representation of package id |
105 | pub id: String, | 108 | pub id: String, |
109 | // The contents of [package.metadata.rust-analyzer] | ||
110 | pub metadata: RustAnalyzerPackageMetaData, | ||
111 | } | ||
112 | |||
113 | #[derive(Deserialize, Default, Debug, Clone, Eq, PartialEq)] | ||
114 | pub struct RustAnalyzerPackageMetaData { | ||
115 | pub rustc_private: bool, | ||
106 | } | 116 | } |
107 | 117 | ||
108 | #[derive(Debug, Clone, Eq, PartialEq)] | 118 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -160,6 +170,13 @@ impl PackageData { | |||
160 | } | 170 | } |
161 | } | 171 | } |
162 | 172 | ||
173 | #[derive(Deserialize, Default)] | ||
174 | // Deserialise helper for the cargo metadata | ||
175 | struct PackageMetadata { | ||
176 | #[serde(rename = "rust-analyzer")] | ||
177 | rust_analyzer: Option<RustAnalyzerPackageMetaData>, | ||
178 | } | ||
179 | |||
163 | impl CargoWorkspace { | 180 | impl CargoWorkspace { |
164 | pub fn from_cargo_metadata( | 181 | pub fn from_cargo_metadata( |
165 | cargo_toml: &AbsPath, | 182 | cargo_toml: &AbsPath, |
@@ -243,23 +260,27 @@ impl CargoWorkspace { | |||
243 | 260 | ||
244 | meta.packages.sort_by(|a, b| a.id.cmp(&b.id)); | 261 | meta.packages.sort_by(|a, b| a.id.cmp(&b.id)); |
245 | for meta_pkg in &meta.packages { | 262 | for meta_pkg in &meta.packages { |
246 | let cargo_metadata::Package { id, edition, name, manifest_path, version, .. } = | 263 | let cargo_metadata::Package { |
247 | meta_pkg; | 264 | id, edition, name, manifest_path, version, metadata, .. |
265 | } = meta_pkg; | ||
266 | let meta = from_value::<PackageMetadata>(metadata.clone()).unwrap_or_default(); | ||
248 | let is_member = ws_members.contains(&id); | 267 | let is_member = ws_members.contains(&id); |
249 | let edition = edition | 268 | let edition = edition |
250 | .parse::<Edition>() | 269 | .parse::<Edition>() |
251 | .with_context(|| format!("Failed to parse edition {}", edition))?; | 270 | .with_context(|| format!("Failed to parse edition {}", edition))?; |
271 | |||
252 | let pkg = packages.alloc(PackageData { | 272 | let pkg = packages.alloc(PackageData { |
253 | id: id.repr.clone(), | 273 | id: id.repr.clone(), |
254 | name: name.clone(), | 274 | name: name.clone(), |
255 | version: version.to_string(), | 275 | version: version.to_string(), |
256 | manifest: AbsPathBuf::assert(manifest_path.clone()), | 276 | manifest: AbsPathBuf::assert(PathBuf::from(&manifest_path)), |
257 | targets: Vec::new(), | 277 | targets: Vec::new(), |
258 | is_member, | 278 | is_member, |
259 | edition, | 279 | edition, |
260 | dependencies: Vec::new(), | 280 | dependencies: Vec::new(), |
261 | features: meta_pkg.features.clone().into_iter().collect(), | 281 | features: meta_pkg.features.clone().into_iter().collect(), |
262 | active_features: Vec::new(), | 282 | active_features: Vec::new(), |
283 | metadata: meta.rust_analyzer.unwrap_or_default(), | ||
263 | }); | 284 | }); |
264 | let pkg_data = &mut packages[pkg]; | 285 | let pkg_data = &mut packages[pkg]; |
265 | pkg_by_id.insert(id, pkg); | 286 | pkg_by_id.insert(id, pkg); |
@@ -268,7 +289,7 @@ impl CargoWorkspace { | |||
268 | let tgt = targets.alloc(TargetData { | 289 | let tgt = targets.alloc(TargetData { |
269 | package: pkg, | 290 | package: pkg, |
270 | name: meta_tgt.name.clone(), | 291 | name: meta_tgt.name.clone(), |
271 | root: AbsPathBuf::assert(meta_tgt.src_path.clone()), | 292 | root: AbsPathBuf::assert(PathBuf::from(&meta_tgt.src_path)), |
272 | kind: TargetKind::new(meta_tgt.kind.as_slice()), | 293 | kind: TargetKind::new(meta_tgt.kind.as_slice()), |
273 | is_proc_macro, | 294 | is_proc_macro, |
274 | }); | 295 | }); |
@@ -305,7 +326,8 @@ impl CargoWorkspace { | |||
305 | packages[source].active_features.extend(node.features); | 326 | packages[source].active_features.extend(node.features); |
306 | } | 327 | } |
307 | 328 | ||
308 | let workspace_root = AbsPathBuf::assert(meta.workspace_root); | 329 | let workspace_root = |
330 | AbsPathBuf::assert(PathBuf::from(meta.workspace_root.into_os_string())); | ||
309 | let build_data_config = BuildDataConfig::new( | 331 | let build_data_config = BuildDataConfig::new( |
310 | cargo_toml.to_path_buf(), | 332 | cargo_toml.to_path_buf(), |
311 | config.clone(), | 333 | config.clone(), |
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 0220efdb4..1b53fcc30 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
@@ -2,11 +2,7 @@ | |||
2 | //! metadata` or `rust-project.json`) into representation stored in the salsa | 2 | //! metadata` or `rust-project.json`) into representation stored in the salsa |
3 | //! database -- `CrateGraph`. | 3 | //! database -- `CrateGraph`. |
4 | 4 | ||
5 | use std::{ | 5 | use std::{collections::VecDeque, fmt, fs, path::Path, process::Command}; |
6 | fmt, fs, | ||
7 | path::{Component, Path}, | ||
8 | process::Command, | ||
9 | }; | ||
10 | 6 | ||
11 | use anyhow::{Context, Result}; | 7 | use anyhow::{Context, Result}; |
12 | use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; | 8 | use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; |
@@ -60,6 +56,7 @@ impl fmt::Debug for ProjectWorkspace { | |||
60 | match self { | 56 | match self { |
61 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } => f | 57 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } => f |
62 | .debug_struct("Cargo") | 58 | .debug_struct("Cargo") |
59 | .field("root", &cargo.workspace_root().file_name()) | ||
63 | .field("n_packages", &cargo.packages().len()) | 60 | .field("n_packages", &cargo.packages().len()) |
64 | .field("n_sysroot_crates", &sysroot.crates().len()) | 61 | .field("n_sysroot_crates", &sysroot.crates().len()) |
65 | .field( | 62 | .field( |
@@ -279,11 +276,8 @@ impl ProjectWorkspace { | |||
279 | 276 | ||
280 | pub fn collect_build_data_configs(&self, collector: &mut BuildDataCollector) { | 277 | pub fn collect_build_data_configs(&self, collector: &mut BuildDataCollector) { |
281 | match self { | 278 | match self { |
282 | ProjectWorkspace::Cargo { cargo, rustc, .. } => { | 279 | ProjectWorkspace::Cargo { cargo, .. } => { |
283 | collector.add_config(&cargo.workspace_root(), cargo.build_data_config().clone()); | 280 | collector.add_config(&cargo.workspace_root(), cargo.build_data_config().clone()); |
284 | if let Some(rustc) = rustc { | ||
285 | collector.add_config(rustc.workspace_root(), rustc.build_data_config().clone()); | ||
286 | } | ||
287 | } | 281 | } |
288 | _ => {} | 282 | _ => {} |
289 | } | 283 | } |
@@ -380,9 +374,11 @@ fn cargo_to_crate_graph( | |||
380 | cfg_options.insert_atom("debug_assertions".into()); | 374 | cfg_options.insert_atom("debug_assertions".into()); |
381 | 375 | ||
382 | let mut pkg_crates = FxHashMap::default(); | 376 | let mut pkg_crates = FxHashMap::default(); |
383 | 377 | // Does any crate signal to rust-analyzer that they need the rustc_private crates? | |
378 | let mut has_private = false; | ||
384 | // Next, create crates for each package, target pair | 379 | // Next, create crates for each package, target pair |
385 | for pkg in cargo.packages() { | 380 | for pkg in cargo.packages() { |
381 | has_private |= cargo[pkg].metadata.rustc_private; | ||
386 | let mut lib_tgt = None; | 382 | let mut lib_tgt = None; |
387 | for &tgt in cargo[pkg].targets.iter() { | 383 | for &tgt in cargo[pkg].targets.iter() { |
388 | if let Some(file_id) = load(&cargo[tgt].root) { | 384 | if let Some(file_id) = load(&cargo[tgt].root) { |
@@ -443,28 +439,66 @@ fn cargo_to_crate_graph( | |||
443 | } | 439 | } |
444 | } | 440 | } |
445 | 441 | ||
446 | let mut rustc_pkg_crates = FxHashMap::default(); | 442 | if has_private { |
443 | // If the user provided a path to rustc sources, we add all the rustc_private crates | ||
444 | // and create dependencies on them for the crates which opt-in to that | ||
445 | if let Some(rustc_workspace) = rustc { | ||
446 | handle_rustc_crates( | ||
447 | rustc_workspace, | ||
448 | load, | ||
449 | &mut crate_graph, | ||
450 | rustc_build_data_map, | ||
451 | &cfg_options, | ||
452 | proc_macro_loader, | ||
453 | &mut pkg_to_lib_crate, | ||
454 | &public_deps, | ||
455 | cargo, | ||
456 | &pkg_crates, | ||
457 | ); | ||
458 | } | ||
459 | } | ||
460 | crate_graph | ||
461 | } | ||
447 | 462 | ||
448 | // If the user provided a path to rustc sources, we add all the rustc_private crates | 463 | fn handle_rustc_crates( |
449 | // and create dependencies on them for the crates in the current workspace | 464 | rustc_workspace: &CargoWorkspace, |
450 | if let Some(rustc_workspace) = rustc { | 465 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, |
451 | for pkg in rustc_workspace.packages() { | 466 | crate_graph: &mut CrateGraph, |
467 | rustc_build_data_map: Option<&FxHashMap<String, BuildData>>, | ||
468 | cfg_options: &CfgOptions, | ||
469 | proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, | ||
470 | pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>, | ||
471 | public_deps: &[(CrateName, CrateId)], | ||
472 | cargo: &CargoWorkspace, | ||
473 | pkg_crates: &FxHashMap<la_arena::Idx<crate::PackageData>, Vec<CrateId>>, | ||
474 | ) { | ||
475 | let mut rustc_pkg_crates = FxHashMap::default(); | ||
476 | // The root package of the rustc-dev component is rustc_driver, so we match that | ||
477 | let root_pkg = | ||
478 | rustc_workspace.packages().find(|package| rustc_workspace[*package].name == "rustc_driver"); | ||
479 | // The rustc workspace might be incomplete (such as if rustc-dev is not | ||
480 | // installed for the current toolchain) and `rustcSource` is set to discover. | ||
481 | if let Some(root_pkg) = root_pkg { | ||
482 | // Iterate through every crate in the dependency subtree of rustc_driver using BFS | ||
483 | let mut queue = VecDeque::new(); | ||
484 | queue.push_back(root_pkg); | ||
485 | while let Some(pkg) = queue.pop_front() { | ||
486 | // Don't duplicate packages if they are dependended on a diamond pattern | ||
487 | // N.B. if this line is ommitted, we try to analyse over 4_800_000 crates | ||
488 | // which is not ideal | ||
489 | if rustc_pkg_crates.contains_key(&pkg) { | ||
490 | continue; | ||
491 | } | ||
492 | for dep in &rustc_workspace[pkg].dependencies { | ||
493 | queue.push_back(dep.pkg); | ||
494 | } | ||
452 | for &tgt in rustc_workspace[pkg].targets.iter() { | 495 | for &tgt in rustc_workspace[pkg].targets.iter() { |
453 | if rustc_workspace[tgt].kind != TargetKind::Lib { | 496 | if rustc_workspace[tgt].kind != TargetKind::Lib { |
454 | continue; | 497 | continue; |
455 | } | 498 | } |
456 | // Exclude alloc / core / std | ||
457 | if rustc_workspace[tgt] | ||
458 | .root | ||
459 | .components() | ||
460 | .any(|c| c == Component::Normal("library".as_ref())) | ||
461 | { | ||
462 | continue; | ||
463 | } | ||
464 | |||
465 | if let Some(file_id) = load(&rustc_workspace[tgt].root) { | 499 | if let Some(file_id) = load(&rustc_workspace[tgt].root) { |
466 | let crate_id = add_target_crate_root( | 500 | let crate_id = add_target_crate_root( |
467 | &mut crate_graph, | 501 | crate_graph, |
468 | &rustc_workspace[pkg], | 502 | &rustc_workspace[pkg], |
469 | rustc_build_data_map.and_then(|it| it.get(&rustc_workspace[pkg].id)), | 503 | rustc_build_data_map.and_then(|it| it.get(&rustc_workspace[pkg].id)), |
470 | &cfg_options, | 504 | &cfg_options, |
@@ -472,44 +506,50 @@ fn cargo_to_crate_graph( | |||
472 | file_id, | 506 | file_id, |
473 | ); | 507 | ); |
474 | pkg_to_lib_crate.insert(pkg, crate_id); | 508 | pkg_to_lib_crate.insert(pkg, crate_id); |
475 | // Add dependencies on the core / std / alloc for rustc | 509 | // Add dependencies on core / std / alloc for this crate |
476 | for (name, krate) in public_deps.iter() { | 510 | for (name, krate) in public_deps.iter() { |
477 | add_dep(&mut crate_graph, crate_id, name.clone(), *krate); | 511 | add_dep(crate_graph, crate_id, name.clone(), *krate); |
478 | } | 512 | } |
479 | rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); | 513 | rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); |
480 | } | 514 | } |
481 | } | 515 | } |
482 | } | 516 | } |
483 | // Now add a dep edge from all targets of upstream to the lib | 517 | } |
484 | // target of downstream. | 518 | // Now add a dep edge from all targets of upstream to the lib |
485 | for pkg in rustc_workspace.packages() { | 519 | // target of downstream. |
486 | for dep in rustc_workspace[pkg].dependencies.iter() { | 520 | for pkg in rustc_pkg_crates.keys().copied() { |
487 | let name = CrateName::new(&dep.name).unwrap(); | 521 | for dep in rustc_workspace[pkg].dependencies.iter() { |
488 | if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { | 522 | let name = CrateName::new(&dep.name).unwrap(); |
489 | for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() { | 523 | if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { |
490 | add_dep(&mut crate_graph, from, name.clone(), to); | 524 | for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() { |
491 | } | 525 | add_dep(crate_graph, from, name.clone(), to); |
492 | } | 526 | } |
493 | } | 527 | } |
494 | } | 528 | } |
495 | 529 | } | |
496 | // Add dependencies for all the crates of the current workspace to rustc_private libraries | 530 | // Add a dependency on the rustc_private crates for all targets of each package |
497 | for dep in rustc_workspace.packages() { | 531 | // which opts in |
498 | let name = CrateName::normalize_dashes(&rustc_workspace[dep].name); | 532 | for dep in rustc_workspace.packages() { |
499 | 533 | let name = CrateName::normalize_dashes(&rustc_workspace[dep].name); | |
500 | if let Some(&to) = pkg_to_lib_crate.get(&dep) { | 534 | |
501 | for pkg in cargo.packages() { | 535 | if let Some(&to) = pkg_to_lib_crate.get(&dep) { |
502 | if !cargo[pkg].is_member { | 536 | for pkg in cargo.packages() { |
503 | continue; | 537 | let package = &cargo[pkg]; |
504 | } | 538 | if !package.metadata.rustc_private { |
505 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { | 539 | continue; |
506 | add_dep(&mut crate_graph, from, name.clone(), to); | 540 | } |
541 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { | ||
542 | // Avoid creating duplicate dependencies | ||
543 | // This avoids the situation where `from` depends on e.g. `arrayvec`, but | ||
544 | // `rust_analyzer` thinks that it should use the one from the `rustcSource` | ||
545 | // instead of the one from `crates.io` | ||
546 | if !crate_graph[from].dependencies.iter().any(|d| d.name == name) { | ||
547 | add_dep(crate_graph, from, name.clone(), to); | ||
507 | } | 548 | } |
508 | } | 549 | } |
509 | } | 550 | } |
510 | } | 551 | } |
511 | } | 552 | } |
512 | crate_graph | ||
513 | } | 553 | } |
514 | 554 | ||
515 | fn add_target_crate_root( | 555 | fn add_target_crate_root( |