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