01 /**
02 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03 */
04 package net.sourceforge.pmd.lang.java.rule.design;
05
06 import java.util.ArrayList;
07 import java.util.List;
08
09 import net.sourceforge.pmd.lang.ast.Node;
10 import net.sourceforge.pmd.lang.java.ast.ASTName;
11 import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement;
12 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
13
14 public class PositionalIteratorRule extends AbstractJavaRule {
15
16 public Object visit(ASTWhileStatement node, Object data) {
17 if (hasNameAsChild(node.jjtGetChild(0))) {
18 String exprName = getName(node.jjtGetChild(0));
19 if (exprName.indexOf(".hasNext") != -1 && node.jjtGetNumChildren() > 1) {
20
21 Node loopBody = 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, Node node) {
45 for (int i = 0; i < node.jjtGetNumChildren(); i++) {
46 Node child = node.jjtGetChild(i);
47 if (child.jjtGetNumChildren() > 0) {
48 collectNames(target, names, child);
49 } else {
50 if (child instanceof ASTName && isQualifiedName(child) && target.equals(getVariableName(child.getImage()))) {
51 names.add(child.getImage());
52 }
53 }
54 }
55 }
56
57 private boolean hasNameAsChild(Node node) {
58 if (node.jjtGetNumChildren() > 0) {
59 if (node.jjtGetChild(0) instanceof ASTName) {
60 return true;
61 } else {
62 return hasNameAsChild(node.jjtGetChild(0));
63 }
64 }
65 return false;
66 }
67
68 private String getName(Node node) {
69 if (node.jjtGetNumChildren() > 0) {
70 if (node.jjtGetChild(0) instanceof ASTName) {
71 return ((ASTName) node.jjtGetChild(0)).getImage();
72 } else {
73 return getName(node.jjtGetChild(0));
74 }
75 }
76 throw new IllegalArgumentException("Check with hasNameAsChild() first!");
77 }
78 }
|