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.RuleContext;
8 import net.sourceforge.pmd.ast.ASTAdditiveExpression;
9 import net.sourceforge.pmd.ast.ASTAllocationExpression;
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.ASTStatement;
15
16
17
18
19
20
21
22
23
24
25 public final class AvoidConcatenatingNonLiteralsInStringBuffer extends AbstractRule {
26
27 public final Object visit(ASTAdditiveExpression node, Object data) {
28 final ASTBlockStatement bs = (ASTBlockStatement) node.getFirstParentOfType(ASTBlockStatement.class);
29 if (bs == null) {
30 return data;
31 }
32
33 if (!concatsLiteralAndNonLiteral(node)) {
34 return data;
35 }
36
37 if (bs.isAllocation()) {
38 if (isAllocatedStringBuffer(node)) {
39 addViolation((RuleContext) data, node);
40 }
41 } else if (isInStringBufferAppend(node)) {
42 addViolation((RuleContext) data, node);
43 }
44 return data;
45 }
46
47 private final boolean concatsLiteralAndNonLiteral(final ASTAdditiveExpression node) {
48 return node.containsChildOfType(ASTName.class) && node.containsChildOfType(ASTLiteral.class);
49 }
50
51 private final boolean isInStringBufferAppend(final ASTAdditiveExpression node) {
52 final ASTStatement s = (ASTStatement) node.getFirstParentOfType(ASTStatement.class);
53 if (s == null) {
54 return false;
55 }
56 final ASTName n = (ASTName) s.getFirstChildOfType(ASTName.class);
57 return n.getImage()!=null && n.getImage().endsWith("append");
58 }
59
60 private final boolean isAllocatedStringBuffer(final ASTAdditiveExpression node) {
61 final ASTAllocationExpression ao = (ASTAllocationExpression) node.getFirstParentOfType(ASTAllocationExpression.class);
62 if (ao == null) {
63 return false;
64 }
65
66 final ASTClassOrInterfaceType an = (ASTClassOrInterfaceType) ao.getFirstChildOfType(ASTClassOrInterfaceType.class);
67 return an != null && an.getImage().endsWith("StringBuffer");
68 }
69 }
70