View Javadoc

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.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          // is this necessary?  Why does the first node need undefs?
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          // undefinitions was once a field... seems like it works fine as a local
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 }