View Javadoc

    1   /**
    2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
    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(ASTLabeledStatement node, Object data) {
    99          dataFlow.createNewNode(node);
    100         dataFlow.pushOnStack(NodeType.LABEL_STATEMENT, dataFlow.getLast());
    101         return super.visit(node, data);
    102     }
    103
    104     public Object visit(ASTForUpdate node, Object data) {
    105         if (!(data instanceof Structure)) {
    106             return data;
    107         }
    108         Structure dataFlow = (Structure) data;
    109         this.addForExpressionNode(node, dataFlow);
    110         super.visit(node, data);
    111         dataFlow.pushOnStack(NodeType.FOR_UPDATE, dataFlow.getLast());
    112         return data;
    113     }
    114
    115 // 	----------------------------------------------------------------------------
    116 //  BRANCH OUT
    117
    118     public Object visit(ASTStatement node, Object data) {
    119         if (!(data instanceof Structure)) {
    120             return data;
    121         }
    122         Structure dataFlow = (Structure) data;
    123
    124         if (node.jjtGetParent() instanceof ASTForStatement) {
    125             this.addForExpressionNode(node, dataFlow);
    126             dataFlow.pushOnStack(NodeType.FOR_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
    127         } else if (node.jjtGetParent() instanceof ASTDoStatement) {
    128             dataFlow.pushOnStack(NodeType.DO_BEFORE_FIRST_STATEMENT, dataFlow.getLast());
    129             dataFlow.createNewNode((SimpleNode) node.jjtGetParent());
    130         }
    131
    132         super.visit(node, data);
    133
    134         if (node.jjtGetParent() instanceof ASTIfStatement) {
    135             ASTIfStatement st = (ASTIfStatement) node.jjtGetParent();
    136             if (!st.hasElse()) {
    137                 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE, dataFlow.getLast());
    138             } else if (st.hasElse() && !st.jjtGetChild(1).equals(node)) {
    139                 dataFlow.pushOnStack(NodeType.ELSE_LAST_STATEMENT, dataFlow.getLast());
    140             } else {
    141                 dataFlow.pushOnStack(NodeType.IF_LAST_STATEMENT, dataFlow.getLast());
    142             }
    143         } else if (node.jjtGetParent() instanceof ASTWhileStatement) {
    144             dataFlow.pushOnStack(NodeType.WHILE_LAST_STATEMENT, dataFlow.getLast());
    145         } else if (node.jjtGetParent() instanceof ASTForStatement) {
    146             dataFlow.pushOnStack(NodeType.FOR_END, dataFlow.getLast());
    147         } else if (node.jjtGetParent() instanceof ASTLabeledStatement) {
    148             dataFlow.pushOnStack(NodeType.LABEL_LAST_STATEMENT, dataFlow.getLast());
    149         }
    150         return data;
    151     }
    152
    153     public Object visit(ASTSwitchStatement node, Object data) {
    154         if (!(data instanceof Structure)) {
    155             return data;
    156         }
    157         Structure dataFlow = (Structure) data;
    158         super.visit(node, data);
    159         dataFlow.pushOnStack(NodeType.SWITCH_END, dataFlow.getLast());
    160         return data;
    161     }
    162
    163     public Object visit(ASTSwitchLabel node, Object data) {
    164         if (!(data instanceof Structure)) {
    165             return data;
    166         }
    167         Structure dataFlow = (Structure) data;
    168         //super.visit(node, data);
    169         if (node.jjtGetNumChildren() == 0) {
    170             dataFlow.pushOnStack(NodeType.SWITCH_LAST_DEFAULT_STATEMENT, dataFlow.getLast());
    171         } else {
    172             dataFlow.pushOnStack(NodeType.CASE_LAST_STATEMENT, dataFlow.getLast());
    173         }
    174         return data;
    175     }
    176
    177     public Object visit(ASTBreakStatement node, Object data) {
    178         if (!(data instanceof Structure)) {
    179             return data;
    180         }
    181         Structure dataFlow = (Structure) data;
    182         dataFlow.createNewNode(node);
    183         dataFlow.pushOnStack(NodeType.BREAK_STATEMENT, dataFlow.getLast());
    184         return super.visit(node, data);
    185     }
    186
    187
    188     public Object visit(ASTContinueStatement node, Object data) {
    189         if (!(data instanceof Structure)) {
    190             return data;
    191         }
    192         Structure dataFlow = (Structure) data;
    193         dataFlow.createNewNode(node);
    194         dataFlow.pushOnStack(NodeType.CONTINUE_STATEMENT, dataFlow.getLast());
    195         return super.visit(node, data);
    196     }
    197
    198     public Object visit(ASTReturnStatement node, Object data) {
    199         if (!(data instanceof Structure)) {
    200             return data;
    201         }
    202         Structure dataFlow = (Structure) data;
    203         dataFlow.createNewNode(node);
    204         dataFlow.pushOnStack(NodeType.RETURN_STATEMENT, dataFlow.getLast());
    205         return super.visit(node, data);
    206     }
    207
    208     public Object visit(ASTThrowStatement node, Object data) {
    209         if (!(data instanceof Structure)) {
    210             return data;
    211         }
    212         Structure dataFlow = (Structure) data;
    213         dataFlow.createNewNode(node);
    214         dataFlow.pushOnStack(NodeType.THROW_STATEMENT, dataFlow.getLast());
    215         return super.visit(node, data);
    216     }
    217
    218     /*
    219      * The method handles the special "for" loop. It creates always an
    220      * expression node even if the loop looks like for(;;).
    221      * */
    222     private void addForExpressionNode(SimpleNode node, Structure dataFlow) {
    223         ASTForStatement parent = (ASTForStatement) node.jjtGetParent();
    224         boolean hasExpressionChild = false;
    225         boolean hasForInitNode = false;
    226         boolean hasForUpdateNode = false;
    227
    228         for (int i = 0; i < parent.jjtGetNumChildren(); i++) {
    229             if (parent.jjtGetChild(i) instanceof ASTExpression)
    230                 hasExpressionChild = true;
    231             else if (parent.jjtGetChild(i) instanceof ASTForUpdate)
    232                 hasForUpdateNode = true;
    233             else if (parent.jjtGetChild(i) instanceof ASTForInit)
    234                 hasForInitNode = true;
    235         }
    236         if (!hasExpressionChild) {
    237             if (node instanceof ASTForInit) {
    238                 dataFlow.createNewNode(node);
    239                 dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
    240             } else if (node instanceof ASTForUpdate) {
    241                 if (!hasForInitNode) {
    242                     dataFlow.createNewNode(node);
    243                     dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
    244                 }
    245             } else if (node instanceof ASTStatement) {
    246                 if (!hasForInitNode && !hasForUpdateNode) {
    247                     dataFlow.createNewNode(node);
    248                     dataFlow.pushOnStack(NodeType.FOR_EXPR, dataFlow.getLast());
    249                 }
    250             }
    251         }
    252     }
    253 }