Skip to content

Commit

Permalink
Warn on empty lines after outer attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
phansch committed Jan 8, 2018
1 parent 18f3f0d commit 77997d8
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 2 deletions.
53 changes: 51 additions & 2 deletions clippy_lints/src/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc::lint::*;
use rustc::hir::*;
use rustc::ty::{self, TyCtxt};
use semver::Version;
use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
use syntax::ast::{Attribute, AttrStyle, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
use syntax::codemap::Span;
use utils::{in_macro, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then};

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

/// **What it does:** Checks for empty lines after outer attributes
///
/// **Why is this bad?**
/// Most likely the attribute was meant to be an inner attribute using a '!'.
/// If it was meant to be an outer attribute, then the following item,
/// should not be separated by empty lines.
///
/// **Known problems:** None
///
/// **Example:**
/// ```rust
/// // Bad
/// #[inline(always)]
///
/// fn not_quite_good_code(..) { ... }
///
/// // Good (as inner attribute)
/// #![inline(always)]
///
/// fn this_is_fine_too(..) { ... }
///
/// // Good (as outer attribute)
/// #[inline(always)]
/// fn this_is_fine(..) { ... }
///
/// ```
declare_lint! {
pub EMPTY_LINE_AFTER_OUTER_ATTR,
Warn,
"empty line after outer attribute"
}

#[derive(Copy, Clone)]
pub struct AttrPass;

impl LintPass for AttrPass {
fn get_lints(&self) -> LintArray {
lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER, USELESS_ATTRIBUTE)
lint_array!(INLINE_ALWAYS, DEPRECATED_SEMVER, USELESS_ATTRIBUTE, EMPTY_LINE_AFTER_OUTER_ATTR)
}
}

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

for attr in attrs {
if attr.style == AttrStyle::Outer {
let attr_to_item_span = Span::new(attr.span.lo(), span.lo(), span.ctxt());

if let Some(snippet) = snippet_opt(cx, attr_to_item_span) {
let lines = snippet.split('\n').collect::<Vec<_>>();
if lines.iter().filter(|l| l.trim().is_empty()).count() > 1 {
span_lint(
cx,
EMPTY_LINE_AFTER_OUTER_ATTR,
attr_to_item_span,
&format!("Found an empty line after an outer attribute. Perhaps you forgot to add a '!' to make it an inner attribute?")
);

}
}
}

if let Some(ref values) = attr.meta_item_list() {
if values.len() != 1 || attr.name().map_or(true, |n| n != "inline") {
continue;
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
attrs::DEPRECATED_SEMVER,
attrs::INLINE_ALWAYS,
attrs::USELESS_ATTRIBUTE,
attrs::EMPTY_LINE_AFTER_OUTER_ATTR,
bit_mask::BAD_BIT_MASK,
bit_mask::INEFFECTIVE_BIT_MASK,
bit_mask::VERBOSE_BIT_MASK,
Expand Down
21 changes: 21 additions & 0 deletions tests/ui/empty_line_after_outer_attribute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

#![warn(empty_line_after_outer_attr)]

// This should produce a warning
#[crate_type = "lib"]

fn with_one_newline() { assert!(true) }

// This should produce a warning, too
#[crate_type = "lib"]


fn with_two_newlines() { assert!(true) }

// This should not produce a warning
#[allow(non_camel_case_types)]
#[allow(missing_docs)]
#[allow(missing_docs)]
fn three_attributes() { assert!(true) }

fn main() { }
19 changes: 19 additions & 0 deletions tests/ui/empty_line_after_outer_attribute.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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:5:1
|
5 | / #[crate_type = "lib"]
6 | |
7 | | fn with_one_newline() { assert!(true) }
| |_
|
= note: `-D 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:10:1
|
10 | / #[crate_type = "lib"]
11 | |
12 | |
13 | | fn with_two_newlines() { assert!(true) }
| |_

0 comments on commit 77997d8

Please sign in to comment.