diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 5b88494ae..d66e2b5f8 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -4,7 +4,7 @@ use crate::utils::{get_attr, higher}; use rustc::hir; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; -use rustc::hir::{BindingAnnotation, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; +use rustc::hir::{BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::session::Session; use rustc::{declare_lint_pass, declare_tool_lint}; @@ -511,6 +511,17 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { } } + fn visit_block(&mut self, block: &Block) { + let trailing_pat = self.next("trailing_expr"); + println!(" if let Some({}) = &{}.expr;", trailing_pat, self.current); + println!(" if {}.stmts.len() == {};", self.current, block.stmts.len()); + let current = self.current.clone(); + for (i, stmt) in block.stmts.iter().enumerate() { + self.current = format!("{}.stmts[{}]", current, i); + self.visit_stmt(stmt); + } + } + #[allow(clippy::too_many_lines)] fn visit_pat(&mut self, pat: &Pat) { print!(" if let PatKind::"); diff --git a/tests/ui/author/blocks.rs b/tests/ui/author/blocks.rs new file mode 100644 index 000000000..c7d173388 --- /dev/null +++ b/tests/ui/author/blocks.rs @@ -0,0 +1,15 @@ +#![feature(stmt_expr_attributes)] + +#[rustfmt::skip] +fn main() { + #[clippy::author] + { + ;;;; + } +} + +#[clippy::author] +fn foo() { + let x = 42i32; + -x; +} diff --git a/tests/ui/author/blocks.stderr b/tests/ui/author/blocks.stderr new file mode 100644 index 000000000..a54a1422d --- /dev/null +++ b/tests/ui/author/blocks.stderr @@ -0,0 +1,10 @@ +error: statement with no effect + --> $DIR/blocks.rs:14:5 + | +LL | -x; + | ^^^ + | + = note: `-D clippy::no-effect` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/author/blocks.stdout b/tests/ui/author/blocks.stdout new file mode 100644 index 000000000..0128b3b02 --- /dev/null +++ b/tests/ui/author/blocks.stdout @@ -0,0 +1,13 @@ +if_chain! { + if let ExprKind::Block(ref block) = expr.node; + if let Some(trailing_expr) = &block.expr; + if block.stmts.len() == 0; + then { + // report your lint here + } +} +if_chain! { + then { + // report your lint here + } +} diff --git a/tests/ui/author/for_loop.stdout b/tests/ui/author/for_loop.stdout index a9651c2f7..7ce04e44b 100644 --- a/tests/ui/author/for_loop.stdout +++ b/tests/ui/author/for_loop.stdout @@ -11,10 +11,12 @@ if_chain! { // unimplemented: field checks if arms.len() == 1; if let ExprKind::Loop(ref body, ref label, LoopSource::ForLoop) = arms[0].body.node; - if let StmtKind::Local(ref local) = body.node; + if let Some(trailing_expr) = &body.expr; + if body.stmts.len() == 4; + if let StmtKind::Local(ref local) = body.stmts[0].node; if let PatKind::Binding(BindingAnnotation::Mutable, _, name, None) = local.pat.node; if name.node.as_str() == "__next"; - if let StmtKind::Expr(ref e, _) = local.pat.node + if let StmtKind::Expr(ref e, _) = body.stmts[1].node if let ExprKind::Match(ref expr2, ref arms1, MatchSource::ForLoopDesugar) = e.node; if let ExprKind::Call(ref func1, ref args1) = expr2.node; if let ExprKind::Path(ref path2) = func1.node; @@ -38,15 +40,17 @@ if_chain! { if arms1[1].pats.len() == 1; if let PatKind::Path(ref path7) = arms1[1].pats[0].node; if match_qpath(path7, &["{{root}}", "std", "option", "Option", "None"]); - if let StmtKind::Local(ref local1) = path7.node; + if let StmtKind::Local(ref local1) = body.stmts[2].node; if let Some(ref init) = local1.init; if let ExprKind::Path(ref path8) = init.node; if match_qpath(path8, &["__next"]); if let PatKind::Binding(BindingAnnotation::Unannotated, _, name1, None) = local1.pat.node; if name1.node.as_str() == "y"; - if let StmtKind::Expr(ref e1, _) = local1.pat.node + if let StmtKind::Expr(ref e1, _) = body.stmts[3].node if let ExprKind::Block(ref block) = e1.node; - if let StmtKind::Local(ref local2) = block.node; + if let Some(trailing_expr1) = &block.expr; + if block.stmts.len() == 1; + if let StmtKind::Local(ref local2) = block.stmts[0].node; if let Some(ref init1) = local2.init; if let ExprKind::Path(ref path9) = init1.node; if match_qpath(path9, &["y"]); diff --git a/tests/ui/author/if.stdout b/tests/ui/author/if.stdout index bff6546a9..be8260007 100644 --- a/tests/ui/author/if.stdout +++ b/tests/ui/author/if.stdout @@ -3,7 +3,9 @@ if_chain! { if let Some(ref init) = local.init; if let Some((ref cond, ref then, Some(else_))) = higher::if_block(&init); if let ExprKind::Block(ref block) = else_.node; - if let StmtKind::Semi(ref e, _) = block.node + if let Some(trailing_expr) = &block.expr; + if block.stmts.len() == 1; + if let StmtKind::Semi(ref e, _) = block.stmts[0].node if let ExprKind::Binary(ref op, ref left, ref right) = e.node; if BinOpKind::Eq == op.node; if let ExprKind::Lit(ref lit) = left.node; @@ -13,7 +15,9 @@ if_chain! { if let ExprKind::Lit(ref lit2) = cond.node; if let LitKind::Bool(true) = lit2.node; if let ExprKind::Block(ref block1) = then.node; - if let StmtKind::Semi(ref e1, _) = block1.node + if let Some(trailing_expr1) = &block1.expr; + if block1.stmts.len() == 1; + if let StmtKind::Semi(ref e1, _) = block1.stmts[0].node if let ExprKind::Binary(ref op1, ref left1, ref right1) = e1.node; if BinOpKind::Eq == op1.node; if let ExprKind::Lit(ref lit3) = left1.node;