View Javadoc

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