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 }