Fix false positive in empty_line_after_outer_attr

Before, when you had a block comment between an attribute and the
following item like this:

```rust
\#[crate_type = "lib"]
/*

*/
pub struct Rust;
```

It would cause a false positive on the lint, because there is an empty
line inside the block comment.

This makes sure that basic block comments are detected and removed from
the snippet that was created before.
This commit is contained in:
Philipp Hansch 2018-03-29 21:14:53 +02:00
parent b45801ff19
commit b7929cafe1
No known key found for this signature in database
GPG key ID: 93FB33459D311E5E
4 changed files with 64 additions and 1 deletions

View file

@ -7,7 +7,7 @@ use rustc::ty::{self, TyCtxt};
use semver::Version; use semver::Version;
use syntax::ast::{Attribute, AttrStyle, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::ast::{Attribute, AttrStyle, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
use syntax::codemap::Span; use syntax::codemap::Span;
use utils::{in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then}; use utils::{in_macro, last_line_of_span, match_def_path, opt_def_id, paths, snippet_opt, span_lint, span_lint_and_then, without_block_comments};
/// **What it does:** Checks for items annotated with `#[inline(always)]`, /// **What it does:** Checks for items annotated with `#[inline(always)]`,
/// unless the annotated function is empty or simply panics. /// unless the annotated function is empty or simply panics.
@ -276,6 +276,8 @@ fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) {
if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) { if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) {
let lines = snippet.split('\n').collect::<Vec<_>>(); let lines = snippet.split('\n').collect::<Vec<_>>();
let lines = without_block_comments(lines);
if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 { if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
span_lint( span_lint(
cx, cx,

View file

@ -1086,3 +1086,37 @@ pub fn clip(tcx: TyCtxt, u: u128, ity: ast::UintTy) -> u128 {
let amt = 128 - bits; let amt = 128 - bits;
(u << amt) >> amt (u << amt) >> amt
} }
/// Remove block comments from the given Vec of lines
///
/// # Examples
///
/// ```rust,ignore
/// without_block_comments(vec!["/*", "foo", "*/"]);
/// // => vec![]
///
/// without_block_comments(vec!["bar", "/*", "foo", "*/"]);
/// // => vec!["bar"]
/// ```
pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> {
let mut without = vec![];
// naive approach for block comments
let mut inside_comment = false;
for line in lines.into_iter() {
if line.contains("/*") {
inside_comment = true;
continue;
} else if line.contains("*/") {
inside_comment = false;
continue;
}
if !inside_comment {
without.push(line);
}
}
without
}

View file

@ -79,4 +79,11 @@ pub enum FooFighter {
Bar4 Bar4
} }
// This should not produce a warning because there is a comment in between
#[crate_type = "lib"]
/*
*/
pub struct S;
fn main() { } fn main() { }

View file

@ -0,0 +1,20 @@
extern crate clippy_lints;
use clippy_lints::utils::without_block_comments;
#[test]
fn test_lines_without_block_comments() {
let result = without_block_comments(vec!["/*", "", "*/"]);
println!("result: {:?}", result);
assert!(result.is_empty());
let result = without_block_comments(
vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]
);
assert_eq!(result, vec!["", "#[crate_type = \"lib\"]", ""]);
let result = without_block_comments(vec!["/* rust", "", "*/"]);
assert!(result.is_empty());
let result = without_block_comments(vec!["foo", "bar", "baz"]);
assert_eq!(result, vec!["foo", "bar", "baz"]);
}