Clover coverage report - PMD - 3.7
Coverage timestamp: Wed May 31 2006 09:25:59 EDT
file stats: LOC: 112   Methods: 6
NCLOC: 95   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ImmutableField.java 91.7% 100% 100% 97.1%
coverage coverage
 1    /**
 2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 3    */
 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.HashSet;
 21    import java.util.Iterator;
 22    import java.util.List;
 23    import java.util.Map;
 24    import java.util.Set;
 25    import java.util.ArrayList;
 26   
 27    /**
 28    * @author Olander
 29    */
 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  16 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
 37  16 Map vars = node.getScope().getVariableDeclarations();
 38  16 List constructors = findAllConstructors(node);
 39  16 for (Iterator i = vars.keySet().iterator(); i.hasNext();) {
 40  18 VariableNameDeclaration field = (VariableNameDeclaration) i.next();
 41  18 if (field.getAccessNodeParent().isStatic() || !field.getAccessNodeParent().isPrivate() || field.getAccessNodeParent().isFinal()) {
 42  2 continue;
 43    }
 44   
 45  16 int result = initializedInConstructor((List) vars.get(field), new HashSet(constructors));
 46  16 if (result == MUTABLE) {
 47  12 continue;
 48    }
 49  4 if (result == IMMUTABLE || (result == CHECKDECL && initializedWhenDeclared(field))) {
 50  2 addViolation(data, field.getNode(), field.getImage());
 51    }
 52    }
 53  16 return super.visit(node, data);
 54    }
 55   
 56  3 private boolean initializedWhenDeclared(VariableNameDeclaration field) {
 57  3 return !field.getAccessNodeParent().findChildrenOfType(ASTVariableInitializer.class).isEmpty();
 58    }
 59   
 60  16 private int initializedInConstructor(List usages, Set allConstructors) {
 61  16 int result = MUTABLE, methodInitCount = 0;
 62  16 Set consSet = new HashSet();
 63  16 for (Iterator j = usages.iterator(); j.hasNext();) {
 64  18 NameOccurrence occ = (NameOccurrence) j.next();
 65  18 if (occ.isOnLeftHandSide() || occ.isSelfAssignment()) {
 66  18 SimpleNode node = occ.getLocation();
 67  18 SimpleNode constructor = (SimpleNode) node.getFirstParentOfType(ASTConstructorDeclaration.class);
 68  18 if (constructor != null) {
 69  6 if (inLoopOrTry(node)) {
 70  2 continue;
 71    }
 72  4 if (inAnonymousInnerClass(node)) {
 73  1 methodInitCount++;
 74    } else {
 75  3 consSet.add(constructor);
 76    }
 77    } else {
 78  12 if (node.getFirstParentOfType(ASTMethodDeclaration.class) != null) {
 79  12 methodInitCount++;
 80    }
 81    }
 82    }
 83    }
 84  16 if (usages.isEmpty() || ((methodInitCount == 0) && consSet.isEmpty())) {
 85  3 result = CHECKDECL;
 86    } else {
 87  13 allConstructors.removeAll(consSet);
 88  13 if (allConstructors.isEmpty() && (methodInitCount == 0)) {
 89  1 result = IMMUTABLE;
 90    }
 91    }
 92  16 return result;
 93    }
 94   
 95  6 private boolean inLoopOrTry(SimpleNode node) {
 96  6 return (SimpleNode) node.getFirstParentOfType(ASTTryStatement.class) != null ||
 97    (SimpleNode) node.getFirstParentOfType(ASTForStatement.class) != null ||
 98    (SimpleNode) node.getFirstParentOfType(ASTWhileStatement.class) != null ||
 99    (SimpleNode) node.getFirstParentOfType(ASTDoStatement.class) != null;
 100    }
 101   
 102  4 private boolean inAnonymousInnerClass(SimpleNode node) {
 103  4 ASTClassOrInterfaceBodyDeclaration parent = (ASTClassOrInterfaceBodyDeclaration) node.getFirstParentOfType(ASTClassOrInterfaceBodyDeclaration.class);
 104  4 return parent != null && parent.isAnonymousInnerClass();
 105    }
 106   
 107  16 private List findAllConstructors(ASTClassOrInterfaceDeclaration node) {
 108  16 List cons = new ArrayList();
 109  16 node.findChildrenOfType(ASTConstructorDeclaration.class, cons, false);
 110  16 return cons;
 111    }
 112    }