KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > pmd > rules > strings > UseStringBufferLength


1 package net.sourceforge.pmd.rules.strings;
2
3 import net.sourceforge.pmd.AbstractRule;
4 import net.sourceforge.pmd.ast.ASTCompilationUnit;
5 import net.sourceforge.pmd.ast.ASTLiteral;
6 import net.sourceforge.pmd.ast.ASTName;
7 import net.sourceforge.pmd.ast.SimpleNode;
8 import net.sourceforge.pmd.symboltable.NameDeclaration;
9 import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
10
11 import java.util.HashSet JavaDoc;
12 import java.util.List JavaDoc;
13 import java.util.Set JavaDoc;
14
15
16 /**
17  * This rule finds places where StringBuffer.toString() is called just to see if
18  * the string is 0 length by either using .equals("") or toString().size()
19  * <p/>
20  * <pre>
21  * StringBuffer sb = new StringBuffer(&quot;some string&quot;);
22  * if (sb.toString().equals(&quot;&quot;)) {
23  * // this is wrong
24  * }
25  * if (sb.length() == 0) {
26  * // this is right
27  * }
28  * </pre>
29  *
30  * @author acaplan
31  */

32 public class UseStringBufferLength extends AbstractRule {
33
34     // FIXME Need to remove this somehow.
35
/*
36     Specifically, we need a symbol tree that can be traversed downwards, so that instead
37     of visiting each name and then visiting the declaration for that name, we should visit all
38     the declarations and check their usages.
39     With that in place, this rule would be reduced to:
40     - find all StringBuffer declarations
41     - check each usage
42     - flag those that involve variable.toString()
43     */

44     private Set JavaDoc alreadySeen = new HashSet JavaDoc();
45
46     public Object JavaDoc visit(ASTCompilationUnit acu, Object JavaDoc data) {
47         alreadySeen.clear();
48         return super.visit(acu, data);
49     }
50
51     public Object JavaDoc visit(ASTName decl, Object JavaDoc data) {
52         if (!decl.getImage().endsWith("toString")) {
53             return data;
54         }
55         NameDeclaration nd = decl.getNameDeclaration();
56         if (!(nd instanceof VariableNameDeclaration)) {
57             return data;
58         }
59         VariableNameDeclaration vnd = (VariableNameDeclaration) nd;
60         if (!vnd.getTypeImage().equals("StringBuffer") || alreadySeen.contains(vnd)) {
61             return data;
62         }
63         alreadySeen.add(vnd);
64
65         SimpleNode parent = (SimpleNode) decl.jjtGetParent().jjtGetParent();
66         for (int jx = 0; jx < parent.jjtGetNumChildren(); jx++) {
67             SimpleNode achild = (SimpleNode) parent.jjtGetChild(jx);
68             if (isViolation(parent, achild)) {
69                 addViolation(data, decl);
70             }
71         }
72
73         return data;
74     }
75
76     /**
77      * Check the given node if it calls either .equals or .size we need to check the target
78      */

79     private boolean isViolation(SimpleNode parent, SimpleNode achild) {
80         if ("equals".equals(achild.getImage())) {
81             List JavaDoc literals = parent.findChildrenOfType(ASTLiteral.class);
82             return (!literals.isEmpty() && "\"\"".equals(((SimpleNode) literals.get(0)).getImage()));
83         } else if ("length".equals(achild.getImage())) {
84             return true;
85         }
86         return false;
87     }
88
89
90 }
91
Popular Tags