1 /***
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.rules;
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.ASTBlockStatement;
10 import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
11 import net.sourceforge.pmd.ast.ASTLiteral;
12 import net.sourceforge.pmd.ast.ASTName;
13
14
15
16
17
18
19
20
21
22
23 public final class AvoidConcatenatingNonLiteralsInStringBuffer extends AbstractRule {
24
25 public Object visit(ASTAdditiveExpression node, Object data) {
26 ASTBlockStatement bs = (ASTBlockStatement) node.getFirstParentOfType(ASTBlockStatement.class);
27 if (bs == null) {
28 return data;
29 }
30
31 if (!concatsLiteralStringAndNonLiteral(node)) {
32 return data;
33 }
34
35 if (bs.isAllocation()) {
36 if (isAllocatedStringBuffer(node)) {
37 addViolation(data, node);
38 }
39 } else if (isInStringBufferAppend(node)) {
40 addViolation(data, node);
41 }
42 return data;
43 }
44
45 private boolean concatsLiteralStringAndNonLiteral(ASTAdditiveExpression node) {
46 if (!node.containsChildOfType(ASTName.class)) {
47 return false;
48 }
49 ASTLiteral n = (ASTLiteral)node.getFirstChildOfType(ASTLiteral.class);
50 if (n == null) {
51 return false;
52 }
53 try {
54 Integer.parseInt(n.getImage());
55 } catch (NumberFormatException nfe) {
56 return true;
57 }
58 return false;
59 }
60
61 private boolean isInStringBufferAppend(ASTAdditiveExpression node) {
62 ASTBlockStatement s = (ASTBlockStatement) node.getFirstParentOfType(ASTBlockStatement.class);
63 if (s == null) {
64 return false;
65 }
66 ASTName n = (ASTName) s.getFirstChildOfType(ASTName.class);
67 return n.getImage()!=null && n.getImage().endsWith("append");
68 }
69
70 private boolean isAllocatedStringBuffer(ASTAdditiveExpression node) {
71 ASTAllocationExpression ao = (ASTAllocationExpression) node.getFirstParentOfType(ASTAllocationExpression.class);
72 if (ao == null) {
73 return false;
74 }
75
76 ASTClassOrInterfaceType an = (ASTClassOrInterfaceType) ao.getFirstChildOfType(ASTClassOrInterfaceType.class);
77 return an != null && (an.getImage().endsWith("StringBuffer") || an.getImage().endsWith("StringBuilder"));
78 }
79 }
80