View Javadoc

    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.ASTBlock;
    8   import net.sourceforge.pmd.ast.ASTBlockStatement;
    9   import net.sourceforge.pmd.ast.ASTBooleanLiteral;
    10  import net.sourceforge.pmd.ast.ASTIfStatement;
    11  import net.sourceforge.pmd.ast.ASTReturnStatement;
    12  import net.sourceforge.pmd.ast.ASTStatement;
    13  import net.sourceforge.pmd.ast.SimpleNode;
    14
    15  public class SimplifyBooleanReturns extends AbstractRule {
    16
    17      public Object visit(ASTIfStatement node, Object data) {
    18          // only deal with if..then..else stmts
    19          if (node.jjtGetNumChildren() != 3) {
    20              return super.visit(node, data);
    21          }
    22
    23          // don't bother if either the if or the else block is empty
    24          if (node.jjtGetChild(1).jjtGetNumChildren() == 0 || node.jjtGetChild(2).jjtGetNumChildren() == 0) {
    25              return super.visit(node, data);
    26          }
    27
    28          // first case:
    29          // If
    30          //  Expr
    31          //  Statement
    32          //   ReturnStatement
    33          //  Statement
    34          //   ReturnStatement
    35          // i.e.,
    36          // if (foo)
    37          //  return true;
    38          // else
    39          //  return false;
    40
    41          // second case
    42          // If
    43          // Expr
    44          // Statement
    45          //  Block
    46          //   BlockStatement
    47          //    Statement
    48          //     ReturnStatement
    49          // Statement
    50          //  Block
    51          //   BlockStatement
    52          //    Statement
    53          //     ReturnStatement
    54          // i.e.,
    55          // if (foo) {
    56          //  return true;
    57          // } else {
    58          //  return false;
    59          // }
    60          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))) {
    61              addViolation(data, node);
    62          } 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))) {
    63              addViolation(data, node);
    64          }
    65
    66          return super.visit(node, data);
    67      }
    68
    69      private boolean hasOneBlockStmt(SimpleNode node) {
    70          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;
    71      }
    72
    73      private boolean terminatesInBooleanLiteral(SimpleNode node) {
    74          return eachNodeHasOneChild(node) && (getLastChild(node) instanceof ASTBooleanLiteral);
    75      }
    76
    77      private boolean eachNodeHasOneChild(SimpleNode node) {
    78          if (node.jjtGetNumChildren() > 1) {
    79              return false;
    80          }
    81          if (node.jjtGetNumChildren() == 0) {
    82              return true;
    83          }
    84          return eachNodeHasOneChild((SimpleNode) node.jjtGetChild(0));
    85      }
    86
    87      private SimpleNode getLastChild(SimpleNode node) {
    88          if (node.jjtGetNumChildren() == 0) {
    89              return node;
    90          }
    91          return getLastChild((SimpleNode) node.jjtGetChild(0));
    92      }
    93  }