/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.design;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
public class PositionalIteratorRule extends AbstractJavaRule {
public Object visit(ASTWhileStatement node, Object data) {
if (hasNameAsChild(node.jjtGetChild(0))) {
String exprName = getName(node.jjtGetChild(0));
if (exprName.indexOf(".hasNext") != -1 && node.jjtGetNumChildren() > 1) {
Node loopBody = node.jjtGetChild(1);
List<String> names = new ArrayList<>();
collectNames(getVariableName(exprName), names, loopBody);
int nextCount = 0;
for (String name : names) {
if (name.indexOf(".next") != -1) {
nextCount++;
}
}
if (nextCount > 1) {
addViolation(data, node);
}
}
}
return null;
}
private String getVariableName(String exprName) {
return exprName.substring(0, exprName.indexOf('.'));
}
private void collectNames(String target, List<String> names, Node node) {
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
Node child = node.jjtGetChild(i);
if (child.jjtGetNumChildren() > 0) {
collectNames(target, names, child);
} else {
if (child instanceof ASTName && isQualifiedName(child)
&& target.equals(getVariableName(child.getImage()))) {
names.add(child.getImage());
}
}
}
}
private boolean hasNameAsChild(Node node) {
if (node.jjtGetNumChildren() > 0) {
if (node.jjtGetChild(0) instanceof ASTName) {
return true;
} else {
return hasNameAsChild(node.jjtGetChild(0));
}
}
return false;
}
private String getName(Node node) {
if (node.jjtGetNumChildren() > 0) {
if (node.jjtGetChild(0) instanceof ASTName) {
return ((ASTName) node.jjtGetChild(0)).getImage();
} else {
return getName(node.jjtGetChild(0));
}
}
throw new IllegalArgumentException("Check with hasNameAsChild() first!");
}
}