1 package net.sourceforge.pmd.lang.java.rule.strings;
2
3 import net.sourceforge.pmd.lang.ast.Node;
4 import net.sourceforge.pmd.lang.java.ast.ASTAdditiveExpression;
5 import net.sourceforge.pmd.lang.java.ast.ASTArgumentList;
6 import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
7 import net.sourceforge.pmd.lang.java.ast.ASTName;
8 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
9 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
10 import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
11 import net.sourceforge.pmd.lang.java.ast.ASTType;
12 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
13 import net.sourceforge.pmd.lang.java.symboltable.NameDeclaration;
14 import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
15
16 public class UselessStringValueOfRule extends AbstractJavaRule {
17
18 @Override
19 public Object visit(ASTPrimaryPrefix node, Object data) {
20 if (node.jjtGetNumChildren() == 0 ||
21 !(node.jjtGetChild(0) instanceof ASTName)) {
22 return super.visit(node, data);
23 }
24
25 String image = ((ASTName) node.jjtGetChild(0)).getImage();
26
27 if ("String.valueOf".equals(image)) {
28 Node parent = node.jjtGetParent();
29 if (parent.jjtGetNumChildren() != 2) {
30 return super.visit(node, data);
31 }
32
33 ASTArgumentList args = parent.getFirstDescendantOfType(ASTArgumentList.class);
34 if (args != null) {
35 ASTName arg = args.getFirstDescendantOfType(ASTName.class);
36 if (arg != null) {
37 NameDeclaration declaration = arg.getNameDeclaration();
38 if (declaration != null) {
39 ASTType argType = declaration.getNode().jjtGetParent().jjtGetParent().getFirstDescendantOfType(ASTType.class);
40 if (argType != null
41 && argType.jjtGetChild(0) instanceof ASTReferenceType
42 && ((ASTReferenceType)argType.jjtGetChild(0)).isArray()) {
43 return super.visit(node, data);
44 }
45 }
46 }
47 }
48
49 Node gp = parent.jjtGetParent();
50 if (parent instanceof ASTPrimaryExpression &&
51 gp instanceof ASTAdditiveExpression &&
52 "+".equals(gp.getImage())) {
53 boolean ok = false;
54 if (gp.jjtGetChild(0) == parent) {
55 ok = !isPrimitive(gp.jjtGetChild(1));
56 } else {
57 for (int i = 0; !ok && gp.jjtGetChild(i) != parent; i++) {
58 ok = !isPrimitive(gp.jjtGetChild(i));
59 }
60 }
61 if (ok) {
62 super.addViolation(data, node);
63 return data;
64 }
65 }
66 }
67 return super.visit(node, data);
68 }
69
70 private static boolean isPrimitive(Node parent) {
71 boolean result = false;
72 if (parent instanceof ASTPrimaryExpression && parent.jjtGetNumChildren() == 1) {
73 Node child = parent.jjtGetChild(0);
74 if (child instanceof ASTPrimaryPrefix && child.jjtGetNumChildren() == 1) {
75 Node gc = child.jjtGetChild(0);
76 if (gc instanceof ASTName) {
77 ASTName name = (ASTName) gc;
78 if (name.getNameDeclaration() instanceof VariableNameDeclaration) {
79 VariableNameDeclaration nd = (VariableNameDeclaration) name.getNameDeclaration();
80 if (nd.isPrimitiveType()) {
81 result = true;
82 }
83 }
84 } else if (gc instanceof ASTLiteral) {
85 result = !((ASTLiteral) gc).isStringLiteral();
86 }
87 }
88 }
89 return result;
90 }
91
92 }