View Javadoc

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.ASTClassOrInterfaceDeclaration;
8   import net.sourceforge.pmd.ast.ASTConstructorDeclaration;
9   import net.sourceforge.pmd.ast.ASTMethodDeclaration;
10  import net.sourceforge.pmd.ast.ASTMethodDeclarator;
11  import net.sourceforge.pmd.ast.AccessNode;
12  import net.sourceforge.pmd.ast.SimpleNode;
13  import net.sourceforge.pmd.symboltable.ClassScope;
14  import net.sourceforge.pmd.symboltable.MethodNameDeclaration;
15  import net.sourceforge.pmd.symboltable.NameOccurrence;
16  
17  import java.util.Iterator;
18  import java.util.List;
19  import java.util.Map;
20  
21  public class UnusedPrivateMethodRule extends AbstractRule {
22  
23      public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
24          if (node.isInterface()) {
25              return data;
26          }
27  
28          Map methods = ((ClassScope)node.getScope()).getMethodDeclarations();
29          for (Iterator i = methods.keySet().iterator(); i.hasNext();) {
30              MethodNameDeclaration mnd = (MethodNameDeclaration)i.next();
31              List occs = (List)methods.get(mnd);
32              if (!privateAndNotExcluded(mnd)) {
33                  continue;
34              }
35              if (occs.isEmpty()) {
36                  addViolation(data, mnd.getNode(), mnd.getImage() + mnd.getParameterDisplaySignature());
37              } else {
38                  if (calledFromOutsideItself(occs, mnd)) {
39                      addViolation(data, mnd.getNode(), mnd.getImage() + mnd.getParameterDisplaySignature());
40                  }
41  
42              }
43          }
44          return data;
45      }
46  
47      private boolean calledFromOutsideItself(List occs, MethodNameDeclaration mnd) {
48          int callsFromOutsideMethod = 0;
49          for (Iterator i = occs.iterator(); i.hasNext();) {
50              NameOccurrence occ = (NameOccurrence)i.next();
51              SimpleNode occNode = occ.getLocation();
52              ASTConstructorDeclaration enclosingConstructor = (ASTConstructorDeclaration)occNode.getFirstParentOfType(ASTConstructorDeclaration.class);
53              if (enclosingConstructor != null) {
54                  callsFromOutsideMethod++;
55                  continue; // Do we miss unused private constructors here?
56              }
57              ASTMethodDeclaration enclosingMethod = (ASTMethodDeclaration)occNode.getFirstParentOfType(ASTMethodDeclaration.class);
58              if (enclosingMethod != null && !mnd.getNode().jjtGetParent().equals(enclosingMethod)) {
59                 callsFromOutsideMethod++;
60              }
61          }
62          return callsFromOutsideMethod == 0;
63      }
64  
65      private boolean privateAndNotExcluded(MethodNameDeclaration mnd) {
66          ASTMethodDeclarator node = (ASTMethodDeclarator)mnd.getNode();
67          return ((AccessNode) node.jjtGetParent()).isPrivate() && !node.getImage().equals("readObject") && !node.getImage().equals("writeObject") && !node.getImage().equals("readResolve") && !node.getImage().equals("writeReplace");
68      }
69  }