1 /***
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.rules;
5
6 import net.sourceforge.pmd.AbstractRule;
7 import net.sourceforge.pmd.ast.ASTAssignmentOperator;
8 import net.sourceforge.pmd.ast.ASTExpression;
9 import net.sourceforge.pmd.ast.ASTName;
10 import net.sourceforge.pmd.ast.ASTPrimaryExpression;
11 import net.sourceforge.pmd.ast.ASTPrimarySuffix;
12 import net.sourceforge.pmd.ast.ASTStatementExpression;
13 import net.sourceforge.pmd.ast.Node;
14 import net.sourceforge.pmd.ast.SimpleNode;
15
16 public class IdempotentOperations extends AbstractRule {
17
18 public Object visit(ASTStatementExpression node, Object data) {
19 if (node.jjtGetNumChildren() != 3
20 || !(node.jjtGetChild(0) instanceof ASTPrimaryExpression)
21 || !(node.jjtGetChild(1) instanceof ASTAssignmentOperator)
22 || (((ASTAssignmentOperator) (node.jjtGetChild(1))).isCompound())
23 || !(node.jjtGetChild(2) instanceof ASTExpression)
24 || node.jjtGetChild(0).jjtGetChild(0).jjtGetNumChildren() == 0
25 || node.jjtGetChild(2).jjtGetChild(0).jjtGetChild(0).jjtGetNumChildren() == 0
26 ) {
27 return super.visit(node, data);
28 }
29
30 SimpleNode lhs = (SimpleNode) node.jjtGetChild(0).jjtGetChild(0).jjtGetChild(0);
31 if (!(lhs instanceof ASTName)) {
32 return super.visit(node, data);
33 }
34
35 SimpleNode rhs = (SimpleNode) node.jjtGetChild(2).jjtGetChild(0).jjtGetChild(0).jjtGetChild(0);
36 if (!(rhs instanceof ASTName)) {
37 return super.visit(node, data);
38 }
39
40 if (!lhs.hasImageEqualTo(rhs.getImage())) {
41 return super.visit(node, data);
42 }
43
44 if (lhs.jjtGetParent().jjtGetParent().jjtGetNumChildren() > 1) {
45 Node n = lhs.jjtGetParent().jjtGetParent().jjtGetChild(1);
46 if (n instanceof ASTPrimarySuffix && ((ASTPrimarySuffix) n).isArrayDereference()) {
47 return super.visit(node, data);
48 }
49 }
50
51 if (rhs.jjtGetParent().jjtGetParent().jjtGetNumChildren() > 1) {
52 Node n = rhs.jjtGetParent().jjtGetParent().jjtGetChild(1);
53 if (n instanceof ASTPrimarySuffix && ((ASTPrimarySuffix) n).isArguments() || ((ASTPrimarySuffix) n).isArrayDereference()) {
54 return super.visit(node, data);
55 }
56 }
57
58 if (lhs.findChildrenOfType(ASTPrimarySuffix.class).size() != rhs.findChildrenOfType(ASTPrimarySuffix.class).size()) {
59 return super.visit(node, data);
60 }
61
62 addViolation(data, node);
63 return super.visit(node, data);
64 }
65 }