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.ASTInitializer;
10 import net.sourceforge.pmd.ast.ASTMethodDeclaration;
11 import net.sourceforge.pmd.ast.ASTMethodDeclarator;
12 import net.sourceforge.pmd.ast.AccessNode;
13 import net.sourceforge.pmd.ast.SimpleNode;
14 import net.sourceforge.pmd.symboltable.ClassScope;
15 import net.sourceforge.pmd.symboltable.MethodNameDeclaration;
16 import net.sourceforge.pmd.symboltable.NameOccurrence;
17
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.HashSet;
22 import java.util.Set;
23
24 public class UnusedPrivateMethodRule extends AbstractRule {
25
26
27 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
28 if (node.isInterface()) {
29 return data;
30 }
31
32 Map methods = ((ClassScope) node.getScope()).getMethodDeclarations();
33 for (Iterator i = findUnique(methods).iterator(); i.hasNext();) {
34 MethodNameDeclaration mnd = (MethodNameDeclaration) i.next();
35 List occs = (List) methods.get(mnd);
36 if (!privateAndNotExcluded(mnd)) {
37 continue;
38 }
39 if (occs.isEmpty()) {
40 addViolation(data, mnd.getNode(), mnd.getImage() + mnd.getParameterDisplaySignature());
41 } else {
42 if (calledFromOutsideItself(occs, mnd)) {
43 addViolation(data, mnd.getNode(), mnd.getImage() + mnd.getParameterDisplaySignature());
44 }
45
46 }
47 }
48 return data;
49 }
50
51 private Set findUnique(Map methods) {
52
53
54
55 Set unique = new HashSet();
56 Set sigs = new HashSet();
57 for (Iterator i = methods.keySet().iterator(); i.hasNext();) {
58 MethodNameDeclaration mnd = (MethodNameDeclaration) i.next();
59 String sig = mnd.getImage() + String.valueOf(mnd.getParameterCount());
60 if (!sigs.contains(sig)) {
61 unique.add(mnd);
62 }
63 sigs.add(sig);
64 }
65 return unique;
66 }
67
68 private boolean calledFromOutsideItself(List occs, MethodNameDeclaration mnd) {
69 int callsFromOutsideMethod = 0;
70 for (Iterator i = occs.iterator(); i.hasNext();) {
71 NameOccurrence occ = (NameOccurrence) i.next();
72 SimpleNode occNode = occ.getLocation();
73 ASTConstructorDeclaration enclosingConstructor = (ASTConstructorDeclaration) occNode.getFirstParentOfType(ASTConstructorDeclaration.class);
74 if (enclosingConstructor != null) {
75 callsFromOutsideMethod++;
76 break;
77 }
78 ASTInitializer enclosingInitializer = (ASTInitializer) occNode.getFirstParentOfType(ASTInitializer.class);
79 if (enclosingInitializer != null) {
80 callsFromOutsideMethod++;
81 break;
82 }
83
84 ASTMethodDeclaration enclosingMethod = (ASTMethodDeclaration) occNode.getFirstParentOfType(ASTMethodDeclaration.class);
85 if ((enclosingMethod == null) || (enclosingMethod != null && !mnd.getNode().jjtGetParent().equals(enclosingMethod))) {
86 callsFromOutsideMethod++;
87 }
88 }
89 return callsFromOutsideMethod == 0;
90 }
91
92 private boolean privateAndNotExcluded(MethodNameDeclaration mnd) {
93 ASTMethodDeclarator node = (ASTMethodDeclarator) mnd.getNode();
94 return ((AccessNode) node.jjtGetParent()).isPrivate() && !node.getImage().equals("readObject") && !node.getImage().equals("writeObject") && !node.getImage().equals("readResolve") && !node.getImage().equals("writeReplace");
95 }
96 }