01: /**
02: * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03: */package net.sourceforge.pmd.rules.design;
04:
05: import net.sourceforge.pmd.AbstractRule;
06: import net.sourceforge.pmd.ast.ASTName;
07: import net.sourceforge.pmd.ast.ASTWhileStatement;
08: import net.sourceforge.pmd.ast.SimpleNode;
09:
10: import java.util.ArrayList;
11: import java.util.List;
12:
13: public class PositionalIteratorRule extends AbstractRule {
14:
15: public Object visit(ASTWhileStatement node, Object data) {
16: if (hasNameAsChild((SimpleNode) node.jjtGetChild(0))) {
17: String exprName = getName((SimpleNode) node.jjtGetChild(0));
18: if (exprName.indexOf(".hasNext") != -1
19: && node.jjtGetNumChildren() > 1) {
20:
21: SimpleNode loopBody = (SimpleNode) node.jjtGetChild(1);
22: List<String> names = new ArrayList<String>();
23: collectNames(getVariableName(exprName), names, loopBody);
24: int nextCount = 0;
25: for (String name : names) {
26: if (name.indexOf(".next") != -1) {
27: nextCount++;
28: }
29: }
30:
31: if (nextCount > 1) {
32: addViolation(data, node);
33: }
34:
35: }
36: }
37: return null;
38: }
39:
40: private String getVariableName(String exprName) {
41: return exprName.substring(0, exprName.indexOf('.'));
42: }
43:
44: private void collectNames(String target, List<String> names,
45: SimpleNode node) {
46: for (int i = 0; i < node.jjtGetNumChildren(); i++) {
47: SimpleNode child = (SimpleNode) node.jjtGetChild(i);
48: if (child.jjtGetNumChildren() > 0) {
49: collectNames(target, names, child);
50: } else {
51: if (child instanceof ASTName
52: && isQualifiedName(child)
53: && target.equals(getVariableName(child
54: .getImage()))) {
55: names.add(child.getImage());
56: }
57: }
58: }
59: }
60:
61: private boolean hasNameAsChild(SimpleNode node) {
62: while (node.jjtGetNumChildren() > 0) {
63: if (node.jjtGetChild(0) instanceof ASTName) {
64: return true;
65: }
66: return hasNameAsChild((SimpleNode) node.jjtGetChild(0));
67: }
68: return false;
69: }
70:
71: private String getName(SimpleNode node) {
72: while (node.jjtGetNumChildren() > 0) {
73: if (node.jjtGetChild(0) instanceof ASTName) {
74: return ((ASTName) node.jjtGetChild(0)).getImage();
75: }
76: return getName((SimpleNode) node.jjtGetChild(0));
77: }
78: throw new IllegalArgumentException(
79: "Check with hasNameAsChild() first!");
80: }
81: }
|