//! A group of attributes that can be attached to Rust code in order
//! to generate a clippy lint detecting said code automatically.
-#![allow(print_stdout, use_debug)]
+#![allow(clippy::print_stdout, clippy::use_debug)]
-use rustc::lint::*;
+use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
+use rustc::{declare_tool_lint, lint_array};
use rustc::hir;
use rustc::hir::{Expr, ExprKind, QPath, TyKind, Pat, PatKind, BindingAnnotation, StmtKind, DeclKind, Stmt};
use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
+use rustc_data_structures::fx::FxHashMap;
use syntax::ast::{Attribute, LitKind, DUMMY_NODE_ID};
-use std::collections::HashMap;
use crate::utils::get_attr;
/// **What it does:** Generates clippy code that detects the offending pattern
impl PrintVisitor {
fn new(s: &'static str) -> Self {
Self {
- ids: HashMap::new(),
+ ids: FxHashMap::default(),
current: s.to_owned(),
}
}
struct PrintVisitor {
/// Fields are the current index that needs to be appended to pattern
/// binding names
- ids: HashMap<&'static str, usize>,
+ ids: FxHashMap<&'static str, usize>,
/// the name that needs to be destructured
current: String,
}
self.visit_expr(&arm.body);
if let Some(ref guard) = arm.guard {
let guard_pat = self.next("guard");
- println!(" if let Some(ref {}) = {}[{}].guard", guard_pat, arms_pat, i);
- self.current = guard_pat;
- self.visit_expr(guard);
+ println!(" if let Some(ref {}) = {}[{}].guard;", guard_pat, arms_pat, i);
+ match guard {
+ hir::Guard::If(ref if_expr) => {
+ let if_expr_pat = self.next("expr");
+ println!(" if let Guard::If(ref {}) = {};", if_expr_pat, guard_pat);
+ self.current = if_expr_pat;
+ self.visit_expr(if_expr);
+ }
+ }
}
println!(" if {}[{}].pats.len() == {};", arms_pat, i, arm.pats.len());
for (j, pat) in arm.pats.iter().enumerate() {
}
fn visit_stmt(&mut self, s: &Stmt) {
- print!(" if let Stmt_::");
+ print!(" if let StmtKind::");
let current = format!("{}.node", self.current);
match s.node {
// Could be an item or a local (let) binding:
StmtKind::Decl(ref decl, _) => {
let decl_pat = self.next("decl");
- println!("StmtKind::Decl(ref {}, _) = {}", decl_pat, current);
- print!(" if let Decl_::");
+ println!("Decl(ref {}, _) = {}", decl_pat, current);
+ print!(" if let DeclKind::");
let current = format!("{}.node", decl_pat);
match decl.node {
// A local (let) binding:
- Decl_::DeclLocal(ref local) => {
+ DeclKind::Local(ref local) => {
let local_pat = self.next("local");
- println!("DeclLocal(ref {}) = {};", local_pat, current);
+ println!("Local(ref {}) = {};", local_pat, current);
if let Some(ref init) = local.init {
let init_pat = self.next("init");
println!(" if let Some(ref {}) = {}.init", init_pat, local_pat);
self.visit_pat(&local.pat);
},
// An item binding:
- Decl_::DeclItem(_) => {
- println!("DeclItem(item_id) = {};", current);
+ DeclKind::Item(_) => {
+ println!("Item(item_id) = {};", current);
},
}
}
// Expr without trailing semi-colon (must have unit type):
StmtKind::Expr(ref e, _) => {
let e_pat = self.next("e");
- println!("StmtKind::Expr(ref {}, _) = {}", e_pat, current);
+ println!("Expr(ref {}, _) = {}", e_pat, current);
self.current = e_pat;
self.visit_expr(e);
},
// Expr with trailing semi-colon (may have any type):
StmtKind::Semi(ref e, _) => {
let e_pat = self.next("e");
- println!("StmtKind::Semi(ref {}, _) = {}", e_pat, current);
+ println!("Semi(ref {}, _) = {}", e_pat, current);
self.current = e_pat;
self.visit_expr(e);
},