Lint for multiple versions of dependencies

This commit is contained in:
Yusuf Simonson 2018-04-30 06:20:39 +07:00
parent 1742229ebb
commit 7de706b34b
6 changed files with 86 additions and 0 deletions

View file

@ -17,6 +17,7 @@ We have a bunch of lint categories to allow you to choose how much clippy is sup
* `clippy_style` (code that should be written in a more idiomatic way)
* `clippy_complexity` (code that does something simple but in a complex way)
* `clippy_perf` (code that can be written in a faster way)
* `clippy_cargo` (checks against the cargo manifest)
* **`clippy_correctness`** (code that is just outright wrong or very very useless)
More to come, please [file an issue](https://github.com/rust-lang-nursery/rust-clippy/issues) if you have ideas!

View file

@ -16,6 +16,7 @@ license = "MPL-2.0"
keywords = ["clippy", "lint", "plugin"]
[dependencies]
cargo_metadata = "0.5"
itertools = "0.7"
lazy_static = "1.0"
matches = "0.1.2"

View file

@ -16,6 +16,7 @@
#![feature(iterator_find_map)]
extern crate cargo_metadata;
#[macro_use]
extern crate rustc;
extern crate rustc_typeck;
@ -81,6 +82,9 @@ macro_rules! declare_clippy_lint {
{ pub $name:tt, restriction, $description:tt } => {
declare_lint! { pub $name, Allow, $description }
};
{ pub $name:tt, cargo, $description:tt } => {
declare_lint! { pub $name, Allow, $description }
};
{ pub $name:tt, nursery, $description:tt } => {
declare_lint! { pub $name, Allow, $description }
};
@ -158,6 +162,7 @@ pub mod minmax;
pub mod misc;
pub mod misc_early;
pub mod missing_doc;
pub mod multiple_crate_versions;
pub mod mut_mut;
pub mod mut_reference;
pub mod mutex_atomic;
@ -412,6 +417,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
reg.register_late_lint_pass(box question_mark::QuestionMarkPass);
reg.register_late_lint_pass(box suspicious_trait_impl::SuspiciousImpl);
reg.register_late_lint_pass(box redundant_field_names::RedundantFieldNames);
reg.register_early_lint_pass(box multiple_crate_versions::Pass);
reg.register_late_lint_pass(box map_unit_fn::Pass);
reg.register_late_lint_pass(box infallible_destructuring_match::Pass);
@ -895,6 +901,10 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
vec::USELESS_VEC,
]);
reg.register_lint_group("clippy_cargo", vec![
multiple_crate_versions::MULTIPLE_CRATE_VERSIONS,
]);
reg.register_lint_group("clippy_nursery", vec![
attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
fallible_impl_from::FALLIBLE_IMPL_FROM,

View file

@ -0,0 +1,72 @@
//! lint on multiple versions of a crate being used
use rustc::lint::*;
use syntax::ast::*;
use cargo_metadata;
use itertools::Itertools;
/// **What it does:** Checks to see if multiple versions of a crate are being
/// used.
///
/// **Why is this bad?** This bloats the size of targets, and can lead to
/// confusing error messages when structs or traits are used interchangeably
/// between different versions of a crate.
///
/// **Known problems:** Because this can be caused purely by the dependencies
/// themselves, it's not always possible to fix this issue.
///
/// **Example:**
/// ```toml
/// # This will pull in both winapi v0.3.4 and v0.2.8, triggering a warning.
/// [dependencies]
/// ctrlc = "3.1.0"
/// ansi_term = "0.11.0"
/// ```
declare_clippy_lint! {
pub MULTIPLE_CRATE_VERSIONS,
cargo,
"multiple versions of the same crate being used"
}
pub struct Pass;
impl LintPass for Pass {
fn get_lints(&self) -> LintArray {
lint_array!(MULTIPLE_CRATE_VERSIONS)
}
}
impl EarlyLintPass for Pass {
fn check_crate(&mut self, cx: &EarlyContext, krate: &Crate) {
let metadata = match cargo_metadata::metadata_deps(None, true) {
Ok(metadata) => metadata,
Err(_) => {
cx.span_lint(
MULTIPLE_CRATE_VERSIONS,
krate.span,
"could not read cargo metadata"
);
return;
}
};
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 group.len() > 1 {
let versions = group.into_iter().map(|p| p.version).join(", ");
cx.span_lint(
MULTIPLE_CRATE_VERSIONS,
krate.span,
&format!("multiple versions for dependency `{}`: {}", name, versions),
);
}
}
}
}

View file

@ -24,6 +24,7 @@ lint_levels = {
"restriction": 'Allow',
"pedantic": 'Allow',
"nursery": 'Allow',
"cargo": 'Allow',
}

View file

@ -129,6 +129,7 @@ def main(print_only=False, check=False):
"perf": [],
"restriction": [],
"pedantic": [],
"cargo": [],
"nursery": [],
}