KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > pmd > rules > design > ConfusingTernary


1 /**
2  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3  */

4 package net.sourceforge.pmd.rules.design;
5
6 import net.sourceforge.pmd.AbstractRule;
7 import net.sourceforge.pmd.ast.ASTConditionalAndExpression;
8 import net.sourceforge.pmd.ast.ASTConditionalExpression;
9 import net.sourceforge.pmd.ast.ASTConditionalOrExpression;
10 import net.sourceforge.pmd.ast.ASTEqualityExpression;
11 import net.sourceforge.pmd.ast.ASTExpression;
12 import net.sourceforge.pmd.ast.ASTIfStatement;
13 import net.sourceforge.pmd.ast.ASTPrimaryExpression;
14 import net.sourceforge.pmd.ast.ASTPrimaryPrefix;
15 import net.sourceforge.pmd.ast.ASTUnaryExpressionNotPlusMinus;
16 import net.sourceforge.pmd.ast.SimpleNode;
17
18 /**
19  * if (x != y) { diff(); } else { same(); } and<br>
20  * (!x ? diff() : same());.
21  * <p/>
22  * XPath can handle the easy cases, e.g.:<pre>
23  * //IfStatement[
24  * Statement[2]
25  * and Expression[
26  * EqualityExpression[@Image="!="] or
27  * UnaryExpressionNotPlusMinus[@Image="!"]]]
28  * </pre>
29  * but "&amp;&amp;" and "||" are difficult, since we need a match
30  * for <i>all</i> children instead of just one. This can be done by
31  * using a double-negative, e.g.:<pre>
32  * not(*[not(<i>matchme</i>)])
33  * </pre>
34  * Still, XPath is unable to handle arbitrarily nested cases, since it
35  * lacks recursion, e.g.:<pre>
36  * if (((x != !y)) || !(x)) { diff(); } else { same(); }
37  * </pre>
38  */

39 public class ConfusingTernary extends AbstractRule {
40
41     public Object JavaDoc visit(ASTIfStatement node, Object JavaDoc data) {
42         // look for "if (match) ..; else .."
43
if (node.jjtGetNumChildren() == 3) {
44             SimpleNode inode = (SimpleNode) node.jjtGetChild(0);
45             if (inode instanceof ASTExpression &&
46                     inode.jjtGetNumChildren() == 1) {
47                 SimpleNode jnode = (SimpleNode) inode.jjtGetChild(0);
48                 if (isMatch(jnode)) {
49                     addViolation(data, node);
50                 }
51             }
52         }
53         return super.visit(node, data);
54     }
55
56     public Object JavaDoc visit(ASTConditionalExpression node, Object JavaDoc data) {
57         // look for "match ? .. : .."
58
if (node.jjtGetNumChildren() > 0) {
59             SimpleNode inode = (SimpleNode) node.jjtGetChild(0);
60             if (isMatch(inode)) {
61                 addViolation(data, node);
62             }
63         }
64         return super.visit(node, data);
65     }
66
67     // recursive!
68
private static boolean isMatch(SimpleNode node) {
69         return
70                 isUnaryNot(node) ||
71                 isNotEquals(node) ||
72                 isConditionalWithAllMatches(node) ||
73                 isParenthesisAroundMatch(node);
74     }
75
76     private static boolean isUnaryNot(SimpleNode node) {
77         // look for "!x"
78
return
79                 node instanceof ASTUnaryExpressionNotPlusMinus &&
80                 "!".equals(node.getImage());
81     }
82
83     private static boolean isNotEquals(SimpleNode node) {
84         // look for "x != y"
85
return
86                 node instanceof ASTEqualityExpression &&
87                 "!=".equals(node.getImage());
88     }
89
90     private static boolean isConditionalWithAllMatches(SimpleNode node) {
91         // look for "match && match" or "match || match"
92
if (!(node instanceof ASTConditionalAndExpression) &&
93                 !(node instanceof ASTConditionalOrExpression)) {
94             return false;
95         }
96         int i_max = node.jjtGetNumChildren();
97         if (i_max <= 0) {
98             return false;
99         }
100         for (int i = 0; i < i_max; i++) {
101             SimpleNode inode = (SimpleNode) node.jjtGetChild(i);
102             // recurse!
103
if (!isMatch(inode)) {
104                 return false;
105             }
106         }
107         // all match
108
return true;
109     }
110
111     private static boolean isParenthesisAroundMatch(SimpleNode node) {
112         // look for "(match)"
113
if (!(node instanceof ASTPrimaryExpression) ||
114                 (node.jjtGetNumChildren() != 1)) {
115             return false;
116         }
117         SimpleNode inode = (SimpleNode) node.jjtGetChild(0);
118         if (!(inode instanceof ASTPrimaryPrefix) ||
119                 (inode.jjtGetNumChildren() != 1)) {
120             return false;
121         }
122         SimpleNode jnode = (SimpleNode) inode.jjtGetChild(0);
123         if (!(jnode instanceof ASTExpression) ||
124                 (jnode.jjtGetNumChildren() != 1)) {
125             return false;
126         }
127         SimpleNode knode = (SimpleNode) jnode.jjtGetChild(0);
128         // recurse!
129
return isMatch(knode);
130     }
131 }
132
Popular Tags