Skip to content

Commit 77997d8

Browse files
committed
Warn on empty lines after outer attributes
1 parent 18f3f0d commit 77997d8

File tree

4 files changed

+92
-2
lines changed

4 files changed

+92
-2
lines changed

clippy_lints/src/attrs.rs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc::lint::*;
55
use rustc::hir::*;
66
use rustc::ty::{self, TyCtxt};
77
use semver::Version;
8-
use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
8+
use syntax::ast::{Attribute, AttrStyle, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
99
use syntax::codemap::Span;
1010
use utils::{in_macro, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then};
1111

@@ -78,12 +78,44 @@ declare_lint! {
7878
"use of `#[deprecated(since = \"x\")]` where x is not semver"
7979
}
8080

81+
/// **What it does:** Checks for empty lines after outer attributes
82+
///
83+
/// **Why is this bad?**
84+
/// Most likely the attribute was meant to be an inner attribute using a '!'.
85+
/// If it was meant to be an outer attribute, then the following item,
86+
/// should not be separated by empty lines.
87+
///
88+
/// **Known problems:** None
89+
///
90+
/// **Example:**
91+
/// ```rust
92+
/// // Bad
93+
/// #[inline(always)]
94+
///
95+
/// fn not_quite_good_code(..) { ... }
96+
///
97+
/// // Good (as inner attribute)
98+
/// #![inline(always)]
99+
///
100+
/// fn this_is_fine_too(..) { ... }
101+
///
102+
/// // Good (as outer attribute)
103+
/// #[inline(always)]
104+
/// fn this_is_fine(..) { ... }
105+
///
106+
/// ```
107+
declare_lint! {
108+
pub EMPTY_LINE_AFTER_OUTER_ATTR,
109+
Warn,
110+
"empty line after outer attribute"
111+
}
112+
81113
#[derive(Copy, Clone)]
82114
pub struct AttrPass;
83115

84116
impl LintPass for AttrPass {
85117
fn get_lints(&self) -> LintArray {
86-
lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER, USELESS_ATTRIBUTE)
118+
lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER, USELESS_ATTRIBUTE, EMPTY_LINE_AFTER_OUTER_ATTR)
87119
}
88120
}
89121

@@ -230,6 +262,23 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) {
230262
}
231263

232264
for attr in attrs {
265+
if attr.style == AttrStyle::Outer {
266+
let attr_to_item_span = Span::new(attr.span.lo(), span.lo(), span.ctxt());
267+
268+
if let Some(snippet) = snippet_opt(cx, attr_to_item_span) {
269+
let lines = snippet.split('\n').collect::<Vec<_>>();
270+
if lines.iter().filter(|l| l.trim().is_empty()).count() > 1 {
271+
span_lint(
272+
cx,
273+
EMPTY_LINE_AFTER_OUTER_ATTR,
274+
attr_to_item_span,
275+
&format!("Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?")
276+
);
277+
278+
}
279+
}
280+
}
281+
233282
if let Some(ref values) = attr.meta_item_list() {
234283
if values.len() != 1 || attr.name().map_or(true, |n| n != "inline") {
235284
continue;

clippy_lints/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
427427
attrs::DEPRECATED_SEMVER,
428428
attrs::INLINE_ALWAYS,
429429
attrs::USELESS_ATTRIBUTE,
430+
attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
430431
bit_mask::BAD_BIT_MASK,
431432
bit_mask::INEFFECTIVE_BIT_MASK,
432433
bit_mask::VERBOSE_BIT_MASK,
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
#![warn(empty_line_after_outer_attr)]
3+
4+
// This should produce a warning
5+
#[crate_type = "lib"]
6+
7+
fn with_one_newline() { assert!(true) }
8+
9+
// This should produce a warning, too
10+
#[crate_type = "lib"]
11+
12+
13+
fn with_two_newlines() { assert!(true) }
14+
15+
// This should not produce a warning
16+
#[allow(non_camel_case_types)]
17+
#[allow(missing_docs)]
18+
#[allow(missing_docs)]
19+
fn three_attributes() { assert!(true) }
20+
21+
fn main() { }
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?
2+
--> $DIR/empty_line_after_outer_attribute.rs:5:1
3+
|
4+
5 | / #[crate_type = "lib"]
5+
6 | |
6+
7 | | fn with_one_newline() { assert!(true) }
7+
| |_
8+
|
9+
= note: `-D empty-line-after-outer-attr` implied by `-D warnings`
10+
11+
error: Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?
12+
--> $DIR/empty_line_after_outer_attribute.rs:10:1
13+
|
14+
10 | / #[crate_type = "lib"]
15+
11 | |
16+
12 | |
17+
13 | | fn with_two_newlines() { assert!(true) }
18+
| |_
19+

0 commit comments

Comments
 (0)