From: Eduardo Broto Date: Fri, 22 May 2020 20:39:19 +0000 (+0200) Subject: multiple_crate_versions: skip dev and build deps X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=8642fc97dd1a9b4f0291726c47ec97d15599d74d;p=rust.git multiple_crate_versions: skip dev and build deps --- diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs index c4decfc9401..b24ec897ef5 100644 --- a/clippy_lints/src/multiple_crate_versions.rs +++ b/clippy_lints/src/multiple_crate_versions.rs @@ -1,11 +1,14 @@ //! lint on multiple versions of a crate being used use crate::utils::{run_lints, span_lint}; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::{Crate, CRATE_HIR_ID}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::DUMMY_SP; +use cargo_metadata::{DependencyKind, MetadataCommand, Node, Package, PackageId}; +use if_chain::if_chain; use itertools::Itertools; declare_clippy_lint! { @@ -34,37 +37,65 @@ declare_lint_pass!(MultipleCrateVersions => [MULTIPLE_CRATE_VERSIONS]); impl LateLintPass<'_, '_> for MultipleCrateVersions { + #[allow(clippy::find_map)] fn check_crate(&mut self, cx: &LateContext<'_, '_>, _: &Crate<'_>) { if !run_lints(cx, &[MULTIPLE_CRATE_VERSIONS], CRATE_HIR_ID) { return; } - let metadata = if let Ok(metadata) = cargo_metadata::MetadataCommand::new().exec() { + let metadata = if let Ok(metadata) = MetadataCommand::new().exec() { metadata } else { span_lint(cx, MULTIPLE_CRATE_VERSIONS, DUMMY_SP, "could not read cargo metadata"); - return; }; + let local_name = cx.tcx.crate_name(LOCAL_CRATE).as_str(); let mut packages = metadata.packages; packages.sort_by(|a, b| a.name.cmp(&b.name)); - for (name, group) in &packages.into_iter().group_by(|p| p.name.clone()) { - let group: Vec = group.collect(); + if_chain! { + if let Some(resolve) = &metadata.resolve; + if let Some(local_id) = packages.iter().find(|p| p.name == *local_name).map(|p| &p.id); + then { + for (name, group) in &packages.iter().group_by(|p| p.name.clone()) { + let group: Vec<&Package> = group.collect(); + + if group.len() <= 1 { + continue; + } - if group.len() > 1 { - let mut versions: Vec<_> = group.into_iter().map(|p| p.version).collect(); - versions.sort(); - let versions = versions.iter().join(", "); + if group.iter().all(|p| is_normal_dep(&resolve.nodes, local_id, &p.id)) { + let mut versions: Vec<_> = group.into_iter().map(|p| &p.version).collect(); + versions.sort(); + let versions = versions.iter().join(", "); - span_lint( - cx, - MULTIPLE_CRATE_VERSIONS, - DUMMY_SP, - &format!("multiple versions for dependency `{}`: {}", name, versions), - ); + span_lint( + cx, + MULTIPLE_CRATE_VERSIONS, + DUMMY_SP, + &format!("multiple versions for dependency `{}`: {}", name, versions), + ); + } + } } } } } + +fn is_normal_dep(nodes: &[Node], local_id: &PackageId, dep_id: &PackageId) -> bool { + fn depends_on(node: &Node, dep_id: &PackageId) -> bool { + node.deps.iter().any(|dep| { + dep.pkg == *dep_id + && dep + .dep_kinds + .iter() + .any(|info| matches!(info.kind, DependencyKind::Normal)) + }) + } + + nodes + .iter() + .filter(|node| depends_on(node, dep_id)) + .any(|node| node.id == *local_id || is_normal_dep(nodes, local_id, &node.id)) +} diff --git a/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml new file mode 100644 index 00000000000..72731fbc75d --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml @@ -0,0 +1,17 @@ +# Should not lint for dev or build dependencies. See issue 5041. + +[package] +name = "multiple_crate_versions" +version = "0.1.0" +publish = false + +# One of the versions of winapi is only a dev dependency: allowed +[dependencies] +ctrlc = "=3.1.0" +[dev-dependencies] +ansi_term = "=0.11.0" + +# Both versions of winapi are a build dependency: allowed +[build-dependencies] +ctrlc = "=3.1.0" +ansi_term = "=0.11.0" diff --git a/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs new file mode 100644 index 00000000000..1b2d3ec9459 --- /dev/null +++ b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs @@ -0,0 +1,4 @@ +// compile-flags: --crate-name=multiple_crate_versions +#![warn(clippy::multiple_crate_versions)] + +fn main() {}