Clover coverage report - PMD - 3.3
Coverage timestamp: Thu Sep 15 2005 17:59:57 EDT
file stats: LOC: 99   Methods: 4
NCLOC: 82   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ImmutableField.java 90.9% 100% 100% 96.7%
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.ASTClassOrInterfaceDeclaration;
 8    import net.sourceforge.pmd.ast.ASTConstructorDeclaration;
 9    import net.sourceforge.pmd.ast.ASTDoStatement;
 10    import net.sourceforge.pmd.ast.ASTForStatement;
 11    import net.sourceforge.pmd.ast.ASTMethodDeclaration;
 12    import net.sourceforge.pmd.ast.ASTTryStatement;
 13    import net.sourceforge.pmd.ast.ASTVariableInitializer;
 14    import net.sourceforge.pmd.ast.ASTWhileStatement;
 15    import net.sourceforge.pmd.ast.SimpleNode;
 16    import net.sourceforge.pmd.symboltable.NameOccurrence;
 17    import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
 18   
 19    import java.util.HashSet;
 20    import java.util.Iterator;
 21    import java.util.List;
 22    import java.util.Map;
 23    import java.util.Set;
 24   
 25    /**
 26    * @author Olander
 27    */
 28    public class ImmutableField extends AbstractRule {
 29   
 30    private static final int MUTABLE = 0;
 31    private static final int IMMUTABLE = 1;
 32    private static final int CHECKDECL = 2;
 33   
 34  15 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
 35  15 Map vars = node.getScope().getVariableDeclarations();
 36  15 Set constructors = findAllConstructors(node);
 37  15 for (Iterator i = vars.keySet().iterator(); i.hasNext();) {
 38  17 VariableNameDeclaration field = (VariableNameDeclaration) i.next();
 39  17 if (field.getAccessNodeParent().isStatic() || !field.getAccessNodeParent().isPrivate() || field.getAccessNodeParent().isFinal()) {
 40  2 continue;
 41    }
 42   
 43  15 int result = initializedInConstructor((List)vars.get(field), new HashSet(constructors));
 44  15 if (result == MUTABLE) {
 45  11 continue;
 46    }
 47  4 if (result == IMMUTABLE || ((result == CHECKDECL) && !field.getAccessNodeParent().findChildrenOfType(ASTVariableInitializer.class).isEmpty())) {
 48  2 addViolation(data, field.getNode(), field.getImage());
 49    }
 50    }
 51  15 return super.visit(node, data);
 52    }
 53   
 54  15 private int initializedInConstructor(List usages, Set allConstructors) {
 55  15 int rc = MUTABLE, methodInitCount = 0;
 56  15 Set consSet = new HashSet();
 57  15 for (Iterator j = usages.iterator(); j.hasNext();) {
 58  17 NameOccurrence occ = (NameOccurrence)j.next();
 59  17 if (occ.isOnLeftHandSide() || occ.isSelfAssignment()) {
 60  17 SimpleNode node = occ.getLocation();
 61  17 SimpleNode constructor = (SimpleNode)node.getFirstParentOfType(ASTConstructorDeclaration.class);
 62  17 if (constructor != null) {
 63  5 if (inLoopOrTry(node)) {
 64  2 continue;
 65    }
 66  3 consSet.add(constructor);
 67    } else {
 68  12 if (node.getFirstParentOfType(ASTMethodDeclaration.class) != null) {
 69  12 methodInitCount++;
 70    }
 71    }
 72    }
 73    }
 74  15 if (usages.isEmpty() || ((methodInitCount == 0) && consSet.isEmpty())) {
 75  3 rc = CHECKDECL;
 76    } else {
 77  12 allConstructors.removeAll(consSet);
 78  12 if (allConstructors.isEmpty() && (methodInitCount == 0)) {
 79  1 rc = IMMUTABLE;
 80    }
 81    }
 82  15 return rc;
 83    }
 84   
 85  5 private boolean inLoopOrTry(SimpleNode node) {
 86  5 return (SimpleNode)node.getFirstParentOfType(ASTTryStatement.class) != null ||
 87    (SimpleNode)node.getFirstParentOfType(ASTForStatement.class) != null ||
 88    (SimpleNode)node.getFirstParentOfType(ASTWhileStatement.class) != null ||
 89    (SimpleNode)node.getFirstParentOfType(ASTDoStatement.class) != null;
 90    }
 91   
 92    /** construct a set containing all ASTConstructorDeclaration nodes for this class
 93    */
 94  15 private Set findAllConstructors(ASTClassOrInterfaceDeclaration node) {
 95  15 Set set = new HashSet();
 96  15 set.addAll(node.findChildrenOfType(ASTConstructorDeclaration.class));
 97  15 return set;
 98    }
 99    }