Fix author lint

The author lint was generating invalid code as shown on issue:
https://github.com/rust-lang-nursery/rust-clippy/issues/2442

I've changed the generated code to properly track cast
expressions.

Unfortunatelly, I've had to rewrite the `visit_decl` method, to
avoid that last if of the chain will be added. After looking at the code,
this last line was being added because of the `let x: char` part, but not
because of the `0x45df as char` expression.

It seems that let statements should not generate code on the author
lint, but I'm not sure that this is true or if I'm breaking
something on other code generation parts.

Finally, I've added a test for the author lint, but I'm not sure that
this needs to be added to the testsuite.
This commit is contained in:
Guillem Nieto 2018-02-24 02:02:48 +01:00
parent 575c3c4b54
commit 8494f57c82
3 changed files with 43 additions and 4 deletions

View file

@ -5,8 +5,9 @@
use rustc::lint::*; use rustc::lint::*;
use rustc::hir; use rustc::hir;
use rustc::hir::{Expr, Expr_, QPath}; use rustc::hir::{Expr, Expr_, QPath, Ty_};
use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; use rustc::hir::intravisit::{NestedVisitorMap, Visitor, walk_decl};
use rustc::hir::Decl;
use syntax::ast::{self, Attribute, LitKind, NodeId, DUMMY_NODE_ID}; use syntax::ast::{self, Attribute, LitKind, NodeId, DUMMY_NODE_ID};
use syntax::codemap::Span; use syntax::codemap::Span;
use std::collections::HashMap; use std::collections::HashMap;
@ -79,6 +80,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
return; return;
} }
prelude(); prelude();
PrintVisitor::new("item").visit_impl_item(item); PrintVisitor::new("item").visit_impl_item(item);
done(); done();
} }
@ -182,6 +184,18 @@ struct PrintVisitor {
} }
impl<'tcx> Visitor<'tcx> for PrintVisitor { impl<'tcx> Visitor<'tcx> for PrintVisitor {
fn visit_decl(&mut self, d: &'tcx Decl) {
match d.node {
hir::DeclLocal(ref local) => {
self.visit_pat(&local.pat);
if let Some(ref e) = local.init {
self.visit_expr(e);
}
},
_ => walk_decl(self, d)
}
}
fn visit_expr(&mut self, expr: &Expr) { fn visit_expr(&mut self, expr: &Expr) {
print!(" if let Expr_::Expr"); print!(" if let Expr_::Expr");
let current = format!("{}.node", self.current); let current = format!("{}.node", self.current);
@ -260,9 +274,17 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
}, },
} }
}, },
Expr_::ExprCast(ref expr, ref _ty) => { Expr_::ExprCast(ref expr, ref ty) => {
let cast_pat = self.next("expr"); let cast_pat = self.next("expr");
println!("Cast(ref {}, _) = {};", cast_pat, current); let cast_ty = self.next("cast_ty");
let qp_label = self.next("qp");
println!("Cast(ref {}, ref {}) = {};", cast_pat, cast_ty, current);
if let Ty_::TyPath(ref qp) = ty.node {
println!(" if let Ty_::TyPath(ref {}) = {}.node;", qp_label, cast_ty);
self.current = qp_label;
self.visit_qpath(&qp, ty.id, ty.span);
}
self.current = cast_pat; self.current = cast_pat;
self.visit_expr(expr); self.visit_expr(expr);
}, },

7
tests/ui/author.rs Normal file
View file

@ -0,0 +1,7 @@
#![feature(plugin, custom_attribute)]
fn main() {
#[clippy(author)]
let x: char = 0x45 as char;
}

10
tests/ui/author.stdout Normal file
View file

@ -0,0 +1,10 @@
if_chain! {
if let Expr_::ExprCast(ref expr, ref cast_ty) = stmt.node;
if let Ty_::TyPath(ref qp) = cast_ty.node;
if match_qpath(qp, &["char"]);
if let Expr_::ExprLit(ref lit) = expr.node;
if let LitKind::Int(69, _) = lit.node;
then {
// report your lint here
}
}