Clover coverage report - PMD - 3.9 Coverage timestamp: Tue Dec 19 2006 09:38:44 EST FRAMES NO FRAMES |
file stats: | LOC: | 143 |  | Methods: | 7
| NCLOC: | 105 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
VariableAccessVisitor.java | 90% | 98% | 85.7% | 94.3% |

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 |  | }