diff --git a/.gitignore b/.gitignore index 11458b88927..2891bcf24ee 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,4 @@ util/gh-pages/lints.json helper.txt -*.stdout - .vscode diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c223de8ebfd..f1998235d30 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -222,6 +222,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { reg.register_early_lint_pass(box utils::internal_lints::Clippy); reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default()); reg.register_late_lint_pass(box utils::inspector::Pass); + reg.register_late_lint_pass(box utils::author::Pass); reg.register_late_lint_pass(box types::TypePass); reg.register_late_lint_pass(box booleans::NonminimalBool); reg.register_late_lint_pass(box eq_op::EqOp); diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs new file mode 100644 index 00000000000..af92589b4d2 --- /dev/null +++ b/clippy_lints/src/utils/author.rs @@ -0,0 +1,470 @@ +//! 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)] + +use rustc::lint::*; +use rustc::hir; +use rustc::hir::{Expr, QPath, Expr_}; +use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; +use syntax::ast::{Attribute, NodeId, LitKind, DUMMY_NODE_ID, self}; +use syntax::codemap::Span; +use std::collections::HashMap; + +/// **What it does:** Generates clippy code that detects the offending pattern +/// +/// **Example:** +/// ```rust +/// fn foo() { +/// // detect the following pattern +/// #[clippy(author)] +/// if x == 42 { +/// // but ignore everything from here on +/// #![clippy(author = "ignore")] +/// } +/// } +/// ``` +/// +/// prints +/// +/// ``` +/// if_let_chain!{[ +/// let Expr_::ExprIf(ref cond, ref then, None) = item.node, +/// let Expr_::ExprBinary(BinOp::Eq, ref left, ref right) = cond.node, +/// let Expr_::ExprPath(ref path) = left.node, +/// let Expr_::ExprLit(ref lit) = right.node, +/// let LitKind::Int(42, _) = lit.node, +/// ], { +/// // report your lint here +/// }} +/// ``` +declare_lint! { + pub LINT_AUTHOR, + Warn, + "helper for writing lints" +} + +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(LINT_AUTHOR) + } +} + +fn prelude() { + println!("if_let_chain!{{["); +} + +fn done() { + println!("], {{"); + println!(" // report your lint here"); + println!("}}}}"); +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_item(&mut self, _cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { + if !has_attr(&item.attrs) { + return; + } + prelude(); + PrintVisitor::new("item").visit_item(item); + done(); + } + + fn check_impl_item(&mut self, _cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem) { + if !has_attr(&item.attrs) { + return; + } + prelude(); + PrintVisitor::new("item").visit_impl_item(item); + done(); + } + + fn check_trait_item(&mut self, _cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) { + if !has_attr(&item.attrs) { + return; + } + prelude(); + PrintVisitor::new("item").visit_trait_item(item); + done(); + } + + fn check_variant(&mut self, _cx: &LateContext<'a, 'tcx>, var: &'tcx hir::Variant, generics: &hir::Generics) { + if !has_attr(&var.node.attrs) { + return; + } + prelude(); + PrintVisitor::new("var").visit_variant(var, generics, DUMMY_NODE_ID); + done(); + } + + fn check_struct_field(&mut self, _cx: &LateContext<'a, 'tcx>, field: &'tcx hir::StructField) { + if !has_attr(&field.attrs) { + return; + } + prelude(); + PrintVisitor::new("field").visit_struct_field(field); + done(); + } + + fn check_expr(&mut self, _cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { + if !has_attr(&expr.attrs) { + return; + } + prelude(); + PrintVisitor::new("expr").visit_expr(expr); + done(); + } + + fn check_arm(&mut self, _cx: &LateContext<'a, 'tcx>, arm: &'tcx hir::Arm) { + if !has_attr(&arm.attrs) { + return; + } + prelude(); + PrintVisitor::new("arm").visit_arm(arm); + done(); + } + + fn check_stmt(&mut self, _cx: &LateContext<'a, 'tcx>, stmt: &'tcx hir::Stmt) { + if !has_attr(stmt.node.attrs()) { + return; + } + prelude(); + PrintVisitor::new("stmt").visit_stmt(stmt); + done(); + } + + fn check_foreign_item(&mut self, _cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ForeignItem) { + if !has_attr(&item.attrs) { + return; + } + prelude(); + PrintVisitor::new("item").visit_foreign_item(item); + done(); + } +} + +impl PrintVisitor { + fn new(s: &'static str) -> Self { + PrintVisitor { + ids: HashMap::new(), + current: s.to_owned(), + } + } + + fn next(&mut self, s: &'static str) -> String { + use std::collections::hash_map::Entry::*; + match self.ids.entry(s) { + // already there: start numbering from `1` + Occupied(mut occ) => { + let val = occ.get_mut(); + *val += 1; + format!("{}{}", s, *val) + }, + // not there: insert and return name as given + Vacant(vac) => { + vac.insert(0); + s.to_owned() + } + } + } +} + +struct PrintVisitor { + /// Fields are the current index that needs to be appended to pattern binding names + ids: HashMap<&'static str, usize>, + /// the name that needs to be destructured + current: String, +} + +impl<'tcx> Visitor<'tcx> for PrintVisitor { + fn visit_expr(&mut self, expr: &Expr) { + print!(" let Expr_::Expr"); + let current = format!("{}.node", self.current); + match expr.node { + Expr_::ExprBox(ref inner) => { + let inner_pat = self.next("inner"); + println!("Box(ref {}) = {},", inner_pat, current); + self.current = inner_pat; + self.visit_expr(inner); + }, + Expr_::ExprArray(ref elements) => { + let elements_pat = self.next("elements"); + println!("Array(ref {}) = {},", elements_pat, current); + println!(" {}.len() == {},", elements_pat, elements.len()); + for (i, element) in elements.iter().enumerate() { + self.current = format!("{}[{}]", elements_pat, i); + self.visit_expr(element); + } + }, + Expr_::ExprCall(ref _func, ref _args) => { + println!("Call(ref func, ref args) = {},", current); + println!(" // unimplemented: `ExprCall` is not further destructured at the moment"); + }, + Expr_::ExprMethodCall(ref _method_name, ref _generics, ref _args) => { + println!("MethodCall(ref method_name, ref generics, ref args) = {},", current); + println!(" // unimplemented: `ExprMethodCall` is not further destructured at the moment"); + }, + Expr_::ExprTup(ref elements) => { + let elements_pat = self.next("elements"); + println!("Tup(ref {}) = {},", elements_pat, current); + println!(" {}.len() == {},", elements_pat, elements.len()); + for (i, element) in elements.iter().enumerate() { + self.current = format!("{}[{}]", elements_pat, i); + self.visit_expr(element); + } + }, + Expr_::ExprBinary(ref op, ref left, ref right) => { + let op_pat = self.next("op"); + let left_pat = self.next("left"); + let right_pat = self.next("right"); + println!("Binary(ref {}, ref {}, ref {}) = {},", op_pat, left_pat, right_pat, current); + println!(" BinOp_::{:?} == {}.node,", op.node, op_pat); + self.current = left_pat; + self.visit_expr(left); + self.current = right_pat; + self.visit_expr(right); + }, + Expr_::ExprUnary(ref op, ref inner) => { + let inner_pat = self.next("inner"); + println!("Unary(UnOp::{:?}, ref {}) = {},", op, inner_pat, current); + self.current = inner_pat; + self.visit_expr(inner); + }, + Expr_::ExprLit(ref lit) => { + let lit_pat = self.next("lit"); + println!("Lit(ref {}) = {},", lit_pat, current); + match lit.node { + LitKind::Bool(val) => println!(" let LitKind::Bool({:?}) = {}.node,", val, lit_pat), + LitKind::Char(c) => println!(" let LitKind::Char({:?}) = {}.node,", c, lit_pat), + LitKind::Byte(b) => println!(" let LitKind::Byte({}) = {}.node,", b, lit_pat), + // FIXME: also check int type + LitKind::Int(i, _) => println!(" let LitKind::Int({}, _) = {}.node,", i, lit_pat), + LitKind::Float(..) => println!(" let LitKind::Float(..) = {}.node,", lit_pat), + LitKind::FloatUnsuffixed(_) => println!(" let LitKind::FloatUnsuffixed(_) = {}.node,", lit_pat), + LitKind::ByteStr(ref vec) => { + let vec_pat = self.next("vec"); + println!(" let LitKind::ByteStr(ref {}) = {}.node,", vec_pat, lit_pat); + println!(" let [{:?}] = **{},", vec, vec_pat); + }, + LitKind::Str(ref text, _) => { + let str_pat = self.next("s"); + println!(" let LitKind::Str(ref {}) = {}.node,", str_pat, lit_pat); + println!(" {}.as_str() == {:?}", str_pat, &*text.as_str()) + }, + } + } + Expr_::ExprCast(ref expr, ref _ty) => { + let cast_pat = self.next("expr"); + println!("Cast(ref {}, _) = {},", cast_pat, current); + self.current = cast_pat; + self.visit_expr(expr); + }, + Expr_::ExprType(ref expr, ref _ty) => { + let cast_pat = self.next("expr"); + println!("Type(ref {}, _) = {},", cast_pat, current); + self.current = cast_pat; + self.visit_expr(expr); + }, + Expr_::ExprIf(ref cond, ref then, ref opt_else) => { + let cond_pat = self.next("cond"); + let then_pat = self.next("then"); + if let Some(ref else_) = *opt_else { + let else_pat = self.next("else_"); + println!("If(ref {}, ref {}, Some(ref {})) = {},", cond_pat, then_pat, else_pat, current); + self.current = else_pat; + self.visit_expr(else_); + } else { + println!("If(ref {}, ref {}, None) = {},", cond_pat, then_pat, current); + } + self.current = cond_pat; + self.visit_expr(cond); + 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_::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_::ExprMatch(ref _expr, ref _arms, ref _desugaring) => { + println!("Match(ref expr, ref arms, ref desugaring) = {},", current); + println!(" // unimplemented: `ExprMatch` is not further destructured at the moment"); + }, + Expr_::ExprClosure(ref _capture_clause, ref _func, _, _) => { + println!("Closure(ref capture_clause, ref func, _, _) = {},", current); + println!(" // unimplemented: `ExprClosure` is not further destructured at the moment"); + }, + Expr_::ExprBlock(ref block) => { + let block_pat = self.next("block"); + println!("Block(ref {}) = {},", block_pat, current); + self.current = block_pat; + self.visit_block(block); + }, + Expr_::ExprAssign(ref target, ref value) => { + let target_pat = self.next("target"); + let value_pat = self.next("value"); + println!("Assign(ref {}, ref {}) = {},", target_pat, value_pat, current); + self.current = target_pat; + self.visit_expr(target); + self.current = value_pat; + self.visit_expr(value); + }, + Expr_::ExprAssignOp(ref op, ref target, ref value) => { + let op_pat = self.next("op"); + let target_pat = self.next("target"); + let value_pat = self.next("value"); + println!("AssignOp(ref {}, ref {}, ref {}) = {},", op_pat, target_pat, value_pat, current); + println!(" BinOp_::{:?} == {}.node,", op.node, op_pat); + self.current = target_pat; + self.visit_expr(target); + self.current = value_pat; + self.visit_expr(value); + }, + Expr_::ExprField(ref object, ref field_name) => { + let obj_pat = self.next("object"); + let field_name_pat = self.next("field_name"); + println!("Field(ref {}, ref {}) = {},", obj_pat, field_name_pat, current); + println!(" {}.node.as_str() == {:?}", field_name_pat, field_name.node.as_str()); + self.current = obj_pat; + self.visit_expr(object); + }, + Expr_::ExprTupField(ref object, ref field_id) => { + let obj_pat = self.next("object"); + let field_id_pat = self.next("field_id"); + println!("TupField(ref {}, ref {}) = {},", obj_pat, field_id_pat, current); + println!(" {}.node == {}", field_id_pat, field_id.node); + self.current = obj_pat; + self.visit_expr(object); + }, + Expr_::ExprIndex(ref object, ref index) => { + let object_pat = self.next("object"); + let index_pat = self.next("index"); + println!("Index(ref {}, ref {}) = {},", object_pat, index_pat, current); + self.current = object_pat; + self.visit_expr(object); + self.current = index_pat; + self.visit_expr(index); + }, + Expr_::ExprPath(ref path) => { + let path_pat = self.next("path"); + println!("Path(ref {}) = {},", path_pat, current); + self.current = path_pat; + self.visit_qpath(path, expr.id, expr.span); + }, + Expr_::ExprAddrOf(mutability, ref inner) => { + let inner_pat = self.next("inner"); + println!("AddrOf({:?}, ref {}) = {},", mutability, inner_pat, current); + self.current = inner_pat; + self.visit_expr(inner); + }, + Expr_::ExprBreak(ref _destination, ref opt_value) => { + let destination_pat = self.next("destination"); + if let Some(ref value) = *opt_value { + let value_pat = self.next("value"); + println!("Break(ref {}, Some(ref {})) = {},", destination_pat, value_pat, current); + self.current = value_pat; + self.visit_expr(value); + } else { + println!("Break(ref {}, None) = {},", destination_pat, current); + } + // FIXME: implement label printing + }, + Expr_::ExprAgain(ref _destination) => { + let destination_pat = self.next("destination"); + println!("Again(ref {}) = {},", destination_pat, current); + // FIXME: implement label printing + }, + Expr_::ExprRet(ref opt_value) => { + if let Some(ref value) = *opt_value { + let value_pat = self.next("value"); + println!("Ret(Some(ref {})) = {},", value_pat, current); + self.current = value_pat; + self.visit_expr(value); + } else { + println!("Ret(None) = {},", current); + } + }, + Expr_::ExprInlineAsm(_, ref _input, ref _output) => { + println!("InlineAsm(_, ref input, ref output) = {},", current); + println!(" // unimplemented: `ExprInlineAsm` is not further destructured at the moment"); + }, + Expr_::ExprStruct(ref path, ref fields, ref opt_base) => { + let path_pat = self.next("path"); + let fields_pat = self.next("fields"); + if let Some(ref base) = *opt_base { + let base_pat = self.next("base"); + println!("Struct(ref {}, ref {}, Some(ref {})) = {},", path_pat, fields_pat, base_pat, current); + self.current = base_pat; + self.visit_expr(base); + } else { + println!("Struct(ref {}, ref {}, None) = {},", path_pat, fields_pat, current); + } + self.current = path_pat; + self.visit_qpath(path, expr.id, expr.span); + println!(" {}.len() == {},", fields_pat, fields.len()); + println!(" // unimplemented: field checks"); + }, + // FIXME: compute length (needs type info) + Expr_::ExprRepeat(ref value, _) => { + let value_pat = self.next("value"); + println!("Repeat(ref {}, _) = {},", value_pat, current); + println!("// unimplemented: repeat count check"); + self.current = value_pat; + self.visit_expr(value); + }, + } + } + + fn visit_qpath(&mut self, path: &QPath, _: NodeId, _: Span) { + print!(" match_path({}, &[", self.current); + print_path(path, &mut true); + println!("]),"); + } + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } +} + +fn has_attr(attrs: &[Attribute]) -> bool { + attrs.iter().any(|attr| { + attr.check_name("clippy") && + attr.meta_item_list().map_or(false, |list| { + list.len() == 1 && match list[0].node { + ast::NestedMetaItemKind::MetaItem(ref it) => it.name == "author", + ast::NestedMetaItemKind::Literal(_) => false, + } + }) + }) +} + +fn print_path(path: &QPath, first: &mut bool) { + match *path { + QPath::Resolved(_, ref path) => for segment in &path.segments { + if *first { + *first = false; + } else { + print!(", "); + } + print!("{:?}", segment.name.as_str()); + }, + QPath::TypeRelative(ref ty, ref segment) => { + match ty.node { + hir::Ty_::TyPath(ref inner_path) => { + print_path(inner_path, first); + if *first { + *first = false; + } else { + print!(", "); + } + print!("{:?}", segment.name.as_str()); + }, + ref other => print!("/* unimplemented: {:?}*/", other), + } + }, + } +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e8e11e37a5c..cdce1108be2 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -29,6 +29,7 @@ pub mod paths; pub mod sugg; pub mod inspector; pub mod internal_lints; +pub mod author; pub use self::hir_utils::{SpanlessEq, SpanlessHash}; pub type MethodArgs = HirVec>; diff --git a/clippy_tests/examples/absurd-extreme-comparisons.stdout b/clippy_tests/examples/absurd-extreme-comparisons.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/approx_const.stdout b/clippy_tests/examples/approx_const.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/arithmetic.stdout b/clippy_tests/examples/arithmetic.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/array_indexing.stdout b/clippy_tests/examples/array_indexing.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/assign_ops.stdout b/clippy_tests/examples/assign_ops.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/assign_ops2.stdout b/clippy_tests/examples/assign_ops2.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/attrs.stdout b/clippy_tests/examples/attrs.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/bit_masks.stdout b/clippy_tests/examples/bit_masks.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/blacklisted_name.stdout b/clippy_tests/examples/blacklisted_name.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/block_in_if_condition.stdout b/clippy_tests/examples/block_in_if_condition.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/bool_comparison.stdout b/clippy_tests/examples/bool_comparison.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/booleans.stdout b/clippy_tests/examples/booleans.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/borrow_box.stdout b/clippy_tests/examples/borrow_box.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/box_vec.stdout b/clippy_tests/examples/box_vec.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/cast.stdout b/clippy_tests/examples/cast.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/char_lit_as_u8.stdout b/clippy_tests/examples/char_lit_as_u8.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/cmp_nan.stdout b/clippy_tests/examples/cmp_nan.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/cmp_null.stdout b/clippy_tests/examples/cmp_null.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/cmp_owned.stdout b/clippy_tests/examples/cmp_owned.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/collapsible_if.stdout b/clippy_tests/examples/collapsible_if.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/complex_types.stdout b/clippy_tests/examples/complex_types.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/copies.stdout b/clippy_tests/examples/copies.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/cyclomatic_complexity.stdout b/clippy_tests/examples/cyclomatic_complexity.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/cyclomatic_complexity_attr_used.stdout b/clippy_tests/examples/cyclomatic_complexity_attr_used.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/derive.stdout b/clippy_tests/examples/derive.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/diverging_sub_expression.stdout b/clippy_tests/examples/diverging_sub_expression.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/dlist.stdout b/clippy_tests/examples/dlist.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/doc.stdout b/clippy_tests/examples/doc.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/double_neg.stdout b/clippy_tests/examples/double_neg.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/double_parens.stdout b/clippy_tests/examples/double_parens.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/drop_forget_copy.stdout b/clippy_tests/examples/drop_forget_copy.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/drop_forget_ref.stdout b/clippy_tests/examples/drop_forget_ref.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/duplicate_underscore_argument.stdout b/clippy_tests/examples/duplicate_underscore_argument.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/empty_enum.stdout b/clippy_tests/examples/empty_enum.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/entry.stdout b/clippy_tests/examples/entry.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/enum_glob_use.stdout b/clippy_tests/examples/enum_glob_use.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/enum_variants.stdout b/clippy_tests/examples/enum_variants.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/enums_clike.stdout b/clippy_tests/examples/enums_clike.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/eq_op.stdout b/clippy_tests/examples/eq_op.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/escape_analysis.stdout b/clippy_tests/examples/escape_analysis.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/eta.stdout b/clippy_tests/examples/eta.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/eval_order_dependence.stdout b/clippy_tests/examples/eval_order_dependence.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/filter_methods.stdout b/clippy_tests/examples/filter_methods.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/float_cmp.stdout b/clippy_tests/examples/float_cmp.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/for_loop.stdout b/clippy_tests/examples/for_loop.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/format.stdout b/clippy_tests/examples/format.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/formatting.stdout b/clippy_tests/examples/formatting.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/functions.stdout b/clippy_tests/examples/functions.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/identity_op.stdout b/clippy_tests/examples/identity_op.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/if_let_redundant_pattern_matching.stdout b/clippy_tests/examples/if_let_redundant_pattern_matching.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/if_not_else.stdout b/clippy_tests/examples/if_not_else.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/invalid_upcast_comparisons.stdout b/clippy_tests/examples/invalid_upcast_comparisons.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/item_after_statement.stdout b/clippy_tests/examples/item_after_statement.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/large_enum_variant.stdout b/clippy_tests/examples/large_enum_variant.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/len_zero.stdout b/clippy_tests/examples/len_zero.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/let_if_seq.stdout b/clippy_tests/examples/let_if_seq.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/let_return.stdout b/clippy_tests/examples/let_return.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/let_unit.stdout b/clippy_tests/examples/let_unit.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/lifetimes.stdout b/clippy_tests/examples/lifetimes.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/lint_pass.stdout b/clippy_tests/examples/lint_pass.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/literals.stdout b/clippy_tests/examples/literals.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/map_clone.stdout b/clippy_tests/examples/map_clone.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/matches.stdout b/clippy_tests/examples/matches.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/mem_forget.stdout b/clippy_tests/examples/mem_forget.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/methods.stdout b/clippy_tests/examples/methods.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/min_max.stdout b/clippy_tests/examples/min_max.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/missing-doc.stdout b/clippy_tests/examples/missing-doc.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/module_inception.stdout b/clippy_tests/examples/module_inception.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/modulo_one.stdout b/clippy_tests/examples/modulo_one.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/mut_from_ref.stdout b/clippy_tests/examples/mut_from_ref.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/mut_mut.stdout b/clippy_tests/examples/mut_mut.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/mut_reference.stdout b/clippy_tests/examples/mut_reference.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/mutex_atomic.stdout b/clippy_tests/examples/mutex_atomic.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/needless_bool.stdout b/clippy_tests/examples/needless_bool.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/needless_borrow.stdout b/clippy_tests/examples/needless_borrow.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/needless_continue.stdout b/clippy_tests/examples/needless_continue.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/needless_pass_by_value.stdout b/clippy_tests/examples/needless_pass_by_value.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/needless_return.stdout b/clippy_tests/examples/needless_return.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/needless_update.stdout b/clippy_tests/examples/needless_update.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/neg_multiply.stdout b/clippy_tests/examples/neg_multiply.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/never_loop.stdout b/clippy_tests/examples/never_loop.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/new_without_default.stdout b/clippy_tests/examples/new_without_default.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/no_effect.stdout b/clippy_tests/examples/no_effect.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/non_expressive_names.stdout b/clippy_tests/examples/non_expressive_names.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/ok_if_let.stdout b/clippy_tests/examples/ok_if_let.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/op_ref.stdout b/clippy_tests/examples/op_ref.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/open_options.stdout b/clippy_tests/examples/open_options.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/overflow_check_conditional.stdout b/clippy_tests/examples/overflow_check_conditional.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/panic.stdout b/clippy_tests/examples/panic.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/partialeq_ne_impl.stdout b/clippy_tests/examples/partialeq_ne_impl.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/patterns.stdout b/clippy_tests/examples/patterns.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/precedence.stdout b/clippy_tests/examples/precedence.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/print.stdout b/clippy_tests/examples/print.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/print_with_newline.stdout b/clippy_tests/examples/print_with_newline.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/ptr_arg.stdout b/clippy_tests/examples/ptr_arg.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/range.stdout b/clippy_tests/examples/range.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/redundant_closure_call.stdout b/clippy_tests/examples/redundant_closure_call.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/reference.stdout b/clippy_tests/examples/reference.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/regex.stdout b/clippy_tests/examples/regex.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/serde.stdout b/clippy_tests/examples/serde.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/shadow.stdout b/clippy_tests/examples/shadow.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/short_circuit_statement.stdout b/clippy_tests/examples/short_circuit_statement.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/should_assert_eq.stdout b/clippy_tests/examples/should_assert_eq.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/strings.stdout b/clippy_tests/examples/strings.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/stutter.stdout b/clippy_tests/examples/stutter.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/swap.stdout b/clippy_tests/examples/swap.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/temporary_assignment.stdout b/clippy_tests/examples/temporary_assignment.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/toplevel_ref_arg.stdout b/clippy_tests/examples/toplevel_ref_arg.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/trailing_zeros.rs b/clippy_tests/examples/trailing_zeros.rs new file mode 100644 index 00000000000..ff73228f3f7 --- /dev/null +++ b/clippy_tests/examples/trailing_zeros.rs @@ -0,0 +1,10 @@ +#![feature(plugin, custom_attribute, stmt_expr_attributes)] +#![plugin(clippy)] +#![allow(unused_parens)] + +fn main() { + let x: i32 = 42; + let _ = #[clippy(author)] (x & 0b1111 == 0); // suggest trailing_zeros + let _ = x & 0b11111 == 0; // suggest trailing_zeros + let _ = x & 0b11010 == 0; // do not lint +} diff --git a/clippy_tests/examples/trailing_zeros.stderr b/clippy_tests/examples/trailing_zeros.stderr new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/trailing_zeros.stdout b/clippy_tests/examples/trailing_zeros.stdout new file mode 100644 index 00000000000..7f1e8a60096 --- /dev/null +++ b/clippy_tests/examples/trailing_zeros.stdout @@ -0,0 +1,14 @@ +if_let_chain!{[ + let Expr_::ExprBinary(ref op, ref left, ref right) = expr.node, + BinOp_::BiEq == op.node, + let Expr_::ExprBinary(ref op1, ref left1, ref right1) = left.node, + BinOp_::BiBitAnd == op1.node, + let Expr_::ExprPath(ref path) = left1.node, + match_path(path, &["x"]), + let Expr_::ExprLit(ref lit) = right1.node, + let LitKind::Int(15, _) = lit.node, + let Expr_::ExprLit(ref lit1) = right.node, + let LitKind::Int(0, _) = lit1.node, +]} { + // report your lint here +} diff --git a/clippy_tests/examples/unicode.stdout b/clippy_tests/examples/unicode.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/unit_cmp.stdout b/clippy_tests/examples/unit_cmp.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/unneeded_field_pattern.stdout b/clippy_tests/examples/unneeded_field_pattern.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/unsafe_removed_from_name.stdout b/clippy_tests/examples/unsafe_removed_from_name.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/unused_io_amount.stdout b/clippy_tests/examples/unused_io_amount.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/unused_labels.stdout b/clippy_tests/examples/unused_labels.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/unused_lt.stdout b/clippy_tests/examples/unused_lt.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/used_underscore_binding.stdout b/clippy_tests/examples/used_underscore_binding.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/useless_attribute.stdout b/clippy_tests/examples/useless_attribute.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/vec.stdout b/clippy_tests/examples/vec.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/while_loop.stdout b/clippy_tests/examples/while_loop.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/wrong_self_convention.stdout b/clippy_tests/examples/wrong_self_convention.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/zero_div_zero.stdout b/clippy_tests/examples/zero_div_zero.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/clippy_tests/examples/zero_ptr.stdout b/clippy_tests/examples/zero_ptr.stdout new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/examples.rs b/tests/examples.rs index 02dbdfef04c..44488f11c5c 100644 --- a/tests/examples.rs +++ b/tests/examples.rs @@ -27,18 +27,20 @@ fn examples() { continue; } cmd!("touch", &file).run().unwrap(); - let output = file.with_extension("stderr"); + let stderr = file.with_extension("stderr"); + let stdout = file.with_extension("stdout"); cmd!("cargo", "rustc", "-q", "--example", file.file_stem().unwrap(), "--", "-Dwarnings", "-Zremap-path-prefix-from=examples/", "-Zremap-path-prefix-to=", "-Zremap-path-prefix-from=examples\\", "-Zremap-path-prefix-to=" ) .unchecked() - .stderr(&output) + .stdout(&stdout) + .stderr(&stderr) .env("CLIPPY_DISABLE_WIKI_LINKS", "true") .dir("clippy_tests") .run() .unwrap(); - if cmd!("git", "diff", "--exit-code", output).run().is_err() { + if cmd!("git", "diff", "--exit-code", stderr).run().is_err() || cmd!("git", "diff", "--exit-code", stdout).run().is_err() { error = true; println!("ERROR"); } else {