View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    3    */
    4   package net.sourceforge.pmd.lang.java.rule.design;
    5
    6   import java.util.ArrayList;
    7   import java.util.List;
    8
    9   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  }