Skip to content

Fix empty_line_after_outer_attribute false positive #8892

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ filetime = "0.2"
rustc-workspace-hack = "1.0"

# UI test dependencies
clap = { version = "3.1", features = ["derive"] }
clippy_utils = { path = "clippy_utils" }
derive-new = "0.5"
if_chain = "1.0"
Expand Down
23 changes: 18 additions & 5 deletions clippy_lints/src/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,15 +585,21 @@ impl EarlyLintPass for EarlyAttributes {
}

fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
for attr in &item.attrs {
let mut iter = item.attrs.iter().peekable();
while let Some(attr) = iter.next() {
if matches!(attr.kind, AttrKind::Normal(..))
&& attr.style == AttrStyle::Outer
&& is_present_in_source(cx, attr.span)
{
let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent());
let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt(), item.span.parent());
let end_of_attr_to_next_attr_or_item = Span::new(
attr.span.hi(),
iter.peek().map_or(item.span.lo(), |next_attr| next_attr.span.lo()),
item.span.ctxt(),
item.span.parent(),
);

if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) {
if let Some(snippet) = snippet_opt(cx, end_of_attr_to_next_attr_or_item) {
let lines = snippet.split('\n').collect::<Vec<_>>();
let lines = without_block_comments(lines);

Expand Down Expand Up @@ -623,8 +629,15 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: Opti
if feature_item.has_name(sym::rustfmt);
// check for `rustfmt_skip` and `rustfmt::skip`
if let Some(skip_item) = &items[1].meta_item();
if skip_item.has_name(sym!(rustfmt_skip)) ||
skip_item.path.segments.last().expect("empty path in attribute").ident.name == sym::skip;
if skip_item.has_name(sym!(rustfmt_skip))
|| skip_item
.path
.segments
.last()
.expect("empty path in attribute")
.ident
.name
== sym::skip;
// Only lint outer attributes, because custom inner attributes are unstable
// Tracking issue: https://github.com/rust-lang/rust/issues/54726
if attr.style == AttrStyle::Outer;
Expand Down
8 changes: 6 additions & 2 deletions tests/compile-test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal");

/// All crates used in UI tests are listed here
static TEST_DEPENDENCIES: &[&str] = &[
"clap",
"clippy_utils",
"derive_new",
"futures",
Expand All @@ -40,6 +41,8 @@ static TEST_DEPENDENCIES: &[&str] = &[
// Test dependencies may need an `extern crate` here to ensure that they show up
// in the depinfo file (otherwise cargo thinks they are unused)
#[allow(unused_extern_crates)]
extern crate clap;
#[allow(unused_extern_crates)]
extern crate clippy_utils;
#[allow(unused_extern_crates)]
extern crate derive_new;
Expand Down Expand Up @@ -109,8 +112,9 @@ static EXTERN_FLAGS: SyncLazy<String> = SyncLazy::new(|| {
not_found.is_empty(),
"dependencies not found in depinfo: {:?}\n\
help: Make sure the `-Z binary-dep-depinfo` rust flag is enabled\n\
help: Try adding to dev-dependencies in Cargo.toml",
not_found
help: Try adding to dev-dependencies in Cargo.toml\n\
help: Be sure to also add `extern crate ...;` to tests/compile-test.rs",
not_found,
);
crates
.into_iter()
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/empty_line_after_outer_attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#![feature(custom_inner_attributes)]
#![rustfmt::skip]

#[macro_use]
extern crate clap;

#[macro_use]
extern crate proc_macro_attr;

Expand Down Expand Up @@ -110,4 +113,11 @@ pub trait Bazz {
}
}

#[derive(clap::Parser)]
#[clap(after_help = "This ia a help message.
You're welcome.
")]
pub struct Args;

fn main() {}
12 changes: 6 additions & 6 deletions tests/ui/empty_line_after_outer_attribute.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
--> $DIR/empty_line_after_outer_attribute.rs:11:1
--> $DIR/empty_line_after_outer_attribute.rs:14:1
|
LL | / #[crate_type = "lib"]
LL | |
Expand All @@ -10,15 +10,15 @@ LL | | fn with_one_newline_and_comment() { assert!(true) }
= note: `-D clippy::empty-line-after-outer-attr` implied by `-D warnings`

error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
--> $DIR/empty_line_after_outer_attribute.rs:23:1
--> $DIR/empty_line_after_outer_attribute.rs:26:1
|
LL | / #[crate_type = "lib"]
LL | |
LL | | fn with_one_newline() { assert!(true) }
| |_

error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
--> $DIR/empty_line_after_outer_attribute.rs:28:1
--> $DIR/empty_line_after_outer_attribute.rs:31:1
|
LL | / #[crate_type = "lib"]
LL | |
Expand All @@ -27,23 +27,23 @@ LL | | fn with_two_newlines() { assert!(true) }
| |_

error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
--> $DIR/empty_line_after_outer_attribute.rs:35:1
--> $DIR/empty_line_after_outer_attribute.rs:38:1
|
LL | / #[crate_type = "lib"]
LL | |
LL | | enum Baz {
| |_

error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
--> $DIR/empty_line_after_outer_attribute.rs:43:1
--> $DIR/empty_line_after_outer_attribute.rs:46:1
|
LL | / #[crate_type = "lib"]
LL | |
LL | | struct Foo {
| |_

error: found an empty line after an outer attribute. Perhaps you forgot to add a `!` to make it an inner attribute?
--> $DIR/empty_line_after_outer_attribute.rs:51:1
--> $DIR/empty_line_after_outer_attribute.rs:54:1
|
LL | / #[crate_type = "lib"]
LL | |
Expand Down