Added error "Unreachable code" for if statements
authoraxelcl <axelcl>
Sun, 17 Apr 2005 21:30:28 +0000 (21:30 +0000)
committeraxelcl <axelcl>
Sun, 17 Apr 2005 21:30:28 +0000 (21:30 +0000)
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/internal/compiler/ast/IfStatement.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/php/PHPAutoIndentStrategy.java

index 0bfc22c..4777170 100644 (file)
@@ -26,6 +26,7 @@ import net.sourceforge.phpeclipse.internal.compiler.ast.AND_AND_Expression;
 import net.sourceforge.phpeclipse.internal.compiler.ast.ASTNode;
 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
 import net.sourceforge.phpeclipse.internal.compiler.ast.BinaryExpression;
+import net.sourceforge.phpeclipse.internal.compiler.ast.Block;
 import net.sourceforge.phpeclipse.internal.compiler.ast.BreakStatement;
 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
 import net.sourceforge.phpeclipse.internal.compiler.ast.ConditionalExpression;
@@ -460,19 +461,18 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     return compilationUnit;
   }
 
-//  private boolean isVariable() {
-//    return token == TokenNameVariable; //  || token == TokenNamethis;
-//  }
-
-  private void statementList() {
+  private Block statementList() {
     boolean branchStatement = false;
     Statement statement;
     int sourceStart;
     int sourceEnd;
+    int blockStart = scanner.getCurrentTokenStartPosition();
+    ArrayList blockStatements = new ArrayList();
     do {
       try {
         sourceStart = scanner.getCurrentTokenStartPosition();
-        statement = statement(TokenNameEOF);
+        statement = statement();
+        blockStatements.add(statement);
         if (branchStatement) {
           sourceEnd = scanner.getCurrentTokenEndPosition();
           reportSyntaxError("Unreachable code", sourceStart, sourceEnd);
@@ -481,12 +481,10 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
             || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor)
             || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch)
             || (token == TokenNameenddeclare) || (token == TokenNameEOF) || (token == TokenNameERROR)) {
-          return;
-        }
-        branchStatement = false;
-        if (statement instanceof ReturnStatement ||statement instanceof ContinueStatement || statement instanceof BreakStatement) {
-          branchStatement = true;
+          return createBlock(blockStart, blockStatements);
         }
+        branchStatement = checkUnreachableStatements(statement);
+//        return createBlock(blockStart, blockStatements);
       } catch (SyntaxError sytaxErr1) {
         // if an error occured,
         // try to find keywords
@@ -501,7 +499,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
                 || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor)
                 || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch)
                 || (token == TokenNameenddeclare) || (token == TokenNameEOF) || (token == TokenNameERROR)) {
-              return;
+              return createBlock(blockStart, blockStatements);
             }
             if (token == TokenNameif || token == TokenNameswitch || token == TokenNamefor || token == TokenNamewhile
                 || token == TokenNamedo || token == TokenNameforeach || token == TokenNamecontinue || token == TokenNamebreak
@@ -525,6 +523,33 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     } while (true);
   }
 
+  /**
+   * @param statement
+   * @return
+   */
+  private boolean checkUnreachableStatements(Statement statement) {
+    boolean branchStatement = false;
+    if (statement instanceof ReturnStatement || statement instanceof ContinueStatement || statement instanceof BreakStatement) {
+      branchStatement = true;
+    } else if (statement instanceof IfStatement && ((IfStatement)statement).checkUnreachable) {
+      branchStatement = true;
+    }
+    return branchStatement;
+  }
+
+  /**
+   * @param blockStart
+   * @param blockStatements
+   * @return
+   */
+  private Block createBlock(int blockStart, ArrayList blockStatements) {
+    int blockEnd = scanner.getCurrentTokenEndPosition();
+    Block b = Block.EmptyWith(blockStart, blockEnd);
+    b.statements = new Statement[blockStatements.size()];
+    blockStatements.toArray(b.statements);
+    return b;
+  }
+
   private void functionBody(MethodDeclaration methodDecl) {
     // '{' [statement-list] '}'
     if (token == TokenNameLBRACE) {
@@ -543,12 +568,14 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     }
   }
 
-  private Statement statement(int previousToken) {
+  private Statement statement() {
     Statement statement = null;
     Expression expression;
     int sourceStart = scanner.getCurrentTokenStartPosition();
     int sourceEnd;
     if (token == TokenNameif) {
+      // T_IF '(' expr ')' statement elseif_list else_single
+      // T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';'
       getNextToken();
       if (token == TokenNameLPAREN) {
         getNextToken();
@@ -561,8 +588,15 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       } else {
         throwSyntaxError("')' expected after 'if' condition.");
       }
-      ifStatement();
-      return new IfStatement(expression, statement, sourceStart, scanner.getCurrentTokenEndPosition());
+      // create basic IfStatement
+      IfStatement ifStatement = new IfStatement(expression, null, null, sourceStart, -1);
+      if (token == TokenNameCOLON) {
+        getNextToken();
+        ifStatementColon(ifStatement);
+      } else {
+        ifStatement(ifStatement);
+      }
+      return ifStatement;
     } else if (token == TokenNameswitch) {
       getNextToken();
       if (token == TokenNameLPAREN) {
@@ -645,7 +679,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
           throwSyntaxError("'}' expected after 'do' keyword.");
         }
       } else {
-        statement(TokenNameEOF);
+        statement();
       }
       if (token == TokenNamewhile) {
         getNextToken();
@@ -715,7 +749,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
         sourceEnd = scanner.getCurrentTokenEndPosition();
         getNextToken();
       }
-      return new BreakStatement(null,sourceStart, sourceEnd);
+      return new BreakStatement(null, sourceStart, sourceEnd);
     } else if (token == TokenNamecontinue) {
       expression = null;
       getNextToken();
@@ -732,7 +766,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
         sourceEnd = scanner.getCurrentTokenEndPosition();
         getNextToken();
       }
-      return new ContinueStatement(null,sourceStart, sourceEnd);
+      return new ContinueStatement(null, sourceStart, sourceEnd);
     } else if (token == TokenNamereturn) {
       expression = null;
       getNextToken();
@@ -749,7 +783,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
         sourceEnd = scanner.getCurrentTokenEndPosition();
         getNextToken();
       }
-      return new ReturnStatement(expression,sourceStart, sourceEnd);
+      return new ReturnStatement(expression, sourceStart, sourceEnd);
     } else if (token == TokenNameecho) {
       getNextToken();
       expressionList();
@@ -924,7 +958,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     } else if (token == TokenNameLBRACE) {
       getNextToken();
       if (token != TokenNameRBRACE) {
-        statementList();
+        statement = statementList();
       }
       if (token == TokenNameRBRACE) {
         getNextToken();
@@ -971,7 +1005,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       }
       getNextToken();
     } else {
-      statement(TokenNameRPAREN);
+      statement();
     }
   }
 
@@ -1764,162 +1798,214 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
     } while (token == TokenNamecase || token == TokenNamedefault);
   }
 
-  //  public void labeledStatement() {
-  //    if (token == TokenNamecase) {
-  //      getNextToken();
-  //      constant();
-  //      if (token == TokenNameDDOT) {
-  //        getNextToken();
-  //        statement();
-  //      } else {
-  //        throwSyntaxError("':' character after 'case' constant expected.");
-  //      }
-  //      return;
-  //    } else if (token == TokenNamedefault) {
-  //      getNextToken();
-  //      if (token == TokenNameDDOT) {
-  //        getNextToken();
-  //        statement();
-  //      } else {
-  //        throwSyntaxError("':' character after 'default' expected.");
-  //      }
-  //      return;
-  //    }
-  //  }
-  //  public void expressionStatement() {
-  //  }
-  //  private void inclusionStatement() {
-  //  }
-  //  public void compoundStatement() {
-  //  }
-  //  public void selectionStatement() {
-  //  }
-  //
-  //  public void iterationStatement() {
-  //  }
-  //
-  //  public void jumpStatement() {
-  //  }
-  //
-  //  public void outputStatement() {
-  //  }
-  //
-  //  public void scopeStatement() {
-  //  }
-  //
-  //  public void flowStatement() {
-  //  }
-  //
-  //  public void definitionStatement() {
-  //  }
-  private void ifStatement() {
-    // ':' statement-list [elseif-list] [else-colon-statement] 'endif' ';'
-    if (token == TokenNameCOLON) {
-      getNextToken();
-      if (token != TokenNameendif) {
-        statementList();
-        switch (token) {
-        case TokenNameelse:
-          getNextToken();
-          if (token == TokenNameCOLON) {
-            getNextToken();
-            if (token != TokenNameendif) {
-              statementList();
-            }
-          } else {
-            if (token == TokenNameif) { //'else if'
-              getNextToken();
-              elseifStatementList();
-            } else {
-              throwSyntaxError("':' expected after 'else'.");
-            }
-          }
-          break;
-        case TokenNameelseif:
-          getNextToken();
-          elseifStatementList();
-          break;
-        }
-      }
-      if (token != TokenNameendif) {
-        throwSyntaxError("'endif' expected.");
-      }
+  private void ifStatementColon(IfStatement iState) {
+    // T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';'
+    Block b = inner_statement_list();
+    iState.thenStatement = b;
+    checkUnreachable(iState, b);
+    if (token == TokenNameelseif) {
+      new_elseif_list(iState);
+    } 
+    new_else_single(iState);
+    if (token != TokenNameendif) {
+      throwSyntaxError("'endif' expected.");
+    }
+    getNextToken();
+    if (token != TokenNameSEMICOLON) {
+      reportSyntaxError("';' expected after if-statement.");
+      iState.sourceEnd = scanner.getCurrentTokenStartPosition();
+    } else {
+      iState.sourceEnd = scanner.getCurrentTokenEndPosition();
       getNextToken();
-      if (token != TokenNameSEMICOLON) {
-        throwSyntaxError("';' expected after if-statement.");
-      }
+    }
+  }
+
+  private void ifStatement(IfStatement iState) {
+    //  T_IF '(' expr ')' statement elseif_list else_single
+    Statement s = statement();
+    iState.thenStatement = s;
+    checkUnreachable(iState, s);
+    if (token == TokenNameelseif) {
+      elseif_list(iState);
+    }
+    else_single(iState);
+  }
+
+  private void elseif_list(IfStatement iState) {
+    // /* empty */
+    //| elseif_list T_ELSEIF '(' expr ')' statement
+    ArrayList conditionList = new ArrayList();
+    ArrayList statementList = new ArrayList();
+    Expression e;
+    Statement s;
+    while (token == TokenNameelseif) {
       getNextToken();
-    } else {
-      // statement [else-statement]
-      statement(TokenNameEOF);
-      if (token == TokenNameelseif) {
+      if (token == TokenNameLPAREN) {
         getNextToken();
-        if (token == TokenNameLPAREN) {
-          getNextToken();
-        } else {
-          throwSyntaxError("'(' expected after 'elseif' keyword.");
-        }
-        expr();
-        if (token == TokenNameRPAREN) {
-          getNextToken();
-        } else {
-          throwSyntaxError("')' expected after 'elseif' condition.");
-        }
-        ifStatement();
-      } else if (token == TokenNameelse) {
+      } else {
+        throwSyntaxError("'(' expected after 'elseif' keyword.");
+      }
+      e = expr();
+      conditionList.add(e);
+      if (token == TokenNameRPAREN) {
         getNextToken();
-        statement(TokenNameEOF);
+      } else {
+        throwSyntaxError("')' expected after 'elseif' condition.");
       }
+      s = statement();
+      statementList.add(s);
+      checkUnreachable(iState, s);
     }
+    iState.elseifConditions = new Expression[conditionList.size()];
+    iState.elseifStatements = new Statement[statementList.size()];
+    conditionList.toArray(iState.elseifConditions);
+    statementList.toArray(iState.elseifStatements);
   }
 
-  private void elseifStatementList() {
-    do {
-      elseifStatement();
-      switch (token) {
-      case TokenNameelse:
+  private void new_elseif_list(IfStatement iState) {
+    // /* empty */
+    //| new_elseif_list T_ELSEIF '(' expr ')' ':' inner_statement_list
+    ArrayList conditionList = new ArrayList();
+    ArrayList statementList = new ArrayList();
+    Expression e;
+    Block b;
+    while (token == TokenNameelseif) {
+      getNextToken();
+      if (token == TokenNameLPAREN) {
         getNextToken();
-        if (token == TokenNameCOLON) {
-          getNextToken();
-          if (token != TokenNameendif) {
-            statementList();
-          }
-          return;
-        } else {
-          if (token == TokenNameif) { //'else if'
-            getNextToken();
-          } else {
-            throwSyntaxError("':' expected after 'else'.");
-          }
-        }
-        break;
-      case TokenNameelseif:
+      } else {
+        throwSyntaxError("'(' expected after 'elseif' keyword.");
+      }
+      e = expr();
+      conditionList.add(e);
+      if (token == TokenNameRPAREN) {
         getNextToken();
-        break;
-      default:
-        return;
+      } else {
+        throwSyntaxError("')' expected after 'elseif' condition.");
       }
-    } while (true);
+      if (token == TokenNameCOLON) {
+        getNextToken();
+      } else {
+        throwSyntaxError("':' expected after 'elseif' keyword.");
+      }
+      b = inner_statement_list();
+      statementList.add(b);
+      checkUnreachable(iState, b);
+    }
+    iState.elseifConditions = new Expression[conditionList.size()];
+    iState.elseifStatements = new Statement[statementList.size()];
+    conditionList.toArray(iState.elseifConditions);
+    statementList.toArray(iState.elseifStatements);
   }
 
-  private void elseifStatement() {
-    if (token == TokenNameLPAREN) {
+  private void else_single(IfStatement iState) {
+    // /* empty */
+    // T_ELSE statement
+    if (token == TokenNameelse) {
       getNextToken();
-      expr();
-      if (token != TokenNameRPAREN) {
-        throwSyntaxError("')' expected in else-if-statement.");
-      }
+      Statement s = statement();
+      iState.elseStatement = s;
+      checkUnreachable(iState, s);
+    } else {
+      iState.checkUnreachable = false;
+    }
+    iState.sourceEnd = scanner.getCurrentTokenStartPosition();
+  }
+
+  private void new_else_single(IfStatement iState) {
+    // /* empty */
+    //| T_ELSE ':' inner_statement_list
+    if (token == TokenNameelse) {
       getNextToken();
-      if (token != TokenNameCOLON) {
-        throwSyntaxError("':' expected in else-if-statement.");
+      if (token == TokenNameCOLON) {
+        getNextToken();
+      } else {
+        throwSyntaxError("':' expected after 'else' keyword.");
       }
-      getNextToken();
-      if (token != TokenNameendif) {
-        statementList();
+      Block b = inner_statement_list();
+      iState.elseStatement = b;
+      checkUnreachable(iState, b);
+    } else {
+      iState.checkUnreachable = false;
+    }
+  }
+
+  private Block inner_statement_list() {
+    // inner_statement_list inner_statement
+    // /* empty */
+    return statementList();
+  }
+
+  /**
+   * @param iState
+   * @param b
+   */
+  private void checkUnreachable(IfStatement iState, Statement s) {
+    if (s instanceof Block) {
+      Block b = (Block) s;
+      if (b.statements == null || b.statements.length == 0) {
+        iState.checkUnreachable = false;
+      } else {
+        int off = b.statements.length - 1;
+        if (!(b.statements[off] instanceof ReturnStatement) && !(b.statements[off] instanceof ContinueStatement)
+            && !(b.statements[off] instanceof BreakStatement)) {
+          iState.checkUnreachable = false;
+        }
+      }
+    } else {
+      if (!(s instanceof ReturnStatement) && !(s instanceof ContinueStatement) && !(s instanceof BreakStatement)) {
+        iState.checkUnreachable = false;
       }
     }
   }
 
+  //  private void elseifStatementList() {
+  //    do {
+  //      elseifStatement();
+  //      switch (token) {
+  //      case TokenNameelse:
+  //        getNextToken();
+  //        if (token == TokenNameCOLON) {
+  //          getNextToken();
+  //          if (token != TokenNameendif) {
+  //            statementList();
+  //          }
+  //          return;
+  //        } else {
+  //          if (token == TokenNameif) { //'else if'
+  //            getNextToken();
+  //          } else {
+  //            throwSyntaxError("':' expected after 'else'.");
+  //          }
+  //        }
+  //        break;
+  //      case TokenNameelseif:
+  //        getNextToken();
+  //        break;
+  //      default:
+  //        return;
+  //      }
+  //    } while (true);
+  //  }
+
+  //  private void elseifStatement() {
+  //    if (token == TokenNameLPAREN) {
+  //      getNextToken();
+  //      expr();
+  //      if (token != TokenNameRPAREN) {
+  //        throwSyntaxError("')' expected in else-if-statement.");
+  //      }
+  //      getNextToken();
+  //      if (token != TokenNameCOLON) {
+  //        throwSyntaxError("':' expected in else-if-statement.");
+  //      }
+  //      getNextToken();
+  //      if (token != TokenNameendif) {
+  //        statementList();
+  //      }
+  //    }
+  //  }
+
   private void switchStatement() {
     if (token == TokenNameCOLON) {
       // ':' [labeled-statement-list] 'endswitch' ';'
@@ -1962,7 +2048,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       }
       getNextToken();
     } else {
-      statement(TokenNameEOF);
+      statement();
     }
   }
 
@@ -1980,7 +2066,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       }
       getNextToken();
     } else {
-      statement(TokenNameEOF);
+      statement();
     }
   }
 
@@ -1997,7 +2083,7 @@ public class Parser implements ITerminalSymbols, CompilerModifiers, ParserBasicI
       }
       getNextToken();
     } else {
-      statement(TokenNameEOF);
+      statement();
     }
   }
 
index d0257f3..d76577b 100644 (file)
@@ -25,8 +25,11 @@ public class IfStatement extends Statement {
        public Expression condition;
        public Statement thenStatement;
        public Statement elseStatement;
-
+       public Expression[] elseifConditions;
+       public Statement[] elseifStatements;
+       public boolean checkUnreachable;
        boolean thenExit;
+       
 
        // for local variables table attributes
        int thenInitStateIndex = -1;
@@ -43,6 +46,7 @@ public class IfStatement extends Statement {
                this.thenStatement = thenStatement;
                sourceStart = s;
                sourceEnd = e;
+               checkUnreachable = true;
        }
 
        public IfStatement(
@@ -57,6 +61,7 @@ public class IfStatement extends Statement {
                this.elseStatement = elseStatement;
                sourceEnd = e;
                sourceStart = s;
+               checkUnreachable = true;
        }
 
        public FlowInfo analyseCode(
index 042fe11..5647b5b 100644 (file)
@@ -221,10 +221,17 @@ public class PHPAutoIndentStrategy extends DefaultAutoIndentStrategy {
                        } else {
                                int start= document.getLineOffset(line);
                                int whiteend= findEndOfWhiteSpace(document, start, command.offset);
+                               int offset = -1;
+//                             if (command.offset > 0 && command.offset < docLength && document.getChar(command.offset-1) == '{') {
+//                               offset = command.offset;
+//                             }
                                buf.append(document.get(start, whiteend - start));
                                if (getBracketCount(document, start, command.offset, true) > 0) {
                                        buf.append('\t');
                                }
+//                             if (offset >= 0) {
+//                               buf.append('}');
+//                             }
                        }
                        command.text= buf.toString();