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(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::::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::::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