1 package net.sourceforge.pmd.rules.basic;
2
3 import net.sourceforge.pmd.AbstractJavaRule;
4 import net.sourceforge.pmd.ast.ASTExpression;
5 import net.sourceforge.pmd.ast.ASTPrimaryExpression;
6 import net.sourceforge.pmd.ast.ASTPrimaryPrefix;
7 import net.sourceforge.pmd.ast.ASTUnaryExpression;
8 import net.sourceforge.pmd.ast.ASTUnaryExpressionNotPlusMinus;
9 import net.sourceforge.pmd.ast.Node;
10 import net.sourceforge.pmd.ast.SimpleNode;
11
12 public class AvoidMultipleUnaryOperators extends AbstractJavaRule {
13
14 public AvoidMultipleUnaryOperators() {
15 super.addRuleChainVisit("UnaryExpression");
16 super.addRuleChainVisit("UnaryExpressionNotPlusMinus");
17 }
18
19 @Override
20 public Object visit(ASTUnaryExpression node, Object data) {
21 checkUnaryDescendent(node, data);
22 return data;
23 }
24
25 @Override
26 public Object visit(ASTUnaryExpressionNotPlusMinus node, Object data) {
27 checkUnaryDescendent(node, data);
28 return data;
29 }
30
31 private void checkUnaryDescendent(SimpleNode node, Object data) {
32 boolean match = false;
33 if (node.jjtGetNumChildren() == 1) {
34 Node child = node.jjtGetChild(0);
35 if (child instanceof ASTUnaryExpression || child instanceof ASTUnaryExpressionNotPlusMinus) {
36 match = true;
37 } else if (child instanceof ASTPrimaryExpression) {
38 Node primaryExpression = child;
39
40 while (true) {
41 if (primaryExpression.jjtGetNumChildren() == 1
42 && primaryExpression.jjtGetChild(0) instanceof ASTPrimaryPrefix
43 && primaryExpression.jjtGetChild(0).jjtGetNumChildren() == 1
44 && primaryExpression.jjtGetChild(0).jjtGetChild(0) instanceof ASTExpression
45 && primaryExpression.jjtGetChild(0).jjtGetChild(0).jjtGetNumChildren() == 1) {
46 Node candidate = primaryExpression.jjtGetChild(0).jjtGetChild(0).jjtGetChild(0);
47 if (candidate instanceof ASTUnaryExpression
48 || candidate instanceof ASTUnaryExpressionNotPlusMinus) {
49 match = true;
50 break;
51 } else if (candidate instanceof ASTPrimaryExpression) {
52 primaryExpression = candidate;
53 continue;
54 } else {
55 break;
56 }
57 } else {
58 break;
59 }
60 }
61 }
62 }
63
64 if (match) {
65 addViolation(data, node);
66 }
67 }
68 }