01 /**
02 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03 */
04 package net.sourceforge.pmd.lang.java.rule.unusedcode;
05
06 import java.util.List;
07 import java.util.Map;
08
09 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody;
10 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
11 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
12 import net.sourceforge.pmd.lang.java.ast.ASTName;
13 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
14 import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
15 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
16 import net.sourceforge.pmd.lang.java.symboltable.NameOccurrence;
17 import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
18
19 public class UnusedPrivateFieldRule extends AbstractJavaRule {
20
21 @Override
22 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
23 Map<VariableNameDeclaration, List<NameOccurrence>> vars = node.getScope().getVariableDeclarations();
24 for (Map.Entry<VariableNameDeclaration, List<NameOccurrence>> entry: vars.entrySet()) {
25 VariableNameDeclaration decl = entry.getKey();
26 if (!decl.getAccessNodeParent().isPrivate() || isOK(decl.getImage())) {
27 continue;
28 }
29 if (!actuallyUsed(entry.getValue())) {
30 if (!usedInOuterClass(node, decl)) {
31 addViolation(data, decl.getNode(), decl.getImage());
32 }
33 }
34 }
35 return super.visit(node, data);
36 }
37
38 /**
39 * Find out whether the variable is used in an outer class
40 */
41 private boolean usedInOuterClass(ASTClassOrInterfaceDeclaration node,
42 VariableNameDeclaration decl) {
43 List<ASTClassOrInterfaceDeclaration> outerClasses = node.getParentsOfType(ASTClassOrInterfaceDeclaration.class);
44 for (ASTClassOrInterfaceDeclaration outerClass : outerClasses) {
45 ASTClassOrInterfaceBody classOrInterfaceBody = outerClass.getFirstChildOfType(ASTClassOrInterfaceBody.class);
46
47 List<ASTClassOrInterfaceBodyDeclaration> classOrInterfaceBodyDeclarations = classOrInterfaceBody.findChildrenOfType(ASTClassOrInterfaceBodyDeclaration.class);
48
49 for (ASTClassOrInterfaceBodyDeclaration classOrInterfaceBodyDeclaration : classOrInterfaceBodyDeclarations) {
50 for (int i = 0; i < classOrInterfaceBodyDeclaration.jjtGetNumChildren(); i++) {
51 if (classOrInterfaceBodyDeclaration.jjtGetChild(i) instanceof ASTClassOrInterfaceDeclaration) {
52 continue; //Skip other inner classes
53 }
54
55 List<ASTPrimarySuffix> primarySuffixes = classOrInterfaceBodyDeclaration.findDescendantsOfType(ASTPrimarySuffix.class);
56 for (ASTPrimarySuffix primarySuffix : primarySuffixes) {
57 if (decl.getImage().equals(primarySuffix.getImage())) {
58 return true; //No violation
59 }
60 }
61
62 List<ASTPrimaryPrefix> primaryPrefixes = classOrInterfaceBodyDeclaration.findDescendantsOfType(ASTPrimaryPrefix.class);
63 for (ASTPrimaryPrefix primaryPrefix : primaryPrefixes) {
64 ASTName name = primaryPrefix.getFirstDescendantOfType(ASTName.class);
65
66 if (name != null && name.getImage().endsWith(decl.getImage())) {
67 return true; //No violation
68 }
69 }
70 }
71 }
72
73 }
74
75 return false;
76 }
77
78 private boolean actuallyUsed(List<NameOccurrence> usages) {
79 for (NameOccurrence nameOccurrence: usages) {
80 if (!nameOccurrence.isOnLeftHandSide()) {
81 return true;
82 }
83 }
84
85 return false;
86 }
87
88 private boolean isOK(String image) {
89 return image.equals("serialVersionUID") || image.equals("serialPersistentFields") || image.equals("IDENT");
90 }
91 }
|