1 4 package net.sourceforge.pmd.rules.strings; 5 6 import net.sourceforge.pmd.AbstractRule; 7 import net.sourceforge.pmd.ast.ASTAdditiveExpression; 8 import net.sourceforge.pmd.ast.ASTAllocationExpression; 9 import net.sourceforge.pmd.ast.ASTArgumentList; 10 import net.sourceforge.pmd.ast.ASTBlockStatement; 11 import net.sourceforge.pmd.ast.ASTClassOrInterfaceType; 12 import net.sourceforge.pmd.ast.ASTLiteral; 13 import net.sourceforge.pmd.ast.ASTName; 14 import net.sourceforge.pmd.ast.ASTStatementExpression; 15 import net.sourceforge.pmd.ast.Node; 16 import net.sourceforge.pmd.ast.SimpleNode; 17 import net.sourceforge.pmd.symboltable.VariableNameDeclaration; 18 19 import java.util.Iterator ; 20 import java.util.List ; 21 22 31 public class InefficientStringBuffering extends AbstractRule { 32 33 public Object visit(ASTAdditiveExpression node, Object data) { 34 ASTBlockStatement bs = (ASTBlockStatement) node.getFirstParentOfType(ASTBlockStatement.class); 35 if (bs == null) { 36 return data; 37 } 38 39 int immediateLiterals = 0; 40 List nodes = node.findChildrenOfType(ASTLiteral.class); 41 for (Iterator i = nodes.iterator();i.hasNext();) { 42 ASTLiteral literal = (ASTLiteral)i.next(); 43 if (literal.jjtGetParent().jjtGetParent().jjtGetParent() instanceof ASTAdditiveExpression) { 44 immediateLiterals++; 45 } 46 try { 47 Integer.parseInt(literal.getImage()); 48 return data; 49 } catch (NumberFormatException nfe) { 50 } 52 } 53 54 if (immediateLiterals > 1) { 55 return data; 56 } 57 58 List nameNodes = node.findChildrenOfType(ASTName.class); 60 for (Iterator i = nameNodes.iterator(); i.hasNext();) { 61 ASTName name = (ASTName)i.next(); 62 if (name.getNameDeclaration() instanceof VariableNameDeclaration) { 63 VariableNameDeclaration vnd = (VariableNameDeclaration)name.getNameDeclaration(); 64 if (vnd.getAccessNodeParent().isFinal() && vnd.getAccessNodeParent().isStatic()) { 65 return data; 66 } 67 } 68 } 69 70 71 if (bs.isAllocation()) { 72 if (isAllocatedStringBuffer(node)) { 73 addViolation(data, node); 74 } 75 } else if (isInStringBufferOperation(node, 6, "append")) { 76 addViolation(data, node); 77 } 78 return data; 79 } 80 81 protected static boolean isInStringBufferOperation(SimpleNode node, int length, String methodName) { 82 if (!xParentIsStatementExpression(node, length)) { 83 return false; 84 } 85 ASTStatementExpression s = (ASTStatementExpression) node.getFirstParentOfType(ASTStatementExpression.class); 86 if (s == null) { 87 return false; 88 } 89 ASTName n = (ASTName)s.getFirstChildOfType(ASTName.class); 90 if (n == null || n.getImage().indexOf(methodName) == -1 || !(n.getNameDeclaration() instanceof VariableNameDeclaration)) { 91 return false; 92 } 93 94 ASTArgumentList argList = (ASTArgumentList)s.getFirstChildOfType(ASTArgumentList.class); 99 if (argList == null || argList.jjtGetNumChildren() > 1) { 100 return false; 101 } 102 103 return ((VariableNameDeclaration)n.getNameDeclaration()).getTypeImage().equals("StringBuffer"); 104 } 105 106 private static boolean xParentIsStatementExpression(SimpleNode node, int length) { 108 Node curr = node; 109 for (int i=0; i<length; i++) { 110 if (node.jjtGetParent() == null) { 111 return false; 112 } 113 curr = curr.jjtGetParent(); 114 } 115 return curr instanceof ASTStatementExpression; 116 } 117 118 private boolean isAllocatedStringBuffer(ASTAdditiveExpression node) { 119 ASTAllocationExpression ao = (ASTAllocationExpression) node.getFirstParentOfType(ASTAllocationExpression.class); 120 if (ao == null) { 121 return false; 122 } 123 ASTClassOrInterfaceType an = (ASTClassOrInterfaceType) ao.getFirstChildOfType(ASTClassOrInterfaceType.class); 125 return an != null && (an.getImage().endsWith("StringBuffer") || an.getImage().endsWith("StringBuilder")); 126 } 127 } 128 129 | Popular Tags |