View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.lang.java.rule.controversial;
    5
    6   import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator;
    7   import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression;
    8   import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression;
    9   import net.sourceforge.pmd.lang.java.ast.ASTExpression;
    10  import net.sourceforge.pmd.lang.java.ast.ASTName;
    11  import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral;
    12  import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression;
    13  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
    14  import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
    15
    16  // TODO - should check that this is not the first assignment.  e.g., this is OK:
    17  // Object x;
    18  // x = null;
    19  public class NullAssignmentRule extends AbstractJavaRule {
    20
    21      @Override
    22      public Object visit(ASTNullLiteral node, Object data) {
    23
    24          if (node.getNthParent(5) instanceof ASTStatementExpression) {
    25              ASTStatementExpression n = (ASTStatementExpression) node.getNthParent(5);
    26
    27              if (isAssignmentToFinalField(n)) {
    28                  return data;
    29              }
    30
    31              if (n.jjtGetNumChildren() > 2 && n.jjtGetChild(1) instanceof ASTAssignmentOperator) {
    32                  addViolation(data, node);
    33              }
    34          } else if (node.getNthParent(4) instanceof ASTConditionalExpression) {
    35              // "false" expression of ternary
    36              if (isBadTernary((ASTConditionalExpression)node.getNthParent(4))) {
    37                  addViolation(data, node);
    38              }
    39          } else if (node.getNthParent(5) instanceof ASTConditionalExpression && node.getNthParent(4) instanceof ASTExpression) {
    40              // "true" expression of ternary
    41              if (isBadTernary((ASTConditionalExpression)node.getNthParent(5))) {
    42                  addViolation(data, node);
    43              }
    44          }
    45
    46          return data;
    47      }
    48
    49      private boolean isAssignmentToFinalField(ASTStatementExpression n) {
    50          ASTName name = n.getFirstDescendantOfType(ASTName.class);
    51          return name != null
    52                  && name.getNameDeclaration() instanceof VariableNameDeclaration
    53                  && ((VariableNameDeclaration) name.getNameDeclaration()).getAccessNodeParent().isFinal();
    54      }
    55
    56      private boolean isBadTernary(ASTConditionalExpression n) {
    57          return n.isTernary() && !(n.jjtGetChild(0) instanceof ASTEqualityExpression);
    58      }
    59  }