about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/utils/mod.rs13
-rw-r--r--tests/ui/useless_attribute.fixed57
-rw-r--r--tests/ui/useless_attribute.rs12
-rw-r--r--tests/ui/useless_attribute.stderr12
4 files changed, 88 insertions, 6 deletions
diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index 1e6a57c6dfc..e304d980098 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/clippy_lints/src/utils/mod.rs
@@ -42,8 +42,8 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::Node;
 use rustc_hir::*;
 use rustc_span::hygiene::ExpnKind;
-use rustc_span::source_map::{Span, DUMMY_SP};
 use rustc_span::symbol::{kw, Symbol};
+use rustc_span::{BytePos, Pos, Span, DUMMY_SP};
 use smallvec::SmallVec;
 use syntax::ast::{self, Attribute, LitKind};
 use syntax::attr;
@@ -554,7 +554,16 @@ pub fn last_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span {
     let source_map_and_line = cx.sess().source_map().lookup_line(span.lo()).unwrap();
     let line_no = source_map_and_line.line;
     let line_start = &source_map_and_line.sf.lines[line_no];
-    Span::new(*line_start, span.hi(), span.ctxt())
+    let span = Span::new(*line_start, span.hi(), span.ctxt());
+    if_chain! {
+        if let Some(snip) = snippet_opt(cx, span);
+        if let Some(first_ch_pos) = snip.find(|c: char| !c.is_whitespace());
+        then {
+            span.with_lo(span.lo() + BytePos::from_usize(first_ch_pos))
+        } else {
+            span
+        }
+    }
 }
 
 /// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed
new file mode 100644
index 00000000000..56811a99872
--- /dev/null
+++ b/tests/ui/useless_attribute.fixed
@@ -0,0 +1,57 @@
+// run-rustfix
+// aux-build:proc_macro_derive.rs
+
+#![warn(clippy::useless_attribute)]
+#![warn(unreachable_pub)]
+#![feature(rustc_private)]
+
+#![allow(dead_code)]
+#![cfg_attr(feature = "cargo-clippy", allow(dead_code))]
+#[rustfmt::skip]
+#[allow(unused_imports)]
+#[allow(unused_extern_crates)]
+#[macro_use]
+extern crate rustc;
+
+#[macro_use]
+extern crate proc_macro_derive;
+
+// don't lint on unused_import for `use` items
+#[allow(unused_imports)]
+use std::collections;
+
+// don't lint on deprecated for `use` items
+mod foo {
+    #[deprecated]
+    pub struct Bar;
+}
+#[allow(deprecated)]
+pub use foo::Bar;
+
+// This should not trigger the lint. There's lint level definitions inside the external derive
+// that would trigger the useless_attribute lint.
+#[derive(DeriveSomething)]
+struct Baz;
+
+// don't lint on unreachable_pub for `use` items
+mod a {
+    mod b {
+        #[allow(dead_code)]
+        #[allow(unreachable_pub)]
+        pub struct C {}
+    }
+
+    #[allow(unreachable_pub)]
+    pub use self::b::C;
+}
+
+fn test_indented_attr() {
+    #![allow(clippy::almost_swapped)]
+    use std::collections::HashSet;
+
+    let _ = HashSet::<u32>::default();
+}
+
+fn main() {
+    test_indented_attr();
+}
diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs
index 529680a7588..bbf5e495db4 100644
--- a/tests/ui/useless_attribute.rs
+++ b/tests/ui/useless_attribute.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 // aux-build:proc_macro_derive.rs
 
 #![warn(clippy::useless_attribute)]
@@ -44,4 +45,13 @@ mod a {
     pub use self::b::C;
 }
 
-fn main() {}
+fn test_indented_attr() {
+    #[allow(clippy::almost_swapped)]
+    use std::collections::HashSet;
+
+    let _ = HashSet::<u32>::default();
+}
+
+fn main() {
+    test_indented_attr();
+}
diff --git a/tests/ui/useless_attribute.stderr b/tests/ui/useless_attribute.stderr
index 87a1291543e..08a211b41a9 100644
--- a/tests/ui/useless_attribute.stderr
+++ b/tests/ui/useless_attribute.stderr
@@ -1,5 +1,5 @@
 error: useless lint attribute
-  --> $DIR/useless_attribute.rs:7:1
+  --> $DIR/useless_attribute.rs:8:1
    |
 LL | #[allow(dead_code)]
    | ^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(dead_code)]`
@@ -7,10 +7,16 @@ LL | #[allow(dead_code)]
    = note: `-D clippy::useless-attribute` implied by `-D warnings`
 
 error: useless lint attribute
-  --> $DIR/useless_attribute.rs:8:1
+  --> $DIR/useless_attribute.rs:9:1
    |
 LL | #[cfg_attr(feature = "cargo-clippy", allow(dead_code))]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![cfg_attr(feature = "cargo-clippy", allow(dead_code)`
 
-error: aborting due to 2 previous errors
+error: useless lint attribute
+  --> $DIR/useless_attribute.rs:49:5
+   |
+LL |     #[allow(clippy::almost_swapped)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you just forgot a `!`, use: `#![allow(clippy::almost_swapped)]`
+
+error: aborting due to 3 previous errors