mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-28 04:45:05 +00:00
Merge #6571
6571: Cleanup project model r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
10e3a9879c
3 changed files with 73 additions and 106 deletions
|
@ -225,7 +225,10 @@ impl CrateGraph {
|
||||||
to: CrateId,
|
to: CrateId,
|
||||||
) -> Result<(), CyclicDependenciesError> {
|
) -> Result<(), CyclicDependenciesError> {
|
||||||
if self.dfs_find(from, to, &mut FxHashSet::default()) {
|
if self.dfs_find(from, to, &mut FxHashSet::default()) {
|
||||||
return Err(CyclicDependenciesError);
|
return Err(CyclicDependenciesError {
|
||||||
|
from: (from, self[from].display_name.clone()),
|
||||||
|
to: (to, self[to].display_name.clone()),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
self.arena.get_mut(&from).unwrap().add_dep(name, to);
|
self.arena.get_mut(&from).unwrap().add_dep(name, to);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -421,7 +424,20 @@ impl fmt::Display for ParseEditionError {
|
||||||
impl std::error::Error for ParseEditionError {}
|
impl std::error::Error for ParseEditionError {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CyclicDependenciesError;
|
pub struct CyclicDependenciesError {
|
||||||
|
from: (CrateId, Option<CrateDisplayName>),
|
||||||
|
to: (CrateId, Option<CrateDisplayName>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for CyclicDependenciesError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let render = |(id, name): &(CrateId, Option<CrateDisplayName>)| match name {
|
||||||
|
Some(it) => format!("{}({:?})", it, id),
|
||||||
|
None => format!("{:?}", id),
|
||||||
|
};
|
||||||
|
write!(f, "cyclic deps: {} -> {}", render(&self.from), render(&self.to))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl Sysroot {
|
||||||
pub fn public_deps(&self) -> impl Iterator<Item = (&'static str, SysrootCrate)> + '_ {
|
pub fn public_deps(&self) -> impl Iterator<Item = (&'static str, SysrootCrate)> + '_ {
|
||||||
// core is added as a dependency before std in order to
|
// core is added as a dependency before std in order to
|
||||||
// mimic rustcs dependency order
|
// mimic rustcs dependency order
|
||||||
vec!["core", "alloc", "std"].into_iter().filter_map(move |it| Some((it, self.by_name(it)?)))
|
["core", "alloc", "std"].iter().filter_map(move |&it| Some((it, self.by_name(it)?)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn proc_macro(&self) -> Option<SysrootCrate> {
|
pub fn proc_macro(&self) -> Option<SysrootCrate> {
|
||||||
|
|
|
@ -12,8 +12,8 @@ use proc_macro_api::ProcMacroClient;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cargo_workspace, cfg_flag::CfgFlag, utf8_stdout, CargoConfig, CargoWorkspace, ProjectJson,
|
cargo_workspace, cfg_flag::CfgFlag, sysroot::SysrootCrate, utf8_stdout, CargoConfig,
|
||||||
ProjectManifest, Sysroot, TargetKind,
|
CargoWorkspace, ProjectJson, ProjectManifest, Sysroot, TargetKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// `PackageRoot` describes a package root folder.
|
/// `PackageRoot` describes a package root folder.
|
||||||
|
@ -70,12 +70,8 @@ impl ProjectWorkspace {
|
||||||
format!("Failed to deserialize json file {}", project_json.display())
|
format!("Failed to deserialize json file {}", project_json.display())
|
||||||
})?;
|
})?;
|
||||||
let project_location = project_json.parent().unwrap().to_path_buf();
|
let project_location = project_json.parent().unwrap().to_path_buf();
|
||||||
let project = ProjectJson::new(&project_location, data);
|
let project_json = ProjectJson::new(&project_location, data);
|
||||||
let sysroot = match &project.sysroot_src {
|
ProjectWorkspace::load_inline(project_json)?
|
||||||
Some(path) => Some(Sysroot::load(path)?),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
ProjectWorkspace::Json { project, sysroot }
|
|
||||||
}
|
}
|
||||||
ProjectManifest::CargoToml(cargo_toml) => {
|
ProjectManifest::CargoToml(cargo_toml) => {
|
||||||
let cargo_version = utf8_stdout({
|
let cargo_version = utf8_stdout({
|
||||||
|
@ -150,43 +146,38 @@ impl ProjectWorkspace {
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
ProjectWorkspace::Cargo { cargo, sysroot, rustc } => {
|
ProjectWorkspace::Cargo { cargo, sysroot, rustc } => cargo
|
||||||
let roots = cargo
|
.packages()
|
||||||
.packages()
|
.map(|pkg| {
|
||||||
.map(|pkg| {
|
let is_member = cargo[pkg].is_member;
|
||||||
let is_member = cargo[pkg].is_member;
|
let pkg_root = cargo[pkg].root().to_path_buf();
|
||||||
let pkg_root = cargo[pkg].root().to_path_buf();
|
|
||||||
|
|
||||||
let mut include = vec![pkg_root.clone()];
|
let mut include = vec![pkg_root.clone()];
|
||||||
include.extend(cargo[pkg].out_dir.clone());
|
include.extend(cargo[pkg].out_dir.clone());
|
||||||
|
|
||||||
let mut exclude = vec![pkg_root.join(".git")];
|
let mut exclude = vec![pkg_root.join(".git")];
|
||||||
if is_member {
|
if is_member {
|
||||||
exclude.push(pkg_root.join("target"));
|
exclude.push(pkg_root.join("target"));
|
||||||
} else {
|
} else {
|
||||||
exclude.push(pkg_root.join("tests"));
|
exclude.push(pkg_root.join("tests"));
|
||||||
exclude.push(pkg_root.join("examples"));
|
exclude.push(pkg_root.join("examples"));
|
||||||
exclude.push(pkg_root.join("benches"));
|
exclude.push(pkg_root.join("benches"));
|
||||||
}
|
}
|
||||||
PackageRoot { is_member, include, exclude }
|
PackageRoot { is_member, include, exclude }
|
||||||
})
|
})
|
||||||
.chain(sysroot.crates().map(|krate| PackageRoot {
|
.chain(sysroot.crates().map(|krate| PackageRoot {
|
||||||
|
is_member: false,
|
||||||
|
include: vec![sysroot[krate].root_dir().to_path_buf()],
|
||||||
|
exclude: Vec::new(),
|
||||||
|
}))
|
||||||
|
.chain(rustc.into_iter().flat_map(|rustc| {
|
||||||
|
rustc.packages().map(move |krate| PackageRoot {
|
||||||
is_member: false,
|
is_member: false,
|
||||||
include: vec![sysroot[krate].root_dir().to_path_buf()],
|
include: vec![rustc[krate].root().to_path_buf()],
|
||||||
exclude: Vec::new(),
|
exclude: Vec::new(),
|
||||||
}));
|
})
|
||||||
if let Some(rustc_packages) = rustc {
|
}))
|
||||||
roots
|
.collect(),
|
||||||
.chain(rustc_packages.packages().map(|krate| PackageRoot {
|
|
||||||
is_member: false,
|
|
||||||
include: vec![rustc_packages[krate].root().to_path_buf()],
|
|
||||||
exclude: Vec::new(),
|
|
||||||
}))
|
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
roots.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,18 +249,14 @@ impl ProjectWorkspace {
|
||||||
if let Some(&from) = crates.get(&from) {
|
if let Some(&from) = crates.get(&from) {
|
||||||
if let Some((public_deps, _proc_macro)) = &sysroot_dps {
|
if let Some((public_deps, _proc_macro)) = &sysroot_dps {
|
||||||
for (name, to) in public_deps.iter() {
|
for (name, to) in public_deps.iter() {
|
||||||
if let Err(_) = crate_graph.add_dep(from, name.clone(), *to) {
|
add_dep(&mut crate_graph, from, name.clone(), *to)
|
||||||
log::error!("cyclic dependency on {} for {:?}", name, from)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for dep in &krate.deps {
|
for dep in &krate.deps {
|
||||||
let to_crate_id = dep.crate_id;
|
let to_crate_id = dep.crate_id;
|
||||||
if let Some(&to) = crates.get(&to_crate_id) {
|
if let Some(&to) = crates.get(&to_crate_id) {
|
||||||
if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) {
|
add_dep(&mut crate_graph, from, dep.name.clone(), to)
|
||||||
log::error!("cyclic dependency {:?} -> {:?}", from, to);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,16 +295,12 @@ impl ProjectWorkspace {
|
||||||
}
|
}
|
||||||
if cargo[tgt].is_proc_macro {
|
if cargo[tgt].is_proc_macro {
|
||||||
if let Some(proc_macro) = libproc_macro {
|
if let Some(proc_macro) = libproc_macro {
|
||||||
if let Err(_) = crate_graph.add_dep(
|
add_dep(
|
||||||
|
&mut crate_graph,
|
||||||
crate_id,
|
crate_id,
|
||||||
CrateName::new("proc_macro").unwrap(),
|
CrateName::new("proc_macro").unwrap(),
|
||||||
proc_macro,
|
proc_macro,
|
||||||
) {
|
);
|
||||||
log::error!(
|
|
||||||
"cyclic dependency on proc_macro for {}",
|
|
||||||
&cargo[pkg].name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,21 +315,12 @@ impl ProjectWorkspace {
|
||||||
// cargo metadata does not do any normalization,
|
// cargo metadata does not do any normalization,
|
||||||
// so we do it ourselves currently
|
// so we do it ourselves currently
|
||||||
let name = CrateName::normalize_dashes(&name);
|
let name = CrateName::normalize_dashes(&name);
|
||||||
if to != from && crate_graph.add_dep(from, name, to).is_err() {
|
if to != from {
|
||||||
log::error!(
|
add_dep(&mut crate_graph, from, name, to);
|
||||||
"cyclic dependency between targets of {}",
|
|
||||||
&cargo[pkg].name
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (name, krate) in public_deps.iter() {
|
for (name, krate) in public_deps.iter() {
|
||||||
if let Err(_) = crate_graph.add_dep(from, name.clone(), *krate) {
|
add_dep(&mut crate_graph, from, name.clone(), *krate);
|
||||||
log::error!(
|
|
||||||
"cyclic dependency on {} for {}",
|
|
||||||
name,
|
|
||||||
&cargo[pkg].name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -358,13 +332,7 @@ impl ProjectWorkspace {
|
||||||
let name = CrateName::new(&dep.name).unwrap();
|
let name = CrateName::new(&dep.name).unwrap();
|
||||||
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
|
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
|
||||||
for &from in pkg_crates.get(&pkg).into_iter().flatten() {
|
for &from in pkg_crates.get(&pkg).into_iter().flatten() {
|
||||||
if let Err(_) = crate_graph.add_dep(from, name.clone(), to) {
|
add_dep(&mut crate_graph, from, name.clone(), to)
|
||||||
log::error!(
|
|
||||||
"cyclic dependency {} -> {}",
|
|
||||||
&cargo[pkg].name,
|
|
||||||
&cargo[dep.pkg].name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,15 +368,7 @@ impl ProjectWorkspace {
|
||||||
pkg_to_lib_crate.insert(pkg, crate_id);
|
pkg_to_lib_crate.insert(pkg, crate_id);
|
||||||
// Add dependencies on the core / std / alloc for rustc
|
// Add dependencies on the core / std / alloc for rustc
|
||||||
for (name, krate) in public_deps.iter() {
|
for (name, krate) in public_deps.iter() {
|
||||||
if let Err(_) =
|
add_dep(&mut crate_graph, crate_id, name.clone(), *krate);
|
||||||
crate_graph.add_dep(crate_id, name.clone(), *krate)
|
|
||||||
{
|
|
||||||
log::error!(
|
|
||||||
"cyclic dependency on {} for {}",
|
|
||||||
name,
|
|
||||||
&cargo[pkg].name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
|
rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
|
||||||
}
|
}
|
||||||
|
@ -421,13 +381,7 @@ impl ProjectWorkspace {
|
||||||
let name = CrateName::new(&dep.name).unwrap();
|
let name = CrateName::new(&dep.name).unwrap();
|
||||||
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
|
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
|
||||||
for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() {
|
for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() {
|
||||||
if let Err(_) = crate_graph.add_dep(from, name.clone(), to) {
|
add_dep(&mut crate_graph, from, name.clone(), to);
|
||||||
log::error!(
|
|
||||||
"cyclic dependency {} -> {}",
|
|
||||||
&rustc_workspace[pkg].name,
|
|
||||||
&rustc_workspace[dep.pkg].name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,13 +397,7 @@ impl ProjectWorkspace {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for &from in pkg_crates.get(&pkg).into_iter().flatten() {
|
for &from in pkg_crates.get(&pkg).into_iter().flatten() {
|
||||||
if let Err(_) = crate_graph.add_dep(from, name.clone(), to) {
|
add_dep(&mut crate_graph, from, name.clone(), to);
|
||||||
log::error!(
|
|
||||||
"cyclic dependency {} -> {}",
|
|
||||||
&cargo[pkg].name,
|
|
||||||
&rustc_workspace[dep].name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -520,19 +468,18 @@ fn sysroot_to_crate_graph(
|
||||||
) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) {
|
) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) {
|
||||||
let mut cfg_options = CfgOptions::default();
|
let mut cfg_options = CfgOptions::default();
|
||||||
cfg_options.extend(get_rustc_cfg_options(target));
|
cfg_options.extend(get_rustc_cfg_options(target));
|
||||||
let sysroot_crates: FxHashMap<_, _> = sysroot
|
let sysroot_crates: FxHashMap<SysrootCrate, CrateId> = sysroot
|
||||||
.crates()
|
.crates()
|
||||||
.filter_map(|krate| {
|
.filter_map(|krate| {
|
||||||
let file_id = load(&sysroot[krate].root)?;
|
let file_id = load(&sysroot[krate].root)?;
|
||||||
|
|
||||||
let env = Env::default();
|
let env = Env::default();
|
||||||
let proc_macro = vec![];
|
let proc_macro = vec![];
|
||||||
let name = CrateName::new(&sysroot[krate].name)
|
let display_name = CrateDisplayName::from_canonical_name(sysroot[krate].name.clone());
|
||||||
.expect("Sysroot crates' names do not contain dashes");
|
|
||||||
let crate_id = crate_graph.add_crate_root(
|
let crate_id = crate_graph.add_crate_root(
|
||||||
file_id,
|
file_id,
|
||||||
Edition::Edition2018,
|
Edition::Edition2018,
|
||||||
Some(name.into()),
|
Some(display_name),
|
||||||
cfg_options.clone(),
|
cfg_options.clone(),
|
||||||
env,
|
env,
|
||||||
proc_macro,
|
proc_macro,
|
||||||
|
@ -545,9 +492,7 @@ fn sysroot_to_crate_graph(
|
||||||
for &to in sysroot[from].deps.iter() {
|
for &to in sysroot[from].deps.iter() {
|
||||||
let name = CrateName::new(&sysroot[to].name).unwrap();
|
let name = CrateName::new(&sysroot[to].name).unwrap();
|
||||||
if let (Some(&from), Some(&to)) = (sysroot_crates.get(&from), sysroot_crates.get(&to)) {
|
if let (Some(&from), Some(&to)) = (sysroot_crates.get(&from), sysroot_crates.get(&to)) {
|
||||||
if let Err(_) = crate_graph.add_dep(from, name, to) {
|
add_dep(crate_graph, from, name, to);
|
||||||
log::error!("cyclic dependency between sysroot crates")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -588,3 +533,9 @@ fn get_rustc_cfg_options(target: Option<&str>) -> Vec<CfgFlag> {
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) {
|
||||||
|
if let Err(err) = graph.add_dep(from, name, to) {
|
||||||
|
log::error!("{}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue