diff options
Diffstat (limited to 'tools/rust_analyzer/rust_project.rs')
-rw-r--r-- | tools/rust_analyzer/rust_project.rs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/tools/rust_analyzer/rust_project.rs b/tools/rust_analyzer/rust_project.rs index e4314a23..ba87c581 100644 --- a/tools/rust_analyzer/rust_project.rs +++ b/tools/rust_analyzer/rust_project.rs @@ -168,6 +168,23 @@ pub fn generate_rust_project( skipped_crates.len(), skipped_crates ); + let crate_map: BTreeMap<String, &CrateSpec> = unmerged_crates + .iter() + .map(|c| (c.crate_id.to_string(), *c)) + .collect(); + + for unmerged_crate in &unmerged_crates { + let mut path = vec![]; + if let Some(cycle) = detect_cycle(unmerged_crate, &crate_map, &mut path) { + log::warn!( + "Cycle detected: {:?}", + cycle + .iter() + .map(|c| c.crate_id.to_string()) + .collect::<Vec<String>>() + ); + } + } return Err(anyhow!( "Failed to make progress on building crate dependency graph" )); @@ -179,6 +196,38 @@ pub fn generate_rust_project( Ok(project) } +fn detect_cycle<'a>( + current_crate: &'a CrateSpec, + all_crates: &'a BTreeMap<String, &'a CrateSpec>, + path: &mut Vec<&'a CrateSpec>, +) -> Option<Vec<&'a CrateSpec>> { + if path + .iter() + .any(|dependent_crate| dependent_crate.crate_id == current_crate.crate_id) + { + let mut cycle_path = path.clone(); + cycle_path.push(current_crate); + return Some(cycle_path); + } + + path.push(current_crate); + + for dep in ¤t_crate.deps { + match all_crates.get(dep) { + Some(dep_crate) => { + if let Some(cycle) = detect_cycle(dep_crate, all_crates, path) { + return Some(cycle); + } + } + None => log::debug!("dep {dep} not found in unmerged crate map"), + } + } + + path.pop(); + + None +} + pub fn write_rust_project( rust_project_path: &Path, execution_root: &Path, |