Clover coverage report - PMD - 3.9
Coverage timestamp: Tue Dec 19 2006 09:38:44 EST
file stats: LOC: 143   Methods: 7
NCLOC: 105   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
VariableAccessVisitor.java 90% 98% 85.7% 94.3%
coverage coverage
 1    /*
 2    * Created on 14.07.2004
 3    */
 4    package net.sourceforge.pmd.dfa.variableaccess;
 5   
 6    import net.sourceforge.pmd.ast.ASTClassOrInterfaceBodyDeclaration;
 7    import net.sourceforge.pmd.ast.ASTConstructorDeclaration;
 8    import net.sourceforge.pmd.ast.ASTFormalParameter;
 9    import net.sourceforge.pmd.ast.ASTFormalParameters;
 10    import net.sourceforge.pmd.ast.ASTMethodDeclaration;
 11    import net.sourceforge.pmd.ast.ASTVariableInitializer;
 12    import net.sourceforge.pmd.ast.JavaParserVisitorAdapter;
 13    import net.sourceforge.pmd.ast.SimpleNode;
 14    import net.sourceforge.pmd.dfa.IDataFlowNode;
 15    import net.sourceforge.pmd.dfa.StartOrEndDataFlowNode;
 16    import net.sourceforge.pmd.symboltable.NameOccurrence;
 17    import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
 18   
 19    import java.util.ArrayList;
 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   
 26    /**
 27    * @author raik, Sven Jacob
 28    * <p/>
 29    * Searches for special nodes and computes based on the sequence, the type of
 30    * access of a variable.
 31    */
 32    public class VariableAccessVisitor extends JavaParserVisitorAdapter {
 33   
 34  43 public void compute(ASTMethodDeclaration node) {
 35  43 if (node.jjtGetParent() instanceof ASTClassOrInterfaceBodyDeclaration) {
 36  43 this.computeNow(node);
 37    }
 38    }
 39   
 40  0 public void compute(ASTConstructorDeclaration node) {
 41  0 this.computeNow(node);
 42    }
 43   
 44  43 private void computeNow(SimpleNode node) {
 45  43 IDataFlowNode inode = node.getDataFlowNode();
 46   
 47  43 List undefinitions = markUsages(inode);
 48   
 49    // all variables are first in state undefinition
 50  43 IDataFlowNode firstINode = (IDataFlowNode) inode.getFlow().get(0);
 51  43 firstINode.setVariableAccess(undefinitions);
 52   
 53    // all variables are getting undefined when leaving scope
 54  43 IDataFlowNode lastINode = (IDataFlowNode) inode.getFlow().get(inode.getFlow().size() - 1);
 55  43 lastINode.setVariableAccess(undefinitions);
 56    }
 57   
 58  43 private List markUsages(IDataFlowNode inode) {
 59    // undefinitions was once a field... seems like it works fine as a local
 60  43 List undefinitions = new ArrayList();
 61  43 Set variableDeclarations = collectDeclarations(inode);
 62  43 for (Iterator i = variableDeclarations.iterator(); i.hasNext();) {
 63  86 Map declarations = (Map) i.next();
 64  86 for (Iterator j = declarations.entrySet().iterator(); j.hasNext();) {
 65  45 Map.Entry entry = (Map.Entry) j.next();
 66  45 VariableNameDeclaration vnd = (VariableNameDeclaration) entry.getKey();
 67   
 68  45 if (vnd.getAccessNodeParent() instanceof ASTFormalParameter) {
 69    // add definition for parameters
 70  3 addVariableAccess(
 71    (SimpleNode)vnd.getNode().getFirstParentOfType(ASTFormalParameters.class),
 72    new VariableAccess(VariableAccess.DEFINITION, vnd.getImage()),
 73    inode.getFlow());
 74  42 } else if (vnd.getAccessNodeParent().getFirstChildOfType(ASTVariableInitializer.class) != null) {
 75    // add definition for initialized variables
 76  40 addVariableAccess(
 77    vnd.getNode(),
 78    new VariableAccess(VariableAccess.DEFINITION, vnd.getImage()),
 79    inode.getFlow());
 80    }
 81  45 undefinitions.add(new VariableAccess(VariableAccess.UNDEFINITION, vnd.getImage()));
 82   
 83  45 for (Iterator k = ((List) entry.getValue()).iterator(); k.hasNext();) {
 84  122 addAccess(k, inode);
 85    }
 86    }
 87    }
 88  43 return undefinitions;
 89    }
 90   
 91  43 private Set collectDeclarations(IDataFlowNode inode) {
 92  43 Set decls = new HashSet();
 93  43 Map varDecls;
 94  43 for (int i = 0; i < inode.getFlow().size(); i++) {
 95  313 IDataFlowNode n = (IDataFlowNode) inode.getFlow().get(i);
 96  313 if (n instanceof StartOrEndDataFlowNode) {
 97  86 continue;
 98    }
 99  227 varDecls = n.getSimpleNode().getScope().getVariableDeclarations();
 100  227 if (!decls.contains(varDecls)) {
 101  86 decls.add(varDecls);
 102    }
 103    }
 104  43 return decls;
 105    }
 106   
 107  122 private void addAccess(Iterator k, IDataFlowNode inode) {
 108  122 NameOccurrence occurrence = (NameOccurrence) k.next();
 109  122 if (occurrence.isOnLeftHandSide()) {
 110  67 this.addVariableAccess(occurrence.getLocation(), new VariableAccess(VariableAccess.DEFINITION, occurrence.getImage()), inode.getFlow());
 111  55 } else if (occurrence.isOnRightHandSide() || (!occurrence.isOnLeftHandSide() && !occurrence.isOnRightHandSide())) {
 112  55 this.addVariableAccess(occurrence.getLocation(), new VariableAccess(VariableAccess.REFERENCING, occurrence.getImage()), inode.getFlow());
 113    }
 114    }
 115   
 116    /**
 117    * Adds a VariableAccess to a dataflow node.
 118    * @param node location of the access of a variable
 119    * @param va variable access to add
 120    * @param flow dataflownodes that can contain the node.
 121    */
 122  165 private void addVariableAccess(SimpleNode node, VariableAccess va, List flow) {
 123    // backwards to find the right inode (not a method declaration)
 124  764 for (int i = flow.size()-1; i > 0; i--) {
 125  764 IDataFlowNode inode = (IDataFlowNode) flow.get(i);
 126  764 if (inode.getSimpleNode() == null) {
 127  165 continue;
 128    }
 129   
 130  599 List children = inode.getSimpleNode().findChildrenOfType(node.getClass());
 131  599 Iterator childrenIterator = children.iterator();
 132  599 while (childrenIterator.hasNext()) {
 133  438 if (node.equals(childrenIterator.next())) {
 134  165 List v = new ArrayList();
 135  165 v.add(va);
 136  165 inode.setVariableAccess(v);
 137  165 return;
 138    }
 139    }
 140    }
 141    }
 142   
 143    }