Parser detects wrong include files now
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / parser / Parser.java
index eccc174..73d504e 100644 (file)
@@ -1,9 +1,9 @@
 /***********************************************************************************************************************************
- * Copyright (c) 2002 Klaus Hartlage - www.eclipseproject.de All rights reserved. This program and the accompanying material are
+ * Copyright (c) 2002 www.phpeclipse.de All rights reserved. This program and the accompanying material are
  * made available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/cpl-v10.html
  * 
- * Contributors: Klaus Hartlage - www.eclipseproject.de
+ * Contributors: www.phpeclipse.de
  **********************************************************************************************************************************/
 package net.sourceforge.phpdt.internal.compiler.parser;
 
@@ -19,20 +19,31 @@ import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
 import net.sourceforge.phpdt.internal.compiler.util.Util;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
 import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
+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.CompilationUnitDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.ConditionalExpression;
+import net.sourceforge.phpeclipse.internal.compiler.ast.EqualExpression;
 import net.sourceforge.phpeclipse.internal.compiler.ast.Expression;
 import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
 import net.sourceforge.phpeclipse.internal.compiler.ast.IfStatement;
 import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
 import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.OR_OR_Expression;
 import net.sourceforge.phpeclipse.internal.compiler.ast.SingleTypeReference;
 import net.sourceforge.phpeclipse.internal.compiler.ast.Statement;
+import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteral;
+import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralDQ;
+import net.sourceforge.phpeclipse.internal.compiler.ast.StringLiteralSQ;
 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
 
 import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
 
 public class Parser //extends PHPParserSuperclass
     implements ITerminalSymbols, CompilerModifiers, ParserBasicInformation {
@@ -207,23 +218,6 @@ public class Parser //extends PHPParserSuperclass
   }
 
   /**
-   * Method Declaration.
-   * 
-   * @see
-   */
-  //  private void getChar() {
-  //    if (str.length() > chIndx) {
-  //      ch = str.charAt(chIndx++);
-  //
-  //      return;
-  //    }
-  //
-  //    chIndx = str.length() + 1;
-  //    ch = ' ';
-  //    // token = TokenNameEOF;
-  //    phpEnd = true;
-  //  }
-  /**
    * gets the next token from input
    */
   private void getNextToken() {
@@ -587,8 +581,8 @@ public class Parser //extends PHPParserSuperclass
       statement(TokenNameEOF);
       if ((token == TokenNameRBRACE) || (token == TokenNamecase) || (token == TokenNamedefault) || (token == TokenNameelse)
           || (token == TokenNameelseif) || (token == TokenNameendif) || (token == TokenNameendfor)
-          || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch) || (token == TokenNameenddeclare)
-          || (token == TokenNameEOF) || (token == TokenNameERROR)) {
+          || (token == TokenNameendforeach) || (token == TokenNameendwhile) || (token == TokenNameendswitch)
+          || (token == TokenNameenddeclare) || (token == TokenNameEOF) || (token == TokenNameERROR)) {
         return;
       }
     } while (true);
@@ -1978,10 +1972,12 @@ public class Parser //extends PHPParserSuperclass
   }
 
   private Expression expr_without_variable(boolean only_variable) {
+    int exprSourceStart = scanner.getCurrentTokenStartPosition();
+    int exprSourceEnd = scanner.getCurrentTokenEndPosition();
     Expression expression = new Expression();
-    expression.sourceStart = scanner.getCurrentTokenStartPosition();
+    expression.sourceStart = exprSourceStart;
     // default, may be overwritten
-    expression.sourceEnd = scanner.getCurrentTokenEndPosition();
+    expression.sourceEnd = exprSourceEnd;
     //         internal_functions_in_yacc
     // | T_CLONE expr
     // | T_PRINT expr
@@ -2135,11 +2131,17 @@ public class Parser //extends PHPParserSuperclass
       scanner.encapsedStringStack.push(new Character('\''));
       getNextToken();
       try {
+        exprSourceStart = scanner.getCurrentTokenStartPosition();
         if (token == TokenNameEncapsedString1) {
+          expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
+              .getCurrentTokenEndPosition());
         } else {
           encaps_list();
           if (token != TokenNameEncapsedString1) {
             throwSyntaxError("\'\'\' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
+          } else {
+            expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
+                .getCurrentTokenEndPosition());
           }
         }
       } finally {
@@ -2152,11 +2154,17 @@ public class Parser //extends PHPParserSuperclass
       scanner.encapsedStringStack.push(new Character('"'));
       getNextToken();
       try {
+        exprSourceStart = scanner.getCurrentTokenStartPosition();
         if (token == TokenNameEncapsedString2) {
+          expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
+              .getCurrentTokenEndPosition());
         } else {
           encaps_list();
           if (token != TokenNameEncapsedString2) {
             throwSyntaxError("'\"' expected at end of string" + "(Found token: " + scanner.toStringAction(token) + " )");
+          } else {
+            expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart), exprSourceStart, scanner
+                .getCurrentTokenEndPosition());
           }
         }
       } finally {
@@ -2164,10 +2172,18 @@ public class Parser //extends PHPParserSuperclass
         getNextToken();
       }
       break;
-    case TokenNameIntegerLiteral:
-    case TokenNameDoubleLiteral:
     case TokenNameStringDoubleQuote:
+      expression = new StringLiteralDQ(scanner.getCurrentStringLiteralSource(), scanner.getCurrentTokenStartPosition(), scanner
+          .getCurrentTokenEndPosition());
+      common_scalar();
+      break;
     case TokenNameStringSingleQuote:
+      expression = new StringLiteralSQ(scanner.getCurrentStringLiteralSource(), scanner.getCurrentTokenStartPosition(), scanner
+          .getCurrentTokenEndPosition());
+      common_scalar();
+      break;
+    case TokenNameIntegerLiteral:
+    case TokenNameDoubleLiteral:
     case TokenNameStringInterpolated:
     case TokenNameFILE:
     case TokenNameLINE:
@@ -2332,7 +2348,17 @@ public class Parser //extends PHPParserSuperclass
     while (true) {
       switch (token) {
       case TokenNameOR_OR:
+        getNextToken();
+        expression = new OR_OR_Expression(expression, expr(), token);
+        break;
       case TokenNameAND_AND:
+        getNextToken();
+        expression = new AND_AND_Expression(expression, expr(), token);
+        break;
+      case TokenNameEQUAL_EQUAL:
+        getNextToken();
+        expression = new EqualExpression(expression, expr(), token);
+        break;
       case TokenNameand:
       case TokenNameor:
       case TokenNamexor:
@@ -2349,28 +2375,34 @@ public class Parser //extends PHPParserSuperclass
       case TokenNameRIGHT_SHIFT:
       case TokenNameEQUAL_EQUAL_EQUAL:
       case TokenNameNOT_EQUAL_EQUAL:
-      case TokenNameEQUAL_EQUAL:
       case TokenNameNOT_EQUAL:
       case TokenNameLESS:
       case TokenNameLESS_EQUAL:
       case TokenNameGREATER:
       case TokenNameGREATER_EQUAL:
         getNextToken();
-        expr();
+        expression = new BinaryExpression(expression, expr(), token);
         break;
       //  | expr T_INSTANCEOF class_name_reference
       //       | expr '?' expr ':' expr
       case TokenNameinstanceof:
         getNextToken();
         class_name_reference();
+        // TODO use InstanceofExpression
+        expression = new Expression();
+        expression.sourceStart = exprSourceStart;
+        expression.sourceEnd = scanner.getCurrentTokenEndPosition();
         break;
       case TokenNameQUESTION:
         getNextToken();
-        expr();
-        if (token == TokenNameCOLON) {
-          getNextToken();
-          expr();
+        Expression valueIfTrue = expr();
+        if (token != TokenNameCOLON) {
+          throwSyntaxError("':' expected in conditional expression.");
         }
+        getNextToken();
+        Expression valueIfFalse = expr();
+
+        expression = new ConditionalExpression(expression, valueIfTrue, valueIfFalse);
         break;
       default:
         return expression;
@@ -3251,7 +3283,7 @@ public class Parser //extends PHPParserSuperclass
   }
 
   private void internal_functions_in_yacc() {
-    int start = 0;
+    //    int start = 0;
     ImportReference impt = null;
     switch (token) {
     case TokenNameisset:
@@ -3282,28 +3314,11 @@ public class Parser //extends PHPParserSuperclass
       break;
     case TokenNameinclude:
       //T_INCLUDE expr
-      start = scanner.getCurrentTokenStartPosition();
-      getNextToken();
-      expr();
-
-      impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
-      impt.declarationSourceEnd = impt.sourceEnd;
-      impt.declarationEnd = impt.declarationSourceEnd;
-      //endPosition is just before the ;
-      impt.declarationSourceStart = start;
-      includesList.add(impt);
+      checkFileName(token, impt);
       break;
     case TokenNameinclude_once:
       //       T_INCLUDE_ONCE expr
-      start = scanner.getCurrentTokenStartPosition();
-      getNextToken();
-      expr();
-      impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
-      impt.declarationSourceEnd = impt.sourceEnd;
-      impt.declarationEnd = impt.declarationSourceEnd;
-      //endPosition is just before the ;
-      impt.declarationSourceStart = start;
-      includesList.add(impt);
+      checkFileName(token, impt);
       break;
     case TokenNameeval:
       //       T_EVAL '(' expr ')'
@@ -3320,31 +3335,78 @@ public class Parser //extends PHPParserSuperclass
       break;
     case TokenNamerequire:
       //T_REQUIRE expr
-      start = scanner.getCurrentTokenStartPosition();
-      getNextToken();
-      expr();
-      impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
-      impt.declarationSourceEnd = impt.sourceEnd;
-      impt.declarationEnd = impt.declarationSourceEnd;
-      //endPosition is just before the ;
-      impt.declarationSourceStart = start;
-      includesList.add(impt);
+      checkFileName(token, impt);
       break;
     case TokenNamerequire_once:
       //       T_REQUIRE_ONCE expr
-      start = scanner.getCurrentTokenStartPosition();
-      getNextToken();
-      expr();
-      impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
-      impt.declarationSourceEnd = impt.sourceEnd;
-      impt.declarationEnd = impt.declarationSourceEnd;
-      //endPosition is just before the ;
-      impt.declarationSourceStart = start;
-      includesList.add(impt);
+      checkFileName(token, impt);
       break;
     }
   }
 
+  private void checkFileName(int includeToken, ImportReference impt) {
+    //<include-token> expr
+    int start = scanner.getCurrentTokenStartPosition();
+    boolean hasLPAREN = false;
+    getNextToken();
+    if (token == TokenNameLPAREN) {
+      hasLPAREN = true;
+      getNextToken();
+    }
+    Expression expression = expr();
+    if (hasLPAREN) {
+      if (token == TokenNameRPAREN) {
+        getNextToken();
+      } else {
+        throwSyntaxError("')' expected for keyword '" + scanner.toStringAction(includeToken) + "'");
+      }
+    }
+    impt = new ImportReference(scanner.getCurrentTokenSource(start), start, scanner.getCurrentTokenEndPosition(), false);
+    impt.declarationSourceEnd = impt.sourceEnd;
+    impt.declarationEnd = impt.declarationSourceEnd;
+    //endPosition is just before the ;
+    impt.declarationSourceStart = start;
+    includesList.add(impt);
+
+    if (expression instanceof StringLiteral) {
+      StringLiteral literal = (StringLiteral) expression;
+      char[] includeName = literal.source();
+      if (includeName.length == 0) {
+        reportSyntaxError("Empty filename after keyword '" + scanner.toStringAction(includeToken) + "'", literal.sourceStart,
+            literal.sourceStart + 1);
+      }
+      String includeNameString = new String(includeName);
+      if (literal instanceof StringLiteralDQ) {
+        if (includeNameString.indexOf('$') >= 0) {
+          // assuming that the filename contains a variable => no filename check
+          return;
+        }
+      }
+      if (includeNameString.startsWith("http://")) {
+        // assuming external include location
+        return;
+      }
+      if (scanner.compilationUnit != null) {
+        IResource resource = scanner.compilationUnit.getResource();
+        //        java.io.File f = new java.io.File(new String(compilationUnit.getFileName()));
+        //        System.out.println(expression.toStringExpression());
+        //      }
+        if (resource != null && resource instanceof IFile) {
+          // check the filename:
+          //      System.out.println(new String(compilationUnit.getFileName())+" - "+ expression.toStringExpression());
+          IProject project = resource.getProject();
+          if (project != null) {
+            if (PHPFileUtil.determineFilePath(includeNameString, resource, project) == null) {
+              reportSyntaxError("File: " + expression.toStringExpression() + " doesn't exist in project: "
+                  + project.getLocation().toString(), literal.sourceStart, literal.sourceEnd);
+              //              System.out.println(path.toString() + " - " + expression.toStringExpression());
+            }
+          }
+        }
+      }
+    }
+  }
+
   private void isset_variables() {
     // variable
     // | isset_variables ','