KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > pmd > dfa > variableaccess > VariableAccessVisitor


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 JavaDoc;
20 import java.util.HashSet JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.Set JavaDoc;
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     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(SimpleNode node) {
45         IDataFlowNode inode = node.getDataFlowNode();
46
47         List JavaDoc undefinitions = markUsages(inode);
48
49         // all variables are first in state undefinition
50
IDataFlowNode firstINode = (IDataFlowNode) inode.getFlow().get(0);
51         firstINode.setVariableAccess(undefinitions);
52
53         // all variables are getting undefined when leaving scope
54
IDataFlowNode lastINode = (IDataFlowNode) inode.getFlow().get(inode.getFlow().size() - 1);
55         lastINode.setVariableAccess(undefinitions);
56     }
57
58     private List JavaDoc markUsages(IDataFlowNode inode) {
59         // undefinitions was once a field... seems like it works fine as a local
60
List JavaDoc undefinitions = new ArrayList JavaDoc();
61         Set JavaDoc variableDeclarations = collectDeclarations(inode);
62         for (Iterator JavaDoc i = variableDeclarations.iterator(); i.hasNext();) {
63             Map JavaDoc declarations = (Map JavaDoc) i.next();
64             for (Iterator JavaDoc j = declarations.entrySet().iterator(); j.hasNext();) {
65                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) j.next();
66                 VariableNameDeclaration vnd = (VariableNameDeclaration) entry.getKey();
67
68                 if (vnd.getAccessNodeParent() instanceof ASTFormalParameter) {
69                     // add definition for parameters
70
addVariableAccess(
71                             (SimpleNode)vnd.getNode().getFirstParentOfType(ASTFormalParameters.class),
72                             new VariableAccess(VariableAccess.DEFINITION, vnd.getImage()),
73                             inode.getFlow());
74                 } else if (vnd.getAccessNodeParent().getFirstChildOfType(ASTVariableInitializer.class) != null) {
75                     // add definition for initialized variables
76
addVariableAccess(
77                             vnd.getNode(),
78                             new VariableAccess(VariableAccess.DEFINITION, vnd.getImage()),
79                             inode.getFlow());
80                 }
81                 undefinitions.add(new VariableAccess(VariableAccess.UNDEFINITION, vnd.getImage()));
82
83                 for (Iterator JavaDoc k = ((List JavaDoc) entry.getValue()).iterator(); k.hasNext();) {
84                     addAccess(k, inode);
85                 }
86             }
87         }
88         return undefinitions;
89     }
90
91     private Set JavaDoc collectDeclarations(IDataFlowNode inode) {
92         Set JavaDoc decls = new HashSet JavaDoc();
93         Map JavaDoc varDecls;
94         for (int i = 0; i < inode.getFlow().size(); i++) {
95             IDataFlowNode n = (IDataFlowNode) inode.getFlow().get(i);
96             if (n instanceof StartOrEndDataFlowNode) {
97                 continue;
98             }
99             varDecls = n.getSimpleNode().getScope().getVariableDeclarations();
100             if (!decls.contains(varDecls)) {
101                 decls.add(varDecls);
102             }
103         }
104         return decls;
105     }
106
107     private void addAccess(Iterator JavaDoc k, IDataFlowNode inode) {
108         NameOccurrence occurrence = (NameOccurrence) k.next();
109         if (occurrence.isOnLeftHandSide()) {
110             this.addVariableAccess(occurrence.getLocation(), new VariableAccess(VariableAccess.DEFINITION, occurrence.getImage()), inode.getFlow());
111         } else if (occurrence.isOnRightHandSide() || (!occurrence.isOnLeftHandSide() && !occurrence.isOnRightHandSide())) {
112             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     private void addVariableAccess(SimpleNode node, VariableAccess va, List JavaDoc flow) {
123         // backwards to find the right inode (not a method declaration)
124
for (int i = flow.size()-1; i > 0; i--) {
125             IDataFlowNode inode = (IDataFlowNode) flow.get(i);
126             if (inode.getSimpleNode() == null) {
127                 continue;
128             }
129
130             List JavaDoc children = inode.getSimpleNode().findChildrenOfType(node.getClass());
131             Iterator JavaDoc childrenIterator = children.iterator();
132             while (childrenIterator.hasNext()) {
133                 if (node.equals(childrenIterator.next())) {
134                     List JavaDoc v = new ArrayList JavaDoc();
135                     v.add(va);
136                     inode.setVariableAccess(v);
137                     return;
138                 }
139             }
140         }
141     }
142
143 }
144
Popular Tags