1
2
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.ASTMethodDeclaration;
9 import net.sourceforge.pmd.ast.JavaParserVisitorAdapter;
10 import net.sourceforge.pmd.ast.SimpleNode;
11 import net.sourceforge.pmd.dfa.IDataFlowNode;
12 import net.sourceforge.pmd.dfa.StartOrEndDataFlowNode;
13 import net.sourceforge.pmd.symboltable.NameOccurrence;
14 import net.sourceforge.pmd.symboltable.VariableNameDeclaration;
15
16 import java.util.ArrayList;
17 import java.util.HashSet;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.Vector;
23
24 /***
25 * @author raik
26 * <p/>
27 * Searches for special nodes and computes based on the sequence, the type of
28 * access of a variable.
29 */
30 public class VariableAccessVisitor extends JavaParserVisitorAdapter {
31
32 public void compute(ASTMethodDeclaration node) {
33 if (node.jjtGetParent() instanceof ASTClassOrInterfaceBodyDeclaration) {
34 this.computeNow(node);
35 }
36 }
37
38 public void compute(ASTConstructorDeclaration node) {
39 this.computeNow(node);
40 }
41
42 private void computeNow(SimpleNode node) {
43 IDataFlowNode inode = node.getDataFlowNode();
44
45 List undefinitions = markUsages(inode);
46
47
48 IDataFlowNode firstINode = (IDataFlowNode) inode.getFlow().get(0);
49 firstINode.setVariableAccess(undefinitions);
50
51 IDataFlowNode lastINode = (IDataFlowNode) inode.getFlow().get(inode.getFlow().size() - 1);
52 lastINode.setVariableAccess(undefinitions);
53 }
54
55 private List markUsages(IDataFlowNode inode) {
56
57 List undefinitions = new ArrayList();
58 Set variableDeclarations = collectDeclarations(inode);
59 for (Iterator i = variableDeclarations.iterator(); i.hasNext();) {
60 Map declarations = (Map) i.next();
61 for (Iterator j = declarations.keySet().iterator(); j.hasNext();) {
62 VariableNameDeclaration vnd = (VariableNameDeclaration) j.next();
63 addVariableAccess(vnd.getNode().getBeginLine(), new VariableAccess(VariableAccess.DEFINITION, vnd.getImage()), inode.getFlow());
64 undefinitions.add(new VariableAccess(VariableAccess.UNDEFINITION, vnd.getImage()));
65 for (Iterator k = ((List) declarations.get(vnd)).iterator(); k.hasNext();) {
66 addAccess(k, inode);
67 }
68 }
69 }
70 return undefinitions;
71 }
72
73 private Set collectDeclarations(IDataFlowNode inode) {
74 Set decls = new HashSet();
75 for (int i = 0; i < inode.getFlow().size(); i++) {
76 IDataFlowNode n = (IDataFlowNode) inode.getFlow().get(i);
77 if (n instanceof StartOrEndDataFlowNode) {
78 continue;
79 }
80 if (!decls.contains(n.getSimpleNode().getScope().getVariableDeclarations())) {
81 decls.add(n.getSimpleNode().getScope().getVariableDeclarations());
82 }
83 }
84 return decls;
85 }
86
87 private void addAccess(Iterator k, IDataFlowNode inode) {
88 NameOccurrence occurrence = (NameOccurrence) k.next();
89 if (occurrence.isOnLeftHandSide()) {
90 this.addVariableAccess(occurrence.getLocation().getBeginLine(), new VariableAccess(VariableAccess.DEFINITION, occurrence.getImage()), inode.getFlow());
91 } else if (occurrence.isOnRightHandSide() || (!occurrence.isOnLeftHandSide() && !occurrence.isOnRightHandSide())) {
92 this.addVariableAccess(occurrence.getLocation().getBeginLine(), new VariableAccess(VariableAccess.REFERENCING, occurrence.getImage()), inode.getFlow());
93 }
94 }
95
96 private void addVariableAccess(int line, VariableAccess va, List flow) {
97 for (int i = 1; i < flow.size(); i++) {
98 IDataFlowNode inode = (IDataFlowNode) flow.get(i);
99 if (line == inode.getLine()) {
100 Vector v = new Vector();
101 v.add(va);
102 inode.setVariableAccess(v);
103 }
104 }
105 }
106
107 }