improved PHP parser
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / Compiler.java
index a8f006c..14bded4 100644 (file)
@@ -12,11 +12,13 @@ package net.sourceforge.phpdt.internal.compiler;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.Map;
+
 import net.sourceforge.phpdt.core.compiler.IProblem;
 import net.sourceforge.phpdt.internal.compiler.env.IBinaryType;
 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
 import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
 import net.sourceforge.phpdt.internal.compiler.impl.ITypeRequestor;
 import net.sourceforge.phpdt.internal.compiler.lookup.LookupEnvironment;
 import net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding;
@@ -28,10 +30,13 @@ import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
 import net.sourceforge.phpdt.internal.compiler.util.Util;
 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
+
+import org.eclipse.core.resources.IResource;
+
 public class Compiler implements ITypeRequestor, ProblemSeverities {
   public UnitParser parser;
   public ICompilerRequestor requestor;
-  //   public CompilerOptions options;
+  public CompilerOptions options;
   public ProblemReporter problemReporter;
   // management of unit to be processed
   //public CompilationUnitResult currentCompilationUnitResult;
@@ -92,11 +97,11 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
    *            problems, the compiler will gather them all and hand them back
    *            as part of the compilation unit result.
    */
-  public Compiler(INameEnvironment environment, IErrorHandlingPolicy policy, 
-  //           Map settings,
-      final ICompilerRequestor requestor, IProblemFactory problemFactory) {
+  public Compiler(INameEnvironment environment, IErrorHandlingPolicy policy,
+      Map settings, final ICompilerRequestor requestor,
+      IProblemFactory problemFactory) {
     // create a problem handler given a handling policy
-    //         this.options = new CompilerOptions(settings);
+    this.options = new CompilerOptions(settings);
     // wrap requestor in DebugRequestor if one is specified
     //         if(DebugRequestor == null) {
     this.requestor = requestor;
@@ -110,8 +115,8 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
     //                         }
     //                 };
     //         }
-    this.problemReporter = new ProblemReporter(policy, problemFactory);//this.options,
-                                                                       // problemFactory);
+    this.problemReporter = new ProblemReporter(policy, this.options,
+        problemFactory);
     this.lookupEnvironment = new LookupEnvironment(this, problemReporter,
         environment); //options, problemReporter, environment);
     this.parser = new UnitParser(problemReporter);
@@ -162,14 +167,13 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
    * @param parseLiteralExpressionsAsConstants
    *            <code>boolean</code> This parameter is used to optimize the
    *            literals or leave them as they are in the source. If you put
-   *            true, "Hello" + " world" will be converted to "Hello world".
+   *            true, "Hello" . " world" will be converted to "Hello world".
    */
-  public Compiler(INameEnvironment environment, IErrorHandlingPolicy policy, 
-  //           Map settings,
-      final ICompilerRequestor requestor, IProblemFactory problemFactory,
-      boolean parseLiteralExpressionsAsConstants) {
+  public Compiler(INameEnvironment environment, IErrorHandlingPolicy policy,
+      Map settings, final ICompilerRequestor requestor,
+      IProblemFactory problemFactory, boolean parseLiteralExpressionsAsConstants) {
     // create a problem handler given a handling policy
-    //         this.options = new CompilerOptions(settings);
+    this.options = new CompilerOptions(settings);
     // wrap requestor in DebugRequestor if one is specified
     //         if(DebugRequestor == null) {
     this.requestor = requestor;
@@ -183,9 +187,8 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
     //                         }
     //                 };
     //         }
-    this.problemReporter = new ProblemReporter(policy, problemFactory);//,
-                                                                       // this.options,
-                                                                       // problemFactory);
+    this.problemReporter = new ProblemReporter(policy, this.options,
+        problemFactory);
     this.lookupEnvironment = new LookupEnvironment(this, problemReporter,
         environment);//options, problemReporter, environment);
     this.parser = new UnitParser(problemReporter);
@@ -206,7 +209,7 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
     // Switch the current policy and compilation result for this unit to the
     // requested one.
     CompilationResult unitResult = new CompilationResult(sourceUnit,
-        totalUnits, totalUnits, 10); //this.options.maxProblemsPerUnit);
+        totalUnits, totalUnits, this.options.maxProblemsPerUnit);
     try {
       // diet parsing for large collection of unit
       CompilationUnitDeclaration parsedUnit;
@@ -215,16 +218,11 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
       } else {
         parsedUnit = parser.dietParse(sourceUnit, unitResult);
       }
-      //                       if (options.verbose) {
-      //                               String count = String.valueOf(totalUnits + 1);
-      //                               System.out.println(
-      //                                       Util.bind(
-      //                                               "compilation.request" , //$NON-NLS-1$
-      //                                               new String[] {
-      //                                                       count,
-      //                                                       count,
-      //                                                       new String(sourceUnit.getFileName())}));
-      //                       }
+      if (options.verbose) {
+        String count = String.valueOf(totalUnits + 1);
+        System.out.println(Util.bind("compilation.request", //$NON-NLS-1$
+            new String[]{count, count, new String(sourceUnit.getFileName())}));
+      }
       // initial type binding creation
       lookupEnvironment.buildTypeBindings(parsedUnit);
       this.addCompilationUnit(sourceUnit, parsedUnit);
@@ -274,7 +272,7 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
     for (int i = 0; i < maxUnits; i++) {
       CompilationUnitDeclaration parsedUnit;
       CompilationResult unitResult = new CompilationResult(sourceUnits[i], i,
-          maxUnits, 10);//, this.options.maxProblemsPerUnit);
+          maxUnits, this.options.maxProblemsPerUnit);
       try {
         // diet parsing for large collection of units
         if (totalUnits < parseThreshold) {
@@ -282,17 +280,13 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
         } else {
           parsedUnit = parser.dietParse(sourceUnits[i], unitResult);
         }
-        //                             if (options.verbose) {
-        //                                     System.out.println(
-        //                                             Util.bind(
-        //                                                     "compilation.request" , //$NON-NLS-1$
-        //                                                     new String[] {
-        //                                                             String.valueOf(i + 1),
-        //                                                             String.valueOf(maxUnits),
-        //                                                             new String(sourceUnits[i].getFileName())}));
-        //                             }
+        if (options.verbose) {
+          System.out.println(Util.bind("compilation.request", //$NON-NLS-1$
+              new String[]{String.valueOf(i + 1), String.valueOf(maxUnits),
+                  new String(sourceUnits[i].getFileName())}));
+        }
         // initial type binding creation
-//        lookupEnvironment.buildTypeBindings(parsedUnit);
+        //        lookupEnvironment.buildTypeBindings(parsedUnit);
         this.addCompilationUnit(sourceUnits[i], parsedUnit);
         //} catch (AbortCompilationUnit e) {
         //requestor.acceptResult(unitResult.tagAsAccepted());
@@ -318,30 +312,24 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
       for (; i < totalUnits; i++) {
         unit = unitsToProcess[i];
         try {
-          //                                   if (options.verbose)
-          //                                           System.out.println(
-          //                                                   Util.bind(
-          //                                                           "compilation.process" , //$NON-NLS-1$
-          //                                                           new String[] {
-          //                                                                   String.valueOf(i + 1),
-          //                                                                   String.valueOf(totalUnits),
-          //                                                                   new String(unitsToProcess[i].getFileName())}));
+          if (options.verbose)
+            System.out.println(Util.bind("compilation.process", //$NON-NLS-1$
+                new String[]{String.valueOf(i + 1), String.valueOf(totalUnits),
+                    new String(unitsToProcess[i].getFileName())}));
           process(unit, i);
         } finally {
           // cleanup compilation unit result
           unit.cleanUp();
-          //                                   if (options.verbose)
-          //                                           System.out.println(Util.bind("compilation.done", //$NON-NLS-1$
-          //                                   new String[] {
-          //                                           String.valueOf(i + 1),
-          //                                           String.valueOf(totalUnits),
-          //                                           new String(unitsToProcess[i].getFileName())}));
+          if (options.verbose)
+            System.out.println(Util.bind("compilation.done", //$NON-NLS-1$
+                new String[]{String.valueOf(i + 1), String.valueOf(totalUnits),
+                    new String(unitsToProcess[i].getFileName())}));
         }
         unitsToProcess[i] = null; // release reference to processed unit
-                                  // declaration
+        // declaration
         requestor.acceptResult(unit.compilationResult.tagAsAccepted());
       }
-    } catch (AbortCompilation e) {
+    } catch (AbortCompilation e) { 
       this.handleInternalException(e, unit);
     } catch (Error e) {
       this.handleInternalException(e, unit, null);
@@ -355,11 +343,11 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
     //         if (options.verbose) {
     //                 if (totalUnits > 1) {
     //                         System.out.println(
-    //                                 Util.bind("compilation.units" , String.valueOf(totalUnits)));
+    //                                 ProjectPrefUtil.bind("compilation.units" , String.valueOf(totalUnits)));
     // //$NON-NLS-1$
     //                 } else {
     //                         System.out.println(
-    //                                 Util.bind("compilation.unit" , String.valueOf(totalUnits)));
+    //                                 ProjectPrefUtil.bind("compilation.unit" , String.valueOf(totalUnits)));
     // //$NON-NLS-1$
     //                 }
     //         }
@@ -482,12 +470,12 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
    */
   public void process(CompilationUnitDeclaration unit, int i) {
     getMethodBodies(unit, i);
-    // fault in fields & methods  
-    if (unit.scope != null)  
+    // fault in fields & methods
+    if (unit.scope != null)
       unit.scope.faultInTypes();
     // verify inherited methods
-//    if (unit.scope != null)
-//      unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
+    //    if (unit.scope != null)
+    //      unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
     // type checking
     unit.resolve();
     // flow analysis
@@ -507,6 +495,72 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
     //         if (DebugRequestor != null) DebugRequestor.reset();
   }
   /**
+        * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+        */
+       public CompilationUnitDeclaration resolve(
+                       CompilationUnitDeclaration unit, 
+                       ICompilationUnit sourceUnit, 
+                       boolean verifyMethods,
+                       boolean analyzeCode) {
+                               
+               try {
+                       if (unit == null) {
+                               // build and record parsed units
+                               parseThreshold = 0; // will request a full parse
+                               beginToCompile(new ICompilationUnit[] { sourceUnit });
+                               // process all units (some more could be injected in the loop by the lookup environment)
+                               unit = unitsToProcess[0];
+                       } else {
+                               // initial type binding creation
+                               lookupEnvironment.buildTypeBindings(unit);
+
+                               // binding resolution
+                               lookupEnvironment.completeTypeBindings();
+                       }
+                       // TODO : jsurfer check this
+//                     this.parser.getMethodBodies(unit);
+                       getMethodBodies(unit, 0);
+                       
+                       if (unit.scope != null) {
+                               // fault in fields & methods
+                               unit.scope.faultInTypes();
+                               if (unit.scope != null && verifyMethods) {
+                                       // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
+                                       // verify inherited methods
+                                       unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
+                               }
+                               // type checking
+                               unit.resolve();         
+
+                               // flow analysis
+//                             if (analyzeCode) unit.analyseCode();
+               
+                               // code generation
+//                             if (generateCode) unit.generateCode();
+                       }
+                       if (unitsToProcess != null) unitsToProcess[0] = null; // release reference to processed unit declaration
+                       requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+                       return unit;
+               } catch (AbortCompilation e) {
+                       this.handleInternalException(e, unit);
+                       return unit == null ? unitsToProcess[0] : unit;
+               } catch (Error e) {
+                       this.handleInternalException(e, unit, null);
+                       throw e; // rethrow
+               } catch (RuntimeException e) {
+                       this.handleInternalException(e, unit, null);
+                       throw e; // rethrow
+               } finally {
+                       // No reset is performed there anymore since,
+                       // within the CodeAssist (or related tools),
+                       // the compiler may be called *after* a call
+                       // to this resolve(...) method. And such a call
+                       // needs to have a compiler with a non-empty
+                       // environment.
+                       // this.reset();
+               }
+       }
+  /**
    * Internal API used to resolve a given compilation unit. Can run a subset of
    * the compilation process
    */
@@ -538,7 +592,7 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
         //                             if (generateCode) unit.generateCode();
       }
       unitsToProcess[0] = null; // release reference to processed unit
-                                // declaration
+      // declaration
       requestor.acceptResult(unit.compilationResult.tagAsAccepted());
       return unit;
     } catch (AbortCompilation e) {
@@ -560,4 +614,5 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
       // this.reset();
     }
   }
-}
+
+}
\ No newline at end of file