View Javadoc

    1   package net.sourceforge.pmd.rules;
    2
    3   import java.util.Iterator;
    4   import java.util.Set;
    5
    6   import net.sourceforge.pmd.AbstractRule;
    7   import net.sourceforge.pmd.ast.ASTExpression;
    8   import net.sourceforge.pmd.ast.ASTLocalVariableDeclaration;
    9   import net.sourceforge.pmd.ast.ASTName;
    10  import net.sourceforge.pmd.ast.ASTType;
    11  import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
    12  import net.sourceforge.pmd.symboltable.NameOccurrence;
    13  import net.sourceforge.pmd.util.CollectionUtil;
    14
    15  /***
    16   * An operation on an Immutable object (BigDecimal or BigInteger) won't change
    17   * the object itself. The result of the operation is a new object. Therefore,
    18   * ignoring the operation result is an error.
    19   */
    20  public class UselessOperationOnImmutable extends AbstractRule {
    21
    22      /***
    23       * These are the methods which are immutable
    24       */
    25      private static final Set targetMethods = CollectionUtil.asSet(new String[] { ".add", ".multiply", ".divide", ".subtract", ".setScale", ".negate", ".movePointLeft", ".movePointRight", ".pow", ".shiftLeft", ".shiftRight" });
    26
    27      /***
    28       * These are the classes that the rule can apply to
    29       */
    30      private static final Set targetClasses = CollectionUtil.asSet(new String[] { "java.math.BigDecimal", "BigDecimal", "java.math.BigInteger", "BigInteger" });
    31
    32      public Object visit(ASTLocalVariableDeclaration node, Object data) {
    33
    34          ASTVariableDeclaratorId var = getDeclaration(node);
    35          if (var == null) {
    36              return super.visit(node, data);
    37          }
    38          String variableName = var.getImage();
    39          for (Iterator it = var.getUsages().iterator(); it.hasNext();) {
    40              NameOccurrence no = (NameOccurrence) it.next();
    41              ASTName sn = (ASTName) no.getLocation();
    42              if (!sn.jjtGetParent().jjtGetParent().jjtGetParent().getClass().equals(ASTExpression.class)) {
    43                  String methodCall = sn.getImage().substring(variableName.length());
    44                  if (targetMethods.contains(methodCall)) {
    45                      addViolation(data, sn);
    46                  }
    47              }
    48          }
    49          return super.visit(node, data);
    50      }
    51
    52      /***
    53       * This method checks the variable declaration if it is on a class we care
    54       * about. If it is, it returns the DeclaratorId
    55       *
    56       * @param node
    57       *            The ASTLocalVariableDeclaration which is a problem
    58       * @return ASTVariableDeclaratorId
    59       */
    60      private ASTVariableDeclaratorId getDeclaration(ASTLocalVariableDeclaration node) {
    61          ASTType type = node.getTypeNode();
    62          if (targetClasses.contains(type.getTypeImage())) {
    63              return (ASTVariableDeclaratorId) node.jjtGetChild(1).jjtGetChild(0);
    64          }
    65          return null;
    66      }
    67  }