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;
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 }