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