View Javadoc

    1   /*
    2    * Created on 11.07.2004
    3    */
    4   package net.sourceforge.pmd.dfa;
    5
    6   import net.sourceforge.pmd.ast.*;
    7
    8   /***
    9    * @author raik
    10   *         <p/>
    11   *         Sublayer of DataFlowFacade. Finds all data flow nodes and stores the
    12   *         type information (@see StackObject). At last it uses this information to
    13   *         link the nodes.
    14   */
    15  public class StatementAndBraceFinder extends JavaParserVisitorAdapter {
    16
    17      private Structure dataFlow;
    18
    19      public void buildDataFlowFor(SimpleJavaNode node) {
    20          if (!(node instanceof ASTMethodDeclaration) && !(node instanceof ASTConstructorDeclaration)) {
    21              throw new RuntimeException("Can't build a data flow for anything other than a method or a constructor");
    22          }
    23
    24          this.dataFlow = new Structure();
    25          this.dataFlow.createStartNode(node.getBeginLine());
    26          this.dataFlow.createNewNode(node);
    27
    28          node.jjtAccept(this, dataFlow);
    29
    30          this.dataFlow.createEndNode(node.getEndLine());
    31
    32          Linker linker = new Linker(dataFlow.getBraceStack(), dataFlow.getContinueBreakReturnStack());
    33          try {
    34              linker.computePaths();
    35          } catch (LinkerException e) {
    36              e.printStackTrace();
    37          } catch (SequenceException e) {
    38              e.printStackTrace();
    39          }
    40      }
    41
    42      public Object visit(ASTStatementExpression node, Object data) {
    43          if (!(data instanceof Structure)) {
    44              return data;
    45          }
    46          Structure dataFlow = (Structure) data;
    47          dataFlow.createNewNode(node);
    48          return super.visit(node, data);
    49      }
    50
    51      public Object visit(ASTVariableDeclarator node, Object data) {
    52          if (!(data instanceof Structure)) {
    53              return data;
    54          }
    55          Structure dataFlow = (Structure) data;
    56          dataFlow.createNewNode(node);
    57          return super.visit(node, data);
    58      }
    59
    60      public Object visit(ASTExpression node, Object data) {
    61          if (!(data instanceof Structure)) {
    62              return data;
    63          }
    64          Structure dataFlow = (Structure) data;
    65
    66          // TODO what about throw stmts?
    67          if (node.jjtGetParent() instanceof ASTIfStatement) {
    68              dataFlow.createNewNode(node); // START IF
    69              dataFlow.pushOnStack(NodeType.IF_EXPR, dataFlow.getLast());
    70          } else if (node.jjtGetParent() instanceof ASTWhileStatement) {
    71              dataFlow.createNewNode(node); // START WHILE
    72              dataFlow.pushOnStack(NodeType.WHILE_EXPR, dataFlow.getLast());
    73          } else if (node.jjtGetParent() instanceof ASTSwitchStatement) {
    74              dataFlow.createNewNode(node); // START SWITCH
    75              dataFlow.pushOnStack(NodeType.SWITCH_START, dataFlow.getLast());
    76          } else if (node.jjtGetParent() instanceof ASTForStatement) {
    77              dataFlow.createNewNode(node); // FOR EXPR
    78              dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
    79          } else if (node.jjtGetParent() instanceof ASTDoStatement) {
    80              dataFlow.createNewNode(node); // DO EXPR
    81              dataFlow.pushOnStack(NodeType.DO_EXPR, dataFlow.getLast());
    82          }
    83
    84          return super.visit(node, data);
    85      }
    86
    87      public Object visit(ASTForInit node, Object data) {
    88          if (!(data instanceof Structure)) {
    89              return data;
    90          }
    91          Structure dataFlow = (Structure) data;
    92          super.visit(node, data);
    93          dataFlow.pushOnStack(NodeType.FOR_INIT, dataFlow.getLast());
    94          this.addForExpressionNode(node, dataFlow);
    95          return data;
    96      }
    97
    98      public Object visit(ASTForUpdate node, Object data) {
    99          if (!(data instanceof Structure)) {
    100             return data;
    101         }
    102         Structure dataFlow = (Structure) data;
    103         this.addForExpressionNode(node, dataFlow);
    104         super.visit(node, data);
    105         dataFlow.pushOnStack(NodeType.FOR_UPDATE, dataFlow.getLast());
    106         return data;
    107     }
    108
    109 // 	----------------------------------------------------------------------------
    110 //  BRANCH OUT
    111
    112     public Object visit(ASTStatement node, Object data) {
    113         if (!(data instanceof Structure)) {
    114             return data;
    115         }
    116         Structure dataFlow = (Structure) data;
    117
    118         if (node.jjtGetParent() instanceof ASTForStatement) {
    119             this.addForExpressionNode(node, dataFlow);
    120             dataFlow.pushOnStack(NodeType.FOR_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
    121         } else if (node.jjtGetParent() instanceof ASTDoStatement) {
    122             dataFlow.pushOnStack(NodeType.DO_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
    123             dataFlow.createNewNode((SimpleNode) node.jjtGetParent());
    124         }
    125
    126         super.visit(node, data);
    127
    128         if (node.jjtGetParent() instanceof ASTIfStatement) {
    129             ASTIfStatement st = (ASTIfStatement) node.jjtGetParent();
    130             if (!st.hasElse()) {
    131                 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE, dataFlow.getLast());
    132             } else if (st.hasElse() && !st.jjtGetChild(1).equals(node)) {
    133                 dataFlow.pushOnStack(NodeType.ELSE_LAST_STATEMENT, dataFlow.getLast());
    134             } else {
    135                 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT, dataFlow.getLast());
    136             }
    137         } else if (node.jjtGetParent() instanceof ASTWhileStatement) {
    138             dataFlow.pushOnStack(NodeType.WHILE_LAST_STATEMENT, dataFlow.getLast());
    139         } else if (node.jjtGetParent() instanceof ASTForStatement) {
    140             dataFlow.pushOnStack(NodeType.FOR_END, dataFlow.getLast());
    141         }
    142         return data;
    143     }
    144
    145     public Object visit(ASTSwitchStatement node, Object data) {
    146         if (!(data instanceof Structure)) {
    147             return data;
    148         }
    149         Structure dataFlow = (Structure) data;
    150         super.visit(node, data);
    151         dataFlow.pushOnStack(NodeType.SWITCH_END, dataFlow.getLast());
    152         return data;
    153     }
    154
    155     public Object visit(ASTSwitchLabel node, Object data) {
    156         if (!(data instanceof Structure)) {
    157             return data;
    158         }
    159         Structure dataFlow = (Structure) data;
    160         //super.visit(node, data);
    161         if (node.jjtGetNumChildren() == 0) {
    162             dataFlow.pushOnStack(NodeType.SWITCH_LAST_DEFAULT_STATEMENT, dataFlow.getLast());
    163         } else {
    164             dataFlow.pushOnStack(NodeType.CASE_LAST_STATEMENT, dataFlow.getLast());
    165         }
    166         return data;
    167     }
    168
    169     public Object visit(ASTBreakStatement node, Object data) {
    170         if (!(data instanceof Structure)) {
    171             return data;
    172         }
    173         Structure dataFlow = (Structure) data;
    174         dataFlow.createNewNode(node);
    175         dataFlow.pushOnStack(NodeType.BREAK_STATEMENT, dataFlow.getLast());
    176         return super.visit(node, data);
    177     }
    178
    179
    180     public Object visit(ASTContinueStatement node, Object data) {
    181         if (!(data instanceof Structure)) {
    182             return data;
    183         }
    184         Structure dataFlow = (Structure) data;
    185         dataFlow.createNewNode(node);
    186         dataFlow.pushOnStack(NodeType.CONTINUE_STATEMENT, dataFlow.getLast());
    187         return super.visit(node, data);
    188     }
    189
    190     public Object visit(ASTReturnStatement node, Object data) {
    191         if (!(data instanceof Structure)) {
    192             return data;
    193         }
    194         Structure dataFlow = (Structure) data;
    195         dataFlow.createNewNode(node);
    196         dataFlow.pushOnStack(NodeType.RETURN_STATEMENT, dataFlow.getLast());
    197         return super.visit(node, data);
    198     }
    199
    200     /*
    201      * The method handles the special "for" loop. It creates always an
    202      * expression node even if the loop looks like for(;;).
    203      * */
    204     private void addForExpressionNode(SimpleNode node, Structure dataFlow) {
    205         ASTForStatement parent = (ASTForStatement) node.jjtGetParent();
    206         boolean hasExpressionChild = false;
    207         boolean hasForInitNode = false;
    208         boolean hasForUpdateNode = false;
    209
    210         for (int i = 0; i < parent.jjtGetNumChildren(); i++) {
    211             if (parent.jjtGetChild(i) instanceof ASTExpression)
    212                 hasExpressionChild = true;
    213             else if (parent.jjtGetChild(i) instanceof ASTForUpdate)
    214                 hasForUpdateNode = true;
    215             else if (parent.jjtGetChild(i) instanceof ASTForInit)
    216                 hasForInitNode = true;
    217         }
    218         if (!hasExpressionChild) {
    219             if (node instanceof ASTForInit) {
    220                 dataFlow.createNewNode(node);
    221                 dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
    222             } else if (node instanceof ASTForUpdate) {
    223                 if (!hasForInitNode) {
    224                     dataFlow.createNewNode(node);
    225                     dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
    226                 }
    227             } else if (node instanceof ASTStatement) {
    228                 if (!hasForInitNode && !hasForUpdateNode) {
    229                     dataFlow.createNewNode(node);
    230                     dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
    231                 }
    232             }
    233         }
    234     }
    235 }