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.RuleContext;
8 import net.sourceforge.pmd.ast.ASTBlock;
9 import net.sourceforge.pmd.ast.ASTBlockStatement;
10 import net.sourceforge.pmd.ast.ASTBooleanLiteral;
11 import net.sourceforge.pmd.ast.ASTIfStatement;
12 import net.sourceforge.pmd.ast.ASTReturnStatement;
13 import net.sourceforge.pmd.ast.ASTStatement;
14 import net.sourceforge.pmd.ast.SimpleNode;
15
16 public class SimplifyBooleanReturns extends AbstractRule {
17
18 public Object visit(ASTIfStatement node, Object data) {
19
20 if (node.jjtGetNumChildren() != 3) {
21 return super.visit(node, data);
22 }
23
24
25 if (node.jjtGetChild(1).jjtGetNumChildren() == 0 || node.jjtGetChild(2).jjtGetNumChildren() == 0) {
26 return super.visit(node, data);
27 }
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 if (node.jjtGetChild(1).jjtGetChild(0) instanceof ASTReturnStatement && node.jjtGetChild(2).jjtGetChild(0) instanceof ASTReturnStatement && terminatesInBooleanLiteral((SimpleNode) node.jjtGetChild(1).jjtGetChild(0)) && terminatesInBooleanLiteral((SimpleNode) node.jjtGetChild(2).jjtGetChild(0))) {
62 RuleContext ctx = (RuleContext) data;
63 ctx.getReport().addRuleViolation(createRuleViolation(ctx, node));
64 } else if (hasOneBlockStmt((SimpleNode) node.jjtGetChild(1)) && hasOneBlockStmt((SimpleNode) node.jjtGetChild(2)) && terminatesInBooleanLiteral((SimpleNode) node.jjtGetChild(1).jjtGetChild(0)) && terminatesInBooleanLiteral((SimpleNode) node.jjtGetChild(2).jjtGetChild(0))) {
65 RuleContext ctx = (RuleContext) data;
66 ctx.getReport().addRuleViolation(createRuleViolation(ctx, node));
67 }
68
69 return super.visit(node, data);
70 }
71
72 private boolean hasOneBlockStmt(SimpleNode node) {
73 return node.jjtGetChild(0) instanceof ASTBlock && node.jjtGetChild(0).jjtGetNumChildren() == 1 && node.jjtGetChild(0).jjtGetChild(0) instanceof ASTBlockStatement && node.jjtGetChild(0).jjtGetChild(0).jjtGetChild(0) instanceof ASTStatement && node.jjtGetChild(0).jjtGetChild(0).jjtGetChild(0).jjtGetChild(0) instanceof ASTReturnStatement;
74 }
75
76 private boolean terminatesInBooleanLiteral(SimpleNode node) {
77 return eachNodeHasOneChild(node) && (getLastChild(node) instanceof ASTBooleanLiteral);
78 }
79
80 private boolean eachNodeHasOneChild(SimpleNode node) {
81 if (node.jjtGetNumChildren() > 1) {
82 return false;
83 }
84 if (node.jjtGetNumChildren() == 0) {
85 return true;
86 }
87 return eachNodeHasOneChild((SimpleNode) node.jjtGetChild(0));
88 }
89
90 private SimpleNode getLastChild(SimpleNode node) {
91 if (node.jjtGetNumChildren() == 0) {
92 return node;
93 }
94 return getLastChild((SimpleNode) node.jjtGetChild(0));
95 }
96 }