about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorllogiq <bogusandre@gmail.com>2015-05-15 18:46:43 +0200
committerllogiq <bogusandre@gmail.com>2015-05-15 18:46:43 +0200
commitedf747ab7617c38381e791f56c0376f0f8fea559 (patch)
treed41f1b2171287dd2fb3c15bb7d4b91888785e1c2 /src
parent6f527ea810b304bf7da2b97d27fe979cdc7c8612 (diff)
downloadrust-edf747ab7617c38381e791f56c0376f0f8fea559.tar.gz
rust-edf747ab7617c38381e791f56c0376f0f8fea559.zip
new lint: identity_op, refactored bit_masks a bit
Diffstat (limited to 'src')
-rw-r--r--src/identity_op.rs82
-rw-r--r--src/lib.rs3
2 files changed, 85 insertions, 0 deletions
diff --git a/src/identity_op.rs b/src/identity_op.rs
new file mode 100644
index 00000000000..ec4495539d2
--- /dev/null
+++ b/src/identity_op.rs
@@ -0,0 +1,82 @@
+use rustc::plugin::Registry;
+use rustc::lint::*;
+use rustc::middle::const_eval::lookup_const_by_id;
+use rustc::middle::def::*;
+use syntax::ast::*;
+use syntax::ast_util::{is_comparison_binop, binop_to_string};
+use syntax::ptr::P;
+use syntax::codemap::Span;
+
+declare_lint! { pub IDENTITY_OP, Warn,
+    "Warn on identity operations, e.g. '_ + 0'"}
+    
+#[derive(Copy,Clone)]
+pub struct IdentityOp;
+
+impl LintPass for IdentityOp {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(IDENTITY_OP)
+    }
+    
+    fn check_expr(&mut self, cx: &Context, e: &Expr) {
+		if let ExprBinary(ref cmp, ref left, ref right) = e.node {
+			match cmp.node {
+				BiAdd | BiBitOr | BiBitXor => {
+					check(cx, left, 0, e.span, right.span);
+					check(cx, right, 0, e.span, left.span);
+				},
+				BiShl | BiShr | BiSub => 
+					check(cx, right, 0, e.span, left.span),
+				BiMul => {
+					check(cx, left, 1, e.span, right.span);
+					check(cx, right, 1, e.span, left.span);
+				},
+				BiDiv =>
+					check(cx, right, 1, e.span, left.span),
+				BiBitAnd => {
+					check(cx, left, -1, e.span, right.span);
+					check(cx, right, -1, e.span, left.span);
+				},
+				_ => ()
+			}
+		}
+    }
+}
+
+
+fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) {
+	if have_lit(cx, e, m) {
+		let map = cx.sess().codemap();
+		cx.span_lint(IDENTITY_OP, span, &format!(
+			"The operation is ineffective. Consider reducing it to '{}'", 
+			&*map.span_to_snippet(arg).unwrap_or("..".to_string())));
+	}
+}
+
+fn have_lit(cx: &Context, e : &Expr, m: i8) -> bool {
+	match &e.node {
+		&ExprUnary(UnNeg, ref litexp) => have_lit(cx, litexp, -m), 
+		&ExprLit(ref lit) => {
+			match (&lit.node, m) {
+				(&LitInt(0, _), 0) => true,
+				(&LitInt(1, SignedIntLit(_, Plus)), 1) => true,
+				(&LitInt(1, UnsuffixedIntLit(Plus)), 1) => true,
+				(&LitInt(1, SignedIntLit(_, Minus)), -1) => true,
+				(&LitInt(1, UnsuffixedIntLit(Minus)), -1) => true,
+				_ => false
+			}
+		},
+		&ExprParen(ref p) => have_lit(cx, p, m),
+		&ExprPath(_, _) => {
+                match cx.tcx.def_map.borrow().get(&e.id) {
+                    Some(&PathResolution { base_def: DefConst(def_id), ..}) => 
+						match lookup_const_by_id(cx.tcx, def_id, Option::None) {
+							Some(l) => have_lit(cx, l, m),
+							None => false
+						},
+                    _ => false
+                }
+            }
+		_ => false
+	}
+}
diff --git a/src/lib.rs b/src/lib.rs
index 1655faaf8b0..c9585d2ebba 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -22,6 +22,7 @@ pub mod ptr_arg;
 pub mod needless_bool;
 pub mod approx_const;
 pub mod eta_reduction;
+pub mod identity_op;
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
@@ -38,6 +39,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_lint_pass(box misc::FloatCmp as LintPassObject);
     reg.register_lint_pass(box misc::Precedence as LintPassObject);
     reg.register_lint_pass(box eta_reduction::EtaPass as LintPassObject);
+    reg.register_lint_pass(box identity_op::IdentityOp as LintPassObject);
     
     reg.register_lint_group("clippy", vec![types::BOX_VEC, types::LINKEDLIST,
                                            misc::SINGLE_MATCH, misc::STR_TO_STRING,
@@ -50,5 +52,6 @@ pub fn plugin_registrar(reg: &mut Registry) {
                                            misc::CMP_NAN, misc::FLOAT_CMP,
                                            misc::PRECEDENCE,
                                            eta_reduction::REDUNDANT_CLOSURE,
+                                           identity_op::IDENTITY_OP,
                                            ]);
 }