From 48072bcfe6e42d31b289751033b712322be00d60 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Thu, 27 Oct 2022 22:19:36 +0800 Subject: [PATCH] Improve file found in multiple build targets warning Signed-off-by: hi-rustin --- src/cargo/util/toml/mod.rs | 51 ++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index a6f144cb5622..76db07a8de0c 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -1,4 +1,5 @@ -use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::collections::hash_map::Entry; +use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::fmt; use std::marker::PhantomData; use std::path::{Path, PathBuf}; @@ -1737,12 +1738,22 @@ impl TomlManifest { debug!("manifest has no build targets"); } - if let Err(e) = unique_build_targets(&targets, package_root) { - warnings.push(format!( - "file found to be present in multiple \ - build targets: {}", - e - )); + if let Err(conflict_targets) = unique_build_targets(&targets, package_root) { + conflict_targets.iter().for_each(|c| { + warnings.push(format!( + "file `{}` found to be present in multiple \ + build targets:\n{}", + c.0.display().to_string(), + c.1.iter() + .map(|t| format!( + " * This file exist in `{}` as a `{}` target.", + t.name(), + t.kind().description() + )) + .collect::>() + .join("\n") + )); + }) } if let Some(links) = &package.links { @@ -2442,16 +2453,34 @@ fn default_readme_from_package_root(package_root: &Path) -> Option { /// Checks a list of build targets, and ensures the target names are unique within a vector. /// If not, the name of the offending build target is returned. -fn unique_build_targets(targets: &[Target], package_root: &Path) -> Result<(), String> { - let mut seen = HashSet::new(); +fn unique_build_targets( + targets: &[Target], + package_root: &Path, +) -> Result<(), HashMap>> { + let mut source_targets = HashMap::new(); for target in targets { if let TargetSourcePath::Path(path) = target.src_path() { let full = package_root.join(path); - if !seen.insert(full.clone()) { - return Err(full.display().to_string()); + match source_targets.entry(full) { + Entry::Vacant(e) => { + e.insert(vec![target.clone()]); + } + Entry::Occupied(mut e) => { + e.get_mut().push(target.clone()); + } } } } + + let conflict_targets = source_targets + .into_iter() + .filter(|(_, targets)| targets.len() > 1) + .collect::>(); + + if !conflict_targets.is_empty() { + return Err(conflict_targets); + } + Ok(()) }