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.design;
5   
6   import net.sourceforge.pmd.lang.ast.Node;
7   import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
8   import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody;
9   import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
10  import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
11  import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
12  import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
13  import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
14  import net.sourceforge.pmd.lang.java.ast.ASTResultType;
15  import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
16  
17  public class UseUtilityClassRule extends AbstractJavaRule {
18  
19      @Override
20      public Object visit(ASTClassOrInterfaceBody decl, Object data) {
21          if (decl.jjtGetParent() instanceof ASTClassOrInterfaceDeclaration) {
22              ASTClassOrInterfaceDeclaration parent = (ASTClassOrInterfaceDeclaration) decl.jjtGetParent();
23              if (parent.isAbstract() || parent.isInterface()) {
24                  return super.visit(decl, data);
25              }
26              int i = decl.jjtGetNumChildren();
27              int methodCount = 0;
28              boolean isOK = false;
29              while (i > 0) {
30                  Node p = decl.jjtGetChild(--i);
31                  if (p.jjtGetNumChildren() == 0) {
32                      continue;
33                  }
34                  Node n = p.jjtGetChild(0);
35                  if (n instanceof ASTAnnotation) {
36                      n = p.jjtGetChild(1);
37                  }
38                  if (n instanceof ASTFieldDeclaration) {
39                      if (!((ASTFieldDeclaration) n).isStatic()) {
40                          isOK = true;
41                          break;
42                      }
43                  } else if (n instanceof ASTConstructorDeclaration) {
44                      if (((ASTConstructorDeclaration) n).isPrivate()) {
45                          isOK = true;
46                          break;
47                      }
48                  } else if (n instanceof ASTMethodDeclaration) {
49                      ASTMethodDeclaration m = (ASTMethodDeclaration) n;
50                      if (!m.isPrivate()) {
51                          methodCount++;
52                      }
53                      if (!m.isStatic()) {
54                          isOK = true;
55                          break;
56                      }
57  
58                      // TODO use symbol table
59                      if (m.getMethodName().equals("suite")) {
60                          ASTResultType res = m.getResultType();
61                          ASTClassOrInterfaceType c = res.getFirstDescendantOfType(ASTClassOrInterfaceType.class);
62                          if (c != null && c.hasImageEqualTo("Test")) {
63                              isOK = true;
64                              break;
65                          }
66                      }
67  
68                  }
69              }
70              if (!isOK && methodCount > 0) {
71                  addViolation(data, decl);
72              }
73          }
74          return super.visit(decl, data);
75      }
76  
77  }