Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/project-model/src/workspace.rs')
-rw-r--r--crates/project-model/src/workspace.rs132
1 files changed, 77 insertions, 55 deletions
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index bc4ab45dae..72ddf80928 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -21,8 +21,8 @@ use crate::{
cfg_flag::CfgFlag,
rustc_cfg,
sysroot::SysrootCrate,
- utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath, ProjectJson, ProjectManifest, Sysroot,
- TargetKind, WorkspaceBuildScripts,
+ utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath, Package, ProjectJson, ProjectManifest,
+ Sysroot, TargetKind, WorkspaceBuildScripts,
};
/// A set of cfg-overrides per crate.
@@ -156,7 +156,11 @@ impl ProjectWorkspace {
})?;
let project_location = project_json.parent().to_path_buf();
let project_json = ProjectJson::new(&project_location, data);
- ProjectWorkspace::load_inline(project_json, config.target.as_deref(), config)?
+ ProjectWorkspace::load_inline(
+ project_json,
+ config.target.as_deref(),
+ &config.extra_env,
+ )?
}
ProjectManifest::CargoToml(cargo_toml) => {
let cargo_version = utf8_stdout({
@@ -184,20 +188,33 @@ impl ProjectWorkspace {
})?;
let cargo = CargoWorkspace::new(meta);
- let sysroot = if config.no_sysroot {
- None
- } else {
- Some(Sysroot::discover(cargo_toml.parent(), config).with_context(|| {
- format!(
+ let sysroot = match &config.sysroot {
+ Some(RustcSource::Path(path)) => {
+ Some(Sysroot::with_sysroot_dir(path.clone()).with_context(|| {
+ format!(
+ "Failed to find sysroot for Cargo.toml file {}.",
+ cargo_toml.display()
+ )
+ })?)
+ }
+ Some(RustcSource::Discover) => Some(
+ Sysroot::discover(cargo_toml.parent(), &config.extra_env).with_context(
+ || {
+ format!(
"Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?",
cargo_toml.display()
)
- })?)
+ },
+ )?,
+ ),
+ None => None,
};
let rustc_dir = match &config.rustc_source {
Some(RustcSource::Path(path)) => ManifestPath::try_from(path.clone()).ok(),
- Some(RustcSource::Discover) => Sysroot::discover_rustc(&cargo_toml, config),
+ Some(RustcSource::Discover) => {
+ Sysroot::discover_rustc(&cargo_toml, &config.extra_env)
+ }
None => None,
};
@@ -217,7 +234,8 @@ impl ProjectWorkspace {
None => None,
};
- let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref(), config);
+ let rustc_cfg =
+ rustc_cfg::get(Some(&cargo_toml), config.target.as_deref(), &config.extra_env);
let cfg_overrides = config.cfg_overrides();
ProjectWorkspace::Cargo {
@@ -238,7 +256,7 @@ impl ProjectWorkspace {
pub fn load_inline(
project_json: ProjectJson,
target: Option<&str>,
- config: &CargoConfig,
+ extra_env: &FxHashMap<String, String>,
) -> Result<ProjectWorkspace> {
let sysroot = match (project_json.sysroot.clone(), project_json.sysroot_src.clone()) {
(Some(sysroot), Some(sysroot_src)) => Some(Sysroot::load(sysroot, sysroot_src)?),
@@ -260,7 +278,7 @@ impl ProjectWorkspace {
(None, None) => None,
};
- let rustc_cfg = rustc_cfg::get(None, target, config);
+ let rustc_cfg = rustc_cfg::get(None, target, extra_env);
Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg })
}
@@ -270,9 +288,9 @@ impl ProjectWorkspace {
.first()
.and_then(|it| it.parent())
.ok_or_else(|| format_err!("No detached files to load"))?,
- &CargoConfig::default(),
+ &Default::default(),
)?;
- let rustc_cfg = rustc_cfg::get(None, None, &CargoConfig::default());
+ let rustc_cfg = rustc_cfg::get(None, None, &Default::default());
Ok(ProjectWorkspace::DetachedFiles { files: detached_files, sysroot, rustc_cfg })
}
@@ -306,6 +324,13 @@ impl ProjectWorkspace {
/// The return type contains the path and whether or not
/// the root is a member of the current workspace
pub fn to_roots(&self) -> Vec<PackageRoot> {
+ let mk_sysroot = |sysroot: Option<&Sysroot>| {
+ sysroot.map(|sysroot| PackageRoot {
+ is_local: false,
+ include: vec![sysroot.src_root().to_path_buf()],
+ exclude: Vec::new(),
+ })
+ };
match self {
ProjectWorkspace::Json { project, sysroot, rustc_cfg: _ } => project
.crates()
@@ -316,13 +341,7 @@ impl ProjectWorkspace {
})
.collect::<FxHashSet<_>>()
.into_iter()
- .chain(sysroot.as_ref().into_iter().flat_map(|sysroot| {
- sysroot.crates().map(move |krate| PackageRoot {
- is_local: false,
- include: vec![sysroot[krate].root.parent().to_path_buf()],
- exclude: Vec::new(),
- })
- }))
+ .chain(mk_sysroot(sysroot.as_ref()))
.collect::<Vec<_>>(),
ProjectWorkspace::Cargo {
cargo,
@@ -371,11 +390,7 @@ impl ProjectWorkspace {
}
PackageRoot { is_local, include, exclude }
})
- .chain(sysroot.iter().map(|sysroot| PackageRoot {
- is_local: false,
- include: vec![sysroot.src_root().to_path_buf()],
- exclude: Vec::new(),
- }))
+ .chain(mk_sysroot(sysroot.as_ref()))
.chain(rustc.iter().flat_map(|rustc| {
rustc.packages().map(move |krate| PackageRoot {
is_local: false,
@@ -392,11 +407,7 @@ impl ProjectWorkspace {
include: vec![detached_file.clone()],
exclude: Vec::new(),
})
- .chain(sysroot.crates().map(|krate| PackageRoot {
- is_local: false,
- include: vec![sysroot[krate].root.parent().to_path_buf()],
- exclude: Vec::new(),
- }))
+ .chain(mk_sysroot(Some(sysroot)))
.collect(),
}
}
@@ -419,7 +430,7 @@ impl ProjectWorkspace {
&self,
load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
- config: &CargoConfig,
+ extra_env: &FxHashMap<String, String>,
) -> CrateGraph {
let _p = profile::span("ProjectWorkspace::to_crate_graph");
@@ -430,7 +441,7 @@ impl ProjectWorkspace {
load,
project,
sysroot,
- config,
+ extra_env,
),
ProjectWorkspace::Cargo {
cargo,
@@ -469,7 +480,7 @@ fn project_json_to_crate_graph(
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
project: &ProjectJson,
sysroot: &Option<Sysroot>,
- config: &CargoConfig,
+ extra_env: &FxHashMap<String, String>,
) -> CrateGraph {
let mut crate_graph = CrateGraph::default();
let sysroot_deps = sysroot
@@ -497,7 +508,7 @@ fn project_json_to_crate_graph(
let target_cfgs = match krate.target.as_deref() {
Some(target) => cfg_cache
.entry(target)
- .or_insert_with(|| rustc_cfg::get(None, Some(target), config)),
+ .or_insert_with(|| rustc_cfg::get(None, Some(target), extra_env)),
None => &rustc_cfg,
};
@@ -516,9 +527,15 @@ fn project_json_to_crate_graph(
proc_macro,
krate.is_proc_macro,
if krate.display_name.is_some() {
- CrateOrigin::CratesIo { repo: krate.repository.clone() }
+ CrateOrigin::CratesIo {
+ repo: krate.repository.clone(),
+ name: krate
+ .display_name
+ .clone()
+ .map(|n| n.canonical_name().to_string()),
+ }
} else {
- CrateOrigin::CratesIo { repo: None }
+ CrateOrigin::CratesIo { repo: None, name: None }
},
),
)
@@ -630,6 +647,8 @@ fn cargo_to_crate_graph(
lib_tgt = Some((crate_id, cargo[tgt].name.clone()));
pkg_to_lib_crate.insert(pkg, crate_id);
}
+ // Even crates that don't set proc-macro = true are allowed to depend on proc_macro
+ // (just none of the APIs work when called outside of a proc macro).
if let Some(proc_macro) = libproc_macro {
add_dep_with_prelude(
&mut crate_graph,
@@ -645,19 +664,19 @@ fn cargo_to_crate_graph(
}
// Set deps to the core, std and to the lib target of the current package
- for (from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
+ for &(from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
// Add sysroot deps first so that a lib target named `core` etc. can overwrite them.
- public_deps.add(*from, &mut crate_graph);
+ public_deps.add(from, &mut crate_graph);
if let Some((to, name)) = lib_tgt.clone() {
- if to != *from && *kind != TargetKind::BuildScript {
+ if to != from && kind != TargetKind::BuildScript {
// (build script can not depend on its library target)
// For root projects with dashes in their name,
// cargo metadata does not do any normalization,
// so we do it ourselves currently
let name = CrateName::normalize_dashes(&name);
- add_dep(&mut crate_graph, *from, name, to);
+ add_dep(&mut crate_graph, from, name, to);
}
}
}
@@ -669,17 +688,17 @@ fn cargo_to_crate_graph(
for dep in cargo[pkg].dependencies.iter() {
let name = CrateName::new(&dep.name).unwrap();
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
- for (from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
- if dep.kind == DepKind::Build && *kind != TargetKind::BuildScript {
+ for &(from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
+ if dep.kind == DepKind::Build && kind != TargetKind::BuildScript {
// Only build scripts may depend on build dependencies.
continue;
}
- if dep.kind != DepKind::Build && *kind == TargetKind::BuildScript {
+ if dep.kind != DepKind::Build && kind == TargetKind::BuildScript {
// Build scripts may only depend on build dependencies.
continue;
}
- add_dep(&mut crate_graph, *from, name.clone(), to)
+ add_dep(&mut crate_graph, from, name.clone(), to)
}
}
}
@@ -690,9 +709,9 @@ fn cargo_to_crate_graph(
// and create dependencies on them for the crates which opt-in to that
if let Some(rustc_workspace) = rustc {
handle_rustc_crates(
+ &mut crate_graph,
rustc_workspace,
load,
- &mut crate_graph,
&cfg_options,
override_cfg,
load_proc_macro,
@@ -736,14 +755,17 @@ fn detached_files_to_crate_graph(
let detached_file_crate = crate_graph.add_crate_root(
file_id,
Edition::CURRENT,
- display_name,
+ display_name.clone(),
None,
cfg_options.clone(),
cfg_options.clone(),
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo {
+ repo: None,
+ name: display_name.map(|n| n.canonical_name().to_string()),
+ },
);
public_deps.add(detached_file_crate, &mut crate_graph);
@@ -752,16 +774,16 @@ fn detached_files_to_crate_graph(
}
fn handle_rustc_crates(
+ crate_graph: &mut CrateGraph,
rustc_workspace: &CargoWorkspace,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
- crate_graph: &mut CrateGraph,
cfg_options: &CfgOptions,
override_cfg: &CfgOverrides,
load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult,
- pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>,
+ pkg_to_lib_crate: &mut FxHashMap<Package, CrateId>,
public_deps: &SysrootPublicDeps,
cargo: &CargoWorkspace,
- pkg_crates: &FxHashMap<la_arena::Idx<crate::PackageData>, Vec<(CrateId, TargetKind)>>,
+ pkg_crates: &FxHashMap<Package, Vec<(CrateId, TargetKind)>>,
build_scripts: &WorkspaceBuildScripts,
) {
let mut rustc_pkg_crates = FxHashMap::default();
@@ -775,8 +797,8 @@ fn handle_rustc_crates(
let mut queue = VecDeque::new();
queue.push_back(root_pkg);
while let Some(pkg) = queue.pop_front() {
- // Don't duplicate packages if they are dependended on a diamond pattern
- // N.B. if this line is omitted, we try to analyse over 4_800_000 crates
+ // Don't duplicate packages if they are dependent on a diamond pattern
+ // N.B. if this line is omitted, we try to analyze over 4_800_000 crates
// which is not ideal
if rustc_pkg_crates.contains_key(&pkg) {
continue;
@@ -919,7 +941,7 @@ fn add_target_crate_root(
env,
proc_macro,
is_proc_macro,
- CrateOrigin::CratesIo { repo: pkg.repository.clone() },
+ CrateOrigin::CratesIo { repo: pkg.repository.clone(), name: Some(pkg.name.clone()) },
)
}