diff options
Diffstat (limited to 'crates/project_model')
-rw-r--r-- | crates/project_model/src/cargo_workspace.rs | 34 | ||||
-rw-r--r-- | crates/project_model/src/workspace.rs | 34 |
2 files changed, 56 insertions, 12 deletions
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index b18699b77..4a4996cf4 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs | |||
@@ -119,6 +119,32 @@ pub struct RustAnalyzerPackageMetaData { | |||
119 | pub struct PackageDependency { | 119 | pub struct PackageDependency { |
120 | pub pkg: Package, | 120 | pub pkg: Package, |
121 | pub name: String, | 121 | pub name: String, |
122 | pub kind: DepKind, | ||
123 | } | ||
124 | |||
125 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
126 | pub enum DepKind { | ||
127 | /// Available to the library, binary, and dev targets in the package (but not the build script). | ||
128 | Normal, | ||
129 | /// Available only to test and bench targets (and the library target, when built with `cfg(test)`). | ||
130 | Dev, | ||
131 | /// Available only to the build script target. | ||
132 | Build, | ||
133 | } | ||
134 | |||
135 | impl DepKind { | ||
136 | fn new(list: &[cargo_metadata::DepKindInfo]) -> Self { | ||
137 | for info in list { | ||
138 | match info.kind { | ||
139 | cargo_metadata::DependencyKind::Normal => return Self::Normal, | ||
140 | cargo_metadata::DependencyKind::Development => return Self::Dev, | ||
141 | cargo_metadata::DependencyKind::Build => return Self::Build, | ||
142 | cargo_metadata::DependencyKind::Unknown => continue, | ||
143 | } | ||
144 | } | ||
145 | |||
146 | Self::Normal | ||
147 | } | ||
122 | } | 148 | } |
123 | 149 | ||
124 | /// Information associated with a package's target | 150 | /// Information associated with a package's target |
@@ -144,6 +170,7 @@ pub enum TargetKind { | |||
144 | Example, | 170 | Example, |
145 | Test, | 171 | Test, |
146 | Bench, | 172 | Bench, |
173 | BuildScript, | ||
147 | Other, | 174 | Other, |
148 | } | 175 | } |
149 | 176 | ||
@@ -155,6 +182,7 @@ impl TargetKind { | |||
155 | "test" => TargetKind::Test, | 182 | "test" => TargetKind::Test, |
156 | "bench" => TargetKind::Bench, | 183 | "bench" => TargetKind::Bench, |
157 | "example" => TargetKind::Example, | 184 | "example" => TargetKind::Example, |
185 | "custom-build" => TargetKind::BuildScript, | ||
158 | "proc-macro" => TargetKind::Lib, | 186 | "proc-macro" => TargetKind::Lib, |
159 | _ if kind.contains("lib") => TargetKind::Lib, | 187 | _ if kind.contains("lib") => TargetKind::Lib, |
160 | _ => continue, | 188 | _ => continue, |
@@ -301,7 +329,11 @@ impl CargoWorkspace { | |||
301 | continue; | 329 | continue; |
302 | } | 330 | } |
303 | }; | 331 | }; |
304 | let dep = PackageDependency { name: dep_node.name, pkg }; | 332 | let dep = PackageDependency { |
333 | name: dep_node.name, | ||
334 | pkg, | ||
335 | kind: DepKind::new(&dep_node.dep_kinds), | ||
336 | }; | ||
305 | packages[source].dependencies.push(dep); | 337 | packages[source].dependencies.push(dep); |
306 | } | 338 | } |
307 | packages[source].active_features.extend(node.features); | 339 | packages[source].active_features.extend(node.features); |
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 761fbb3ab..607e62ea5 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
@@ -6,6 +6,7 @@ use std::{collections::VecDeque, fmt, fs, path::Path, process::Command}; | |||
6 | 6 | ||
7 | use anyhow::{Context, Result}; | 7 | use anyhow::{Context, Result}; |
8 | use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; | 8 | use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; |
9 | use cargo_workspace::DepKind; | ||
9 | use cfg::CfgOptions; | 10 | use cfg::CfgOptions; |
10 | use paths::{AbsPath, AbsPathBuf}; | 11 | use paths::{AbsPath, AbsPathBuf}; |
11 | use proc_macro_api::ProcMacroClient; | 12 | use proc_macro_api::ProcMacroClient; |
@@ -407,23 +408,25 @@ fn cargo_to_crate_graph( | |||
407 | } | 408 | } |
408 | } | 409 | } |
409 | 410 | ||
410 | pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); | 411 | pkg_crates.entry(pkg).or_insert_with(Vec::new).push((crate_id, cargo[tgt].kind)); |
411 | } | 412 | } |
412 | } | 413 | } |
413 | 414 | ||
414 | // Set deps to the core, std and to the lib target of the current package | 415 | // Set deps to the core, std and to the lib target of the current package |
415 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { | 416 | for (from, kind) in pkg_crates.get(&pkg).into_iter().flatten() { |
416 | if let Some((to, name)) = lib_tgt.clone() { | 417 | if let Some((to, name)) = lib_tgt.clone() { |
417 | if to != from { | 418 | if to != *from && *kind != TargetKind::BuildScript { |
419 | // (build script can not depend on its library target) | ||
420 | |||
418 | // For root projects with dashes in their name, | 421 | // For root projects with dashes in their name, |
419 | // cargo metadata does not do any normalization, | 422 | // cargo metadata does not do any normalization, |
420 | // so we do it ourselves currently | 423 | // so we do it ourselves currently |
421 | let name = CrateName::normalize_dashes(&name); | 424 | let name = CrateName::normalize_dashes(&name); |
422 | add_dep(&mut crate_graph, from, name, to); | 425 | add_dep(&mut crate_graph, *from, name, to); |
423 | } | 426 | } |
424 | } | 427 | } |
425 | for (name, krate) in public_deps.iter() { | 428 | for (name, krate) in public_deps.iter() { |
426 | add_dep(&mut crate_graph, from, name.clone(), *krate); | 429 | add_dep(&mut crate_graph, *from, name.clone(), *krate); |
427 | } | 430 | } |
428 | } | 431 | } |
429 | } | 432 | } |
@@ -434,8 +437,17 @@ fn cargo_to_crate_graph( | |||
434 | for dep in cargo[pkg].dependencies.iter() { | 437 | for dep in cargo[pkg].dependencies.iter() { |
435 | let name = CrateName::new(&dep.name).unwrap(); | 438 | let name = CrateName::new(&dep.name).unwrap(); |
436 | if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { | 439 | if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { |
437 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { | 440 | for (from, kind) in pkg_crates.get(&pkg).into_iter().flatten() { |
438 | add_dep(&mut crate_graph, from, name.clone(), to) | 441 | if dep.kind == DepKind::Build && *kind != TargetKind::BuildScript { |
442 | // Only build scripts may depend on build dependencies. | ||
443 | continue; | ||
444 | } | ||
445 | if dep.kind != DepKind::Build && *kind == TargetKind::BuildScript { | ||
446 | // Build scripts may only depend on build dependencies. | ||
447 | continue; | ||
448 | } | ||
449 | |||
450 | add_dep(&mut crate_graph, *from, name.clone(), to) | ||
439 | } | 451 | } |
440 | } | 452 | } |
441 | } | 453 | } |
@@ -472,7 +484,7 @@ fn handle_rustc_crates( | |||
472 | pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>, | 484 | pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>, |
473 | public_deps: &[(CrateName, CrateId)], | 485 | public_deps: &[(CrateName, CrateId)], |
474 | cargo: &CargoWorkspace, | 486 | cargo: &CargoWorkspace, |
475 | pkg_crates: &FxHashMap<la_arena::Idx<crate::PackageData>, Vec<CrateId>>, | 487 | pkg_crates: &FxHashMap<la_arena::Idx<crate::PackageData>, Vec<(CrateId, TargetKind)>>, |
476 | ) { | 488 | ) { |
477 | let mut rustc_pkg_crates = FxHashMap::default(); | 489 | let mut rustc_pkg_crates = FxHashMap::default(); |
478 | // The root package of the rustc-dev component is rustc_driver, so we match that | 490 | // The root package of the rustc-dev component is rustc_driver, so we match that |
@@ -541,13 +553,13 @@ fn handle_rustc_crates( | |||
541 | if !package.metadata.rustc_private { | 553 | if !package.metadata.rustc_private { |
542 | continue; | 554 | continue; |
543 | } | 555 | } |
544 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { | 556 | for (from, _) in pkg_crates.get(&pkg).into_iter().flatten() { |
545 | // Avoid creating duplicate dependencies | 557 | // Avoid creating duplicate dependencies |
546 | // This avoids the situation where `from` depends on e.g. `arrayvec`, but | 558 | // This avoids the situation where `from` depends on e.g. `arrayvec`, but |
547 | // `rust_analyzer` thinks that it should use the one from the `rustcSource` | 559 | // `rust_analyzer` thinks that it should use the one from the `rustcSource` |
548 | // instead of the one from `crates.io` | 560 | // instead of the one from `crates.io` |
549 | if !crate_graph[from].dependencies.iter().any(|d| d.name == name) { | 561 | if !crate_graph[*from].dependencies.iter().any(|d| d.name == name) { |
550 | add_dep(crate_graph, from, name.clone(), to); | 562 | add_dep(crate_graph, *from, name.clone(), to); |
551 | } | 563 | } |
552 | } | 564 | } |
553 | } | 565 | } |