/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.java.rule.basic; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression; import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpressionNotPlusMinus; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; public class AvoidMultipleUnaryOperatorsRule extends AbstractJavaRule { public AvoidMultipleUnaryOperatorsRule() { super.addRuleChainVisit(ASTUnaryExpression.class); super.addRuleChainVisit(ASTUnaryExpressionNotPlusMinus.class); } @Override public Object visit(ASTUnaryExpression node, Object data) { checkUnaryDescendent(node, data); return data; } @Override public Object visit(ASTUnaryExpressionNotPlusMinus node, Object data) { checkUnaryDescendent(node, data); return data; } private void checkUnaryDescendent(Node node, Object data) { boolean match = false; if (node.jjtGetNumChildren() == 1) { Node child = node.jjtGetChild(0); if (child instanceof ASTUnaryExpression || child instanceof ASTUnaryExpressionNotPlusMinus) { match = true; } else if (child instanceof ASTPrimaryExpression) { Node primaryExpression = child; // Skip down PrimaryExpression/PrimaryPrefix/Expression chains // created by parentheses while (true) { if (primaryExpression.jjtGetNumChildren() == 1 && primaryExpression.jjtGetChild(0) instanceof ASTPrimaryPrefix && primaryExpression.jjtGetChild(0).jjtGetNumChildren() == 1 && primaryExpression.jjtGetChild(0).jjtGetChild(0) instanceof ASTExpression && primaryExpression.jjtGetChild(0).jjtGetChild(0).jjtGetNumChildren() == 1) { Node candidate = primaryExpression.jjtGetChild(0).jjtGetChild(0).jjtGetChild(0); if (candidate instanceof ASTUnaryExpression || candidate instanceof ASTUnaryExpressionNotPlusMinus) { match = true; break; } else if (candidate instanceof ASTPrimaryExpression) { primaryExpression = candidate; continue; } else { break; } } else { break; } } } } if (match) { addViolation(data, node); } } }