01: package org.acm.seguin.pmd.rules.design;
02:
03: import org.acm.seguin.pmd.AbstractRule;
04: import org.acm.seguin.pmd.RuleContext;
05: import net.sourceforge.jrefactory.ast.ASTName;
06: import net.sourceforge.jrefactory.ast.ASTWhileStatement;
07: import net.sourceforge.jrefactory.ast.SimpleNode;
08:
09: import java.util.ArrayList;
10: import java.util.Iterator;
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.jjtGetFirstChild())) {
17: String exprName = getName((SimpleNode) node
18: .jjtGetFirstChild());
19: if (exprName.indexOf(".hasNext") != -1
20: && 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: RuleContext ctx = (RuleContext) data;
35: ctx.getReport().addRuleViolation(
36: createRuleViolation(ctx, node
37: .getBeginLine()));
38: }
39:
40: }
41: }
42: return null;
43: }
44:
45: private String getVariableName(String exprName) {
46: return exprName.substring(0, exprName.indexOf('.'));
47: }
48:
49: private void collectNames(String target, List names, SimpleNode node) {
50: for (int i = 0; i < node.jjtGetNumChildren(); i++) {
51: SimpleNode child = (SimpleNode) node.jjtGetChild(i);
52: if (child instanceof ASTName
53: && child.getImage().indexOf(".") != -1
54: && target.equals(getVariableName(child.getImage()))) {
55: names.add(child.getImage());
56: } else if (child.jjtGetNumChildren() > 0) {
57: collectNames(target, names, child);
58: } else {
59: }
60: }
61: }
62:
63: private boolean hasNameAsChild(SimpleNode node) {
64: SimpleNode child = node;
65: while (child.jjtGetNumChildren() > 0) {
66: if (child instanceof ASTName) {
67: return true;
68: }
69: child = (SimpleNode) child.jjtGetFirstChild();
70: }
71: return false;
72: }
73:
74: private String getName(SimpleNode node) {
75: SimpleNode child = node;
76: while (child.jjtGetNumChildren() > 0) {
77: if (child instanceof ASTName) {
78: return ((ASTName) child).getImage();
79: }
80: child = (SimpleNode) child.jjtGetFirstChild();
81: }
82: throw new IllegalArgumentException(
83: "Check with hasNameAsChild() first!");
84: }
85: }
|