From ac77a26b8a03582d072989b6af7889902bd7428a Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Thu, 19 Jul 2018 13:44:26 +0200 Subject: [PATCH] Skip useless_attribute lint on allow(unused_imports) on extern crate items with macro_use --- clippy_lints/src/attrs.rs | 44 ++++++++++++++++++++++++----------- tests/ui/useless_attribute.rs | 2 ++ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 5d5e2f964..367968cfe 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -39,22 +39,31 @@ declare_clippy_lint! { } /// **What it does:** Checks for `extern crate` and `use` items annotated with -/// lint attributes +/// lint attributes. +/// +/// This lint whitelists `#[allow(unused_imports)]` and `#[allow(deprecated)]` on +/// `use` items and `#[allow(unused_imports)]` on `extern crate` items with a +/// `#[macro_use]` attribute. /// /// **Why is this bad?** Lint attributes have no effect on crate imports. Most -/// likely a `!` was -/// forgotten +/// likely a `!` was forgotten. /// -/// **Known problems:** Technically one might allow `unused_import` on a `use` -/// item, -/// but it's easier to remove the unused item. +/// **Known problems:** None. /// /// **Example:** /// ```rust +/// // Bad /// #[deny(dead_code)] /// extern crate foo; -/// #[allow(unused_import)] +/// #[forbid(dead_code)] /// use foo::bar; +/// +/// // Ok +/// #[allow(unused_imports)] +/// use foo::baz; +/// #[allow(unused_imports)] +/// #[macro_use] +/// extern crate baz; /// ``` declare_clippy_lint! { pub USELESS_ATTRIBUTE, @@ -154,17 +163,26 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { check_attrs(cx, item.span, item.name, &item.attrs) } match item.node { - ItemKind::ExternCrate(_) | ItemKind::Use(_, _) => { + ItemKind::ExternCrate(..) | ItemKind::Use(..) => { + let skip_unused_imports = item.attrs.iter().any(|attr| attr.name() == "macro_use"); + for attr in &item.attrs { if let Some(ref lint_list) = attr.meta_item_list() { match &*attr.name().as_str() { "allow" | "warn" | "deny" | "forbid" => { - // whitelist `unused_imports` and `deprecated` + // whitelist `unused_imports` and `deprecated` for `use` items + // and `unused_imports` for `extern crate` items with `macro_use` for lint in lint_list { - if is_word(lint, "unused_imports") || is_word(lint, "deprecated") { - if let ItemKind::Use(_, _) = item.node { - return; - } + match item.node { + ItemKind::Use(..) => if is_word(lint, "unused_imports") + || is_word(lint, "deprecated") { + return + }, + ItemKind::ExternCrate(..) => if is_word(lint, "unused_imports") + && skip_unused_imports { + return + }, + _ => {}, } } let line_span = last_line_of_span(cx, attr.span); diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 217e886c8..68c7d2007 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -6,6 +6,8 @@ #[cfg_attr(feature = "cargo-clippy", allow(dead_code, unused_extern_crates))] #[cfg_attr(feature = "cargo-clippy", allow(dead_code, unused_extern_crates))] +#[allow(unused_imports)] +#[macro_use] extern crate clippy_lints; // don't lint on unused_import for `use` items