PositionalIteratorRule.java
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"!= -&& 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(0instanceof 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(0instanceof ASTName) {
71                 return ((ASTNamenode.jjtGetChild(0)).getImage();
72             else {
73           return getName(node.jjtGetChild(0));
74             }
75         }
76         throw new IllegalArgumentException("Check with hasNameAsChild() first!");
77     }
78 }