diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index eadc672e56b..c824c8906a7 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -288,16 +288,27 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { self.current = then_pat; self.visit_expr(then); }, - Expr_::ExprWhile(ref _cond, ref _body, ref _opt_label) => { - println!("While(ref cond, ref body, ref opt_label) = {};", current); - println!(" // unimplemented: `ExprWhile` is not further destructured at the moment"); + Expr_::ExprWhile(ref cond, ref body, _) => { + let cond_pat = self.next("cond"); + let body_pat = self.next("body"); + let label_pat = self.next("label"); + println!("While(ref {}, ref {}, ref {}) = {};", cond_pat, body_pat, label_pat, current); + self.current = cond_pat; + self.visit_expr(cond); + self.current = body_pat; + self.visit_block(body); }, - Expr_::ExprLoop(ref _body, ref _opt_label, ref _desuraging) => { - println!("Loop(ref body, ref opt_label, ref desugaring) = {};", current); - println!(" // unimplemented: `ExprLoop` is not further destructured at the moment"); + Expr_::ExprLoop(ref body, _, desugaring) => { + let body_pat = self.next("body"); + let des = loop_desugaring_name(desugaring); + let label_pat = self.next("label"); + println!("Loop(ref {}, ref {}, {}) = {};", body_pat, label_pat, des, current); + self.current = body_pat; + self.visit_block(body); }, - Expr_::ExprMatch(ref _expr, ref _arms, ref _desugaring) => { - println!("Match(ref expr, ref arms, ref desugaring) = {};", current); + Expr_::ExprMatch(ref _expr, ref _arms, desugaring) => { + let des = desugaring_name(desugaring); + println!("Match(ref expr, ref arms, {}) = {};", des, current); println!(" // unimplemented: `ExprMatch` is not further destructured at the moment"); }, Expr_::ExprClosure(ref _capture_clause, ref _func, _, _, _) => { @@ -456,6 +467,24 @@ fn has_attr(attrs: &[Attribute]) -> bool { }) } +fn desugaring_name(des: hir::MatchSource) -> String { + match des { + hir::MatchSource::ForLoopDesugar => "MatchSource::ForLoopDesugar".to_string(), + hir::MatchSource::TryDesugar => "MatchSource::TryDesugar".to_string(), + hir::MatchSource::WhileLetDesugar => "MatchSource::WhileLetDesugar".to_string(), + hir::MatchSource::Normal => "MatchSource::Normal".to_string(), + hir::MatchSource::IfLetDesugar { contains_else_clause } => format!("MatchSource::IfLetDesugar {{ contains_else_clause: {} }}", contains_else_clause), + } +} + +fn loop_desugaring_name(des: hir::LoopSource) -> &'static str { + match des { + hir::LoopSource::ForLoop => "LoopSource::ForLoop", + hir::LoopSource::Loop => "LoopSource::Loop", + hir::LoopSource::WhileLet => "LoopSource::WhileLet", + } +} + fn print_path(path: &QPath, first: &mut bool) { match *path { QPath::Resolved(_, ref path) => for segment in &path.segments { diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 03630f87108..d606e7a15fc 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -1,4 +1,4 @@ -#![feature(plugin, inclusive_range_syntax)] +#![feature(plugin, inclusive_range_syntax, custom_attribute)] use std::collections::*; @@ -14,7 +14,7 @@ fn for_loop_over_option_and_result() { let v = vec![0, 1, 2]; // check FOR_LOOP_OVER_OPTION lint - for x in option { + #[clippy(author)]for x in option { println!("{}", x); } diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 1e7ff40e1ac..e588bfa0849 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -1,8 +1,8 @@ error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement. - --> $DIR/for_loop.rs:17:14 + --> $DIR/for_loop.rs:17:31 | -17 | for x in option { - | ^^^^^^ +17 | #[clippy(author)]for x in option { + | ^^^^^^ | = note: `-D for-loop-over-option` implied by `-D warnings` = help: consider replacing `for x in option` with `if let Some(x) = option` diff --git a/tests/ui/for_loop.stdout b/tests/ui/for_loop.stdout new file mode 100644 index 00000000000..ce4186fa6a1 --- /dev/null +++ b/tests/ui/for_loop.stdout @@ -0,0 +1,20 @@ +if_chain! { + if let Expr_::ExprBlock(ref block) = stmt.node; + if let Expr_::ExprMatch(ref expr, ref arms, MatchSource::ForLoopDesugar) = block.node; + // unimplemented: `ExprMatch` is not further destructured at the moment + if let Expr_::ExprPath(ref path) = block.node; + if match_qpath(path, &["_result"]); + then { + // report your lint here + } +} +if_chain! { + if let Expr_::ExprBlock(ref block) = expr.node; + if let Expr_::ExprMatch(ref expr, ref arms, MatchSource::ForLoopDesugar) = block.node; + // unimplemented: `ExprMatch` is not further destructured at the moment + if let Expr_::ExprPath(ref path) = block.node; + if match_qpath(path, &["_result"]); + then { + // report your lint here + } +}