/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.java.rule.controversial; import net.sourceforge.pmd.lang.java.ast.ASTAssignmentOperator; import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression; import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTName; import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral; import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; import net.sourceforge.pmd.lang.java.ast.AccessNode; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; // TODO - should check that this is not the first assignment. e.g., this is OK: // Object x; // x = null; public class NullAssignmentRule extends AbstractJavaRule { @Override public Object visit(ASTNullLiteral node, Object data) { if (node.getNthParent(5) instanceof ASTStatementExpression) { ASTStatementExpression n = (ASTStatementExpression) node.getNthParent(5); if (isAssignmentToFinalField(n)) { return data; } if (n.jjtGetNumChildren() > 2 && n.jjtGetChild(1) instanceof ASTAssignmentOperator) { addViolation(data, node); } } else if (node.getNthParent(4) instanceof ASTConditionalExpression) { // "false" expression of ternary if (isBadTernary((ASTConditionalExpression) node.getNthParent(4))) { addViolation(data, node); } } else if (node.getNthParent(5) instanceof ASTConditionalExpression && node.getNthParent(4) instanceof ASTExpression) { // "true" expression of ternary if (isBadTernary((ASTConditionalExpression) node.getNthParent(5))) { addViolation(data, node); } } return data; } private boolean isAssignmentToFinalField(ASTStatementExpression n) { ASTName name = n.getFirstDescendantOfType(ASTName.class); return name != null && name.getNameDeclaration() instanceof VariableNameDeclaration && ((AccessNode) ((VariableNameDeclaration) name.getNameDeclaration()).getAccessNodeParent()).isFinal(); } private boolean isBadTernary(ASTConditionalExpression n) { return n.isTernary() && !(n.jjtGetChild(0) instanceof ASTEqualityExpression); } }