View Javadoc

    1   package net.sourceforge.pmd.rules;
    2
    3   import net.sourceforge.pmd.AbstractRule;
    4   import net.sourceforge.pmd.ast.ASTEqualityExpression;
    5   import net.sourceforge.pmd.ast.ASTLiteral;
    6   import net.sourceforge.pmd.ast.ASTPrimitiveType;
    7   import net.sourceforge.pmd.ast.ASTRelationalExpression;
    8   import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
    9   import net.sourceforge.pmd.ast.SimpleNode;
    10  import net.sourceforge.pmd.symboltable.NameOccurrence;
    11
    12  import java.util.List;
    13
    14  /**
    15   * This is an abstract rule for patterns which compare a method invocation to 0.
    16   * It could be further abstracted to find code that compares something to
    17   * another definable pattern
    18   *
    19   * @author acaplan
    20   */
    21  public abstract class AbstractInefficientZeroCheck extends AbstractRule {
    22
    23      public abstract boolean appliesToClassName(String name);
    24
    25      public abstract boolean isTargetMethod(NameOccurrence occ);
    26
    27      public Object visit(ASTVariableDeclaratorId node, Object data) {
    28          SimpleNode nameNode = node.getTypeNameNode();
    29          if (nameNode instanceof ASTPrimitiveType) {
    30              return data;
    31          }
    32          if (!appliesToClassName(node.getNameDeclaration().getTypeImage())) {
    33              return data;
    34          }
    35
    36          List<NameOccurrence> declars = node.getUsages();
    37          for (NameOccurrence occ: declars) {
    38              if (!isTargetMethod(occ)) {
    39                  continue;
    40              }
    41              SimpleNode expr = (SimpleNode) occ.getLocation().jjtGetParent().jjtGetParent().jjtGetParent();
    42              if ((expr instanceof ASTEqualityExpression ||
    43                      (expr instanceof ASTRelationalExpression && ">".equals(expr.getImage())))
    44                  && isCompareZero(expr)) {
    45                  addViolation(data, occ.getLocation());
    46              }
    47          }
    48          return data;
    49      }
    50
    51      /**
    52       * We only need to report if this is comparing against 0
    53       *
    54       * @param equality
    55       * @return true if this is comparing to 0 else false
    56       */
    57      private boolean isCompareZero(SimpleNode equality) {
    58          return (checkComparison(equality, 0) || checkComparison(equality, 1));
    59
    60      }
    61
    62      /**
    63       * Checks if the equality expression passed in is of comparing against the
    64       * value passed in as i
    65       *
    66       * @param equality
    67       * @param i
    68       *            The ordinal in the equality expression to check
    69       * @return true if the value in position i is 0, else false
    70       */
    71      private boolean checkComparison(SimpleNode equality, int i) {
    72          SimpleNode target = (SimpleNode) equality.jjtGetChild(i).jjtGetChild(0);
    73          if (target.jjtGetNumChildren() == 0) {
    74              return false;
    75          }
    76          target = (SimpleNode) target.jjtGetChild(0);
    77          return (target instanceof ASTLiteral && "0".equals(target.getImage()));
    78      }
    79
    80  }