about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-05-26 06:23:58 +0000
committerbors <bors@rust-lang.org>2020-05-26 06:23:58 +0000
commit182ac89f16ff2594eaa1e3e899fa4d228a3539c3 (patch)
treefcaeb6081e441c8f4e5ff9549a83a772ffd78605
parent2a6cfa7f0537e9437de8ccd3781fb44645af6082 (diff)
parentec0a00e53980619a6313ff4f01099a1aebcfd9e6 (diff)
downloadrust-182ac89f16ff2594eaa1e3e899fa4d228a3539c3.tar.gz
rust-182ac89f16ff2594eaa1e3e899fa4d228a3539c3.zip
Auto merge of #5636 - ebroto:issue_5041, r=phansch
multiple_crate_versions: skip dev and build deps

changelog: multiple_crate_versions: skip dev and build deps

Closes #5041
-rw-r--r--clippy_dev/src/new_lint.rs17
-rw-r--r--clippy_lints/src/multiple_crate_versions.rs60
-rw-r--r--tests/ui-cargo/cargo_common_metadata/fail/src/main.rs1
-rw-r--r--tests/ui-cargo/cargo_common_metadata/pass/src/main.rs1
-rw-r--r--tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml17
-rw-r--r--tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/src/main.rs4
-rw-r--r--tests/ui-cargo/multiple_crate_versions/fail/src/main.rs1
-rw-r--r--tests/ui-cargo/multiple_crate_versions/pass/src/main.rs1
-rw-r--r--tests/ui-cargo/wildcard_dependencies/fail/src/main.rs1
-rw-r--r--tests/ui-cargo/wildcard_dependencies/pass/src/main.rs1
10 files changed, 85 insertions, 19 deletions
diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs
index 08a2e0c0918..c0b2dac2f60 100644
--- a/clippy_dev/src/new_lint.rs
+++ b/clippy_dev/src/new_lint.rs
@@ -76,7 +76,8 @@ fn create_test(lint: &LintData) -> io::Result<()> {
 
         path.push("src");
         fs::create_dir(&path)?;
-        write_file(path.join("main.rs"), get_test_file_contents(lint_name))?;
+        let header = format!("// compile-flags: --crate-name={}", lint_name);
+        write_file(path.join("main.rs"), get_test_file_contents(lint_name, Some(&header)))?;
 
         Ok(())
     }
@@ -90,7 +91,7 @@ fn create_test(lint: &LintData) -> io::Result<()> {
         create_project_layout(lint.name, &test_dir, "pass", "This file should not trigger the lint")
     } else {
         let test_path = format!("tests/ui/{}.rs", lint.name);
-        let test_contents = get_test_file_contents(lint.name);
+        let test_contents = get_test_file_contents(lint.name, None);
         write_file(lint.project_root.join(test_path), test_contents)
     }
 }
@@ -119,8 +120,8 @@ fn to_camel_case(name: &str) -> String {
         .collect()
 }
 
-fn get_test_file_contents(lint_name: &str) -> String {
-    format!(
+fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String {
+    let mut contents = format!(
         "#![warn(clippy::{})]
 
 fn main() {{
@@ -128,7 +129,13 @@ fn main() {{
 }}
 ",
         lint_name
-    )
+    );
+
+    if let Some(header) = header_commands {
+        contents = format!("{}\n{}", header, contents);
+    }
+
+    contents
 }
 
 fn get_manifest_contents(lint_name: &str, hint: &str) -> String {
diff --git a/clippy_lints/src/multiple_crate_versions.rs b/clippy_lints/src/multiple_crate_versions.rs
index c4decfc9401..b6770804e18 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! {
@@ -39,32 +42,61 @@ impl LateLintPass<'_, '_> for MultipleCrateVersions {
             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<cargo_metadata::Package> = group.collect();
+        if_chain! {
+            if let Some(resolve) = &metadata.resolve;
+            if let Some(local_id) = packages
+                .iter()
+                .find_map(|p| if p.name == *local_name { Some(&p.id) } else { None });
+            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/cargo_common_metadata/fail/src/main.rs b/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs
index c67166fc4b0..27841e18aa9 100644
--- a/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs
+++ b/tests/ui-cargo/cargo_common_metadata/fail/src/main.rs
@@ -1,3 +1,4 @@
+// compile-flags: --crate-name=cargo_common_metadata
 #![warn(clippy::cargo_common_metadata)]
 
 fn main() {}
diff --git a/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs b/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs
index c67166fc4b0..27841e18aa9 100644
--- a/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs
+++ b/tests/ui-cargo/cargo_common_metadata/pass/src/main.rs
@@ -1,3 +1,4 @@
+// compile-flags: --crate-name=cargo_common_metadata
 #![warn(clippy::cargo_common_metadata)]
 
 fn main() {}
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() {}
diff --git a/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs b/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs
index 4bc61dd6299..1b2d3ec9459 100644
--- a/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs
+++ b/tests/ui-cargo/multiple_crate_versions/fail/src/main.rs
@@ -1,3 +1,4 @@
+// compile-flags: --crate-name=multiple_crate_versions
 #![warn(clippy::multiple_crate_versions)]
 
 fn main() {}
diff --git a/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs b/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs
index 4bc61dd6299..1b2d3ec9459 100644
--- a/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs
+++ b/tests/ui-cargo/multiple_crate_versions/pass/src/main.rs
@@ -1,3 +1,4 @@
+// compile-flags: --crate-name=multiple_crate_versions
 #![warn(clippy::multiple_crate_versions)]
 
 fn main() {}
diff --git a/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs b/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs
index 3491ccb0d47..581babfeacb 100644
--- a/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs
+++ b/tests/ui-cargo/wildcard_dependencies/fail/src/main.rs
@@ -1,3 +1,4 @@
+// compile-flags: --crate-name=wildcard_dependencies
 #![warn(clippy::wildcard_dependencies)]
 
 fn main() {}
diff --git a/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs b/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs
index 3491ccb0d47..581babfeacb 100644
--- a/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs
+++ b/tests/ui-cargo/wildcard_dependencies/pass/src/main.rs
@@ -1,3 +1,4 @@
+// compile-flags: --crate-name=wildcard_dependencies
 #![warn(clippy::wildcard_dependencies)]
 
 fn main() {}