KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > pmd > rules > AbstractPoorMethodCall


1 package net.sourceforge.pmd.rules;
2
3 import net.sourceforge.pmd.AbstractRule;
4 import net.sourceforge.pmd.ast.ASTAdditiveExpression;
5 import net.sourceforge.pmd.ast.ASTLiteral;
6 import net.sourceforge.pmd.ast.ASTPrimaryExpression;
7 import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
8 import net.sourceforge.pmd.ast.SimpleNode;
9 import net.sourceforge.pmd.symboltable.NameOccurrence;
10
11 import java.util.Iterator JavaDoc;
12 import java.util.List JavaDoc;
13
14 /**
15  * Detects and flags the occurrences of specific method calls against an instance of
16  * a designated class. I.e. String.indexOf. The goal is to be able to suggest more
17  * efficient/modern ways of implementing the same function.
18  *
19  * Concrete subclasses are expected to provide the name of the target class and an
20  * array of method names that we are looking for. We then pass judgement on any literal
21  * arguments we find in the subclass as well.
22  *
23  * @author Brian Remedios
24  * @version $Revision: 1.1 $
25  */

26 public abstract class AbstractPoorMethodCall extends AbstractRule {
27     
28     
29     /**
30      * The name of the type the method will be invoked against.
31      * @return String
32      */

33     protected abstract String JavaDoc targetTypename();
34     
35     /**
36      * Return the names of all the methods we are scanning for, no brackets or
37      * argument types.
38      *
39      * @return String[]
40      */

41     protected abstract String JavaDoc[] methodNames();
42     
43     /**
44      * Returns whether the string argument at the stated position being sent to
45      * the method is ok or not. Return true if you want to record the method call
46      * as a violation, false otherwise.
47      *
48      * @param argIndex int
49      * @param arg String
50      * @return boolean
51      */

52     protected abstract boolean isViolationArgument(int argIndex, String JavaDoc arg);
53     
54     /**
55      * Returns whether the name occurrence is one of the method calls
56      * we are interested in.
57      *
58      * @param occurrence NameOccurrence
59      * @return boolean
60      */

61     private boolean isNotedMethod(NameOccurrence occurrence) {
62         
63         if (occurrence == null) return false;
64         
65         String JavaDoc methodCall = occurrence.getImage();
66         String JavaDoc[] methodNames = methodNames();
67         
68         for (int i=0; i<methodNames.length; i++) {
69             if (methodCall.indexOf(methodNames[i]) != -1) return true;
70         }
71         return false;
72     }
73         
74     /**
75      * Returns whether the value argument is a single character string.
76      *
77      * @param value String
78      * @return boolean
79      */

80     public static boolean isSingleCharAsString(String JavaDoc value) {
81         return value.length() == 3 && value.charAt(0) == '\"';
82     }
83     
84     /**
85      * Method visit.
86      * @param node ASTVariableDeclaratorId
87      * @param data Object
88      * @return Object
89      * @see net.sourceforge.pmd.ast.JavaParserVisitor#visit(ASTVariableDeclaratorId, Object)
90      */

91     public Object JavaDoc visit(ASTVariableDeclaratorId node, Object JavaDoc data) {
92         
93         if (!node.getNameDeclaration().getTypeImage().equals(targetTypename())) {
94             return data;
95         }
96         
97         for (Iterator JavaDoc i = node.getUsages().iterator(); i.hasNext();) {
98             NameOccurrence occ = (NameOccurrence) i.next();
99             if (isNotedMethod(occ.getNameForWhichThisIsAQualifier())) {
100                 SimpleNode parent = (SimpleNode)occ.getLocation().jjtGetParent().jjtGetParent();
101                 if (parent instanceof ASTPrimaryExpression) {
102                     // bail out if it's something like indexOf("a" + "b")
103
List JavaDoc additives = parent.findChildrenOfType(ASTAdditiveExpression.class);
104                     if (!additives.isEmpty()) {
105                         return data;
106                     }
107                     List JavaDoc literals = parent.findChildrenOfType(ASTLiteral.class);
108                     for (int l=0; l<literals.size(); l++) {
109                         ASTLiteral literal = (ASTLiteral)literals.get(l);
110                         if (isViolationArgument(l, literal.getImage())) {
111                             addViolation(data, occ.getLocation());
112                         }
113                     }
114                 }
115             }
116         }
117         return data;
118     }
119 }
120
121
Popular Tags