1
2
3
4 package net.sourceforge.pmd.lang.java.dfa;
5
6 import java.util.ArrayList;
7 import java.util.HashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11
12 import net.sourceforge.pmd.lang.ast.Node;
13 import net.sourceforge.pmd.lang.dfa.DataFlowNode;
14 import net.sourceforge.pmd.lang.dfa.StartOrEndDataFlowNode;
15 import net.sourceforge.pmd.lang.dfa.VariableAccess;
16 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration;
17 import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
18 import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
19 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
20 import net.sourceforge.pmd.lang.java.ast.ASTVariableInitializer;
21 import net.sourceforge.pmd.lang.java.ast.JavaNode;
22 import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter;
23 import net.sourceforge.pmd.lang.java.symboltable.NameOccurrence;
24 import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
25
26
27
28
29
30
31
32 public class VariableAccessVisitor extends JavaParserVisitorAdapter {
33
34 public void compute(ASTMethodDeclaration node) {
35 if (node.jjtGetParent() instanceof ASTClassOrInterfaceBodyDeclaration) {
36 this.computeNow(node);
37 }
38 }
39
40 public void compute(ASTConstructorDeclaration node) {
41 this.computeNow(node);
42 }
43
44 private void computeNow(Node node) {
45 DataFlowNode inode = node.getDataFlowNode();
46
47 List<VariableAccess> undefinitions = markUsages(inode);
48
49
50 DataFlowNode firstINode = inode.getFlow().get(0);
51 firstINode.setVariableAccess(undefinitions);
52
53
54 DataFlowNode lastINode = inode.getFlow().get(inode.getFlow().size() - 1);
55 lastINode.setVariableAccess(undefinitions);
56 }
57
58 private List<VariableAccess> markUsages(DataFlowNode inode) {
59
60 List<VariableAccess> undefinitions = new ArrayList<VariableAccess>();
61 Set<Map<VariableNameDeclaration, List<NameOccurrence>>> variableDeclarations = collectDeclarations(inode);
62 for (Map<VariableNameDeclaration, List<NameOccurrence>> declarations : variableDeclarations) {
63 for (Map.Entry<VariableNameDeclaration, List<NameOccurrence>> entry : declarations.entrySet()) {
64 VariableNameDeclaration vnd = entry.getKey();
65
66 if (vnd.getAccessNodeParent() instanceof ASTFormalParameter) {
67
68 continue;
69 } else if (((Node) vnd.getAccessNodeParent()).getFirstDescendantOfType(ASTVariableInitializer.class) != null) {
70
71 addVariableAccess(vnd.getNode(), new VariableAccess(VariableAccess.DEFINITION, vnd.getImage()),
72 inode.getFlow());
73 }
74 undefinitions.add(new VariableAccess(VariableAccess.UNDEFINITION, vnd.getImage()));
75
76 for (NameOccurrence occurrence : entry.getValue()) {
77 addAccess(occurrence, inode);
78 }
79 }
80 }
81 return undefinitions;
82 }
83
84 private Set<Map<VariableNameDeclaration, List<NameOccurrence>>> collectDeclarations(DataFlowNode inode) {
85 Set<Map<VariableNameDeclaration, List<NameOccurrence>>> decls = new HashSet<Map<VariableNameDeclaration, List<NameOccurrence>>>();
86 Map<VariableNameDeclaration, List<NameOccurrence>> varDecls;
87 for (int i = 0; i < inode.getFlow().size(); i++) {
88 DataFlowNode n = inode.getFlow().get(i);
89 if (n instanceof StartOrEndDataFlowNode) {
90 continue;
91 }
92 varDecls = ((JavaNode)n.getNode()).getScope().getVariableDeclarations();
93 if (!decls.contains(varDecls)) {
94 decls.add(varDecls);
95 }
96 }
97 return decls;
98 }
99
100 private void addAccess(NameOccurrence occurrence, DataFlowNode inode) {
101 if (occurrence.isOnLeftHandSide()) {
102 this.addVariableAccess(occurrence.getLocation(), new VariableAccess(VariableAccess.DEFINITION, occurrence
103 .getImage()), inode.getFlow());
104 } else if (occurrence.isOnRightHandSide() || !occurrence.isOnLeftHandSide() && !occurrence.isOnRightHandSide()) {
105 this.addVariableAccess(occurrence.getLocation(), new VariableAccess(VariableAccess.REFERENCING, occurrence
106 .getImage()), inode.getFlow());
107 }
108 }
109
110
111
112
113
114
115
116 private void addVariableAccess(Node node, VariableAccess va, List<DataFlowNode> flow) {
117
118 for (int i = flow.size() - 1; i > 0; i--) {
119 DataFlowNode inode = flow.get(i);
120 if (inode.getNode() == null) {
121 continue;
122 }
123
124 List<? extends Node> children = inode.getNode().findDescendantsOfType(node.getClass());
125 for (Node n : children) {
126 if (node.equals(n)) {
127 List<VariableAccess> v = new ArrayList<VariableAccess>();
128 v.add(va);
129 inode.setVariableAccess(v);
130 return;
131 }
132 }
133 }
134 }
135
136 }