1 4 package net.sourceforge.pmd.rules.design; 5 6 import net.sourceforge.pmd.AbstractRule; 7 import net.sourceforge.pmd.ast.ASTClassOrInterfaceBodyDeclaration; 8 import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration; 9 import net.sourceforge.pmd.ast.ASTConstructorDeclaration; 10 import net.sourceforge.pmd.ast.ASTDoStatement; 11 import net.sourceforge.pmd.ast.ASTForStatement; 12 import net.sourceforge.pmd.ast.ASTMethodDeclaration; 13 import net.sourceforge.pmd.ast.ASTTryStatement; 14 import net.sourceforge.pmd.ast.ASTVariableInitializer; 15 import net.sourceforge.pmd.ast.ASTWhileStatement; 16 import net.sourceforge.pmd.ast.SimpleNode; 17 import net.sourceforge.pmd.symboltable.NameOccurrence; 18 import net.sourceforge.pmd.symboltable.VariableNameDeclaration; 19 20 import java.util.ArrayList ; 21 import java.util.HashSet ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.Map ; 25 import java.util.Set ; 26 27 30 public class ImmutableField extends AbstractRule { 31 32 private static final int MUTABLE = 0; 33 private static final int IMMUTABLE = 1; 34 private static final int CHECKDECL = 2; 35 36 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { 37 Map vars = node.getScope().getVariableDeclarations(); 38 List constructors = findAllConstructors(node); 39 for (Iterator i = vars.entrySet().iterator(); i.hasNext();) { 40 Map.Entry entry = (Map.Entry ) i.next(); 41 VariableNameDeclaration field = (VariableNameDeclaration) entry.getKey(); 42 if (field.getAccessNodeParent().isStatic() || !field.getAccessNodeParent().isPrivate() || field.getAccessNodeParent().isFinal()) { 43 continue; 44 } 45 46 int result = initializedInConstructor((List ) entry.getValue(), new HashSet (constructors)); 47 if (result == MUTABLE) { 48 continue; 49 } 50 if (result == IMMUTABLE || (result == CHECKDECL && initializedWhenDeclared(field))) { 51 addViolation(data, field.getNode(), field.getImage()); 52 } 53 } 54 return super.visit(node, data); 55 } 56 57 private boolean initializedWhenDeclared(VariableNameDeclaration field) { 58 return !field.getAccessNodeParent().findChildrenOfType(ASTVariableInitializer.class).isEmpty(); 59 } 60 61 private int initializedInConstructor(List usages, Set allConstructors) { 62 int result = MUTABLE, methodInitCount = 0; 63 Set consSet = new HashSet (); 64 for (Iterator j = usages.iterator(); j.hasNext();) { 65 NameOccurrence occ = (NameOccurrence) j.next(); 66 if (occ.isOnLeftHandSide() || occ.isSelfAssignment()) { 67 SimpleNode node = occ.getLocation(); 68 SimpleNode constructor = (SimpleNode) node.getFirstParentOfType(ASTConstructorDeclaration.class); 69 if (constructor != null) { 70 if (inLoopOrTry(node)) { 71 continue; 72 } 73 if (inAnonymousInnerClass(node)) { 74 methodInitCount++; 75 } else { 76 consSet.add(constructor); 77 } 78 } else { 79 if (node.getFirstParentOfType(ASTMethodDeclaration.class) != null) { 80 methodInitCount++; 81 } 82 } 83 } 84 } 85 if (usages.isEmpty() || ((methodInitCount == 0) && consSet.isEmpty())) { 86 result = CHECKDECL; 87 } else { 88 allConstructors.removeAll(consSet); 89 if (allConstructors.isEmpty() && (methodInitCount == 0)) { 90 result = IMMUTABLE; 91 } 92 } 93 return result; 94 } 95 96 private boolean inLoopOrTry(SimpleNode node) { 97 return (SimpleNode) node.getFirstParentOfType(ASTTryStatement.class) != null || 98 (SimpleNode) node.getFirstParentOfType(ASTForStatement.class) != null || 99 (SimpleNode) node.getFirstParentOfType(ASTWhileStatement.class) != null || 100 (SimpleNode) node.getFirstParentOfType(ASTDoStatement.class) != null; 101 } 102 103 private boolean inAnonymousInnerClass(SimpleNode node) { 104 ASTClassOrInterfaceBodyDeclaration parent = (ASTClassOrInterfaceBodyDeclaration) node.getFirstParentOfType(ASTClassOrInterfaceBodyDeclaration.class); 105 return parent != null && parent.isAnonymousInnerClass(); 106 } 107 108 private List findAllConstructors(ASTClassOrInterfaceDeclaration node) { 109 List cons = new ArrayList (); 110 node.findChildrenOfType(ASTConstructorDeclaration.class, cons, false); 111 return cons; 112 } 113 } 114 | Popular Tags |