RC2 compatibility
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / Compiler.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler;
12 import java.io.PrintWriter;
13 import java.io.StringWriter;
14 import java.util.Map;
15
16 import net.sourceforge.phpdt.core.compiler.IProblem;
17 import net.sourceforge.phpdt.internal.compiler.env.IBinaryType;
18 import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
19 import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
20 import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
21 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
22 import net.sourceforge.phpdt.internal.compiler.impl.ITypeRequestor;
23 import net.sourceforge.phpdt.internal.compiler.lookup.LookupEnvironment;
24 import net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding;
25 import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
26 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
27 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilationUnit;
28 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
29 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
30 import net.sourceforge.phpdt.internal.compiler.util.Util;
31 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
32 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
33 public class Compiler implements ITypeRequestor, ProblemSeverities {
34   public UnitParser parser;
35   public ICompilerRequestor requestor;
36   public CompilerOptions options;
37   public ProblemReporter problemReporter;
38   // management of unit to be processed
39   //public CompilationUnitResult currentCompilationUnitResult;
40   public CompilationUnitDeclaration[] unitsToProcess;
41   public int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess
42   // name lookup
43   public LookupEnvironment lookupEnvironment;
44   // ONCE STABILIZED, THESE SHOULD RETURN TO A FINAL FIELD
45   public static boolean DEBUG = true;
46   public int parseThreshold = -1;
47   // number of initial units parsed at once (-1: none)
48   /*
49    * Static requestor reserved to listening compilation results in debug mode,
50    * so as for example to monitor compiler activity independantly from a
51    * particular builder implementation. It is reset at the end of compilation,
52    * and should not persist any information after having been reset.
53    */
54   //    public static IDebugRequestor DebugRequestor = null;
55   /**
56    * Answer a new compiler using the given name environment and compiler
57    * options. The environment and options will be in effect for the lifetime of
58    * the compiler. When the compiler is run, compilation results are sent to
59    * the given requestor.
60    * 
61    * @param environment
62    *            org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
63    *            Environment used by the compiler in order to resolve type and
64    *            package names. The name environment implements the actual
65    *            connection of the compiler to the outside world (e.g. in batch
66    *            mode the name environment is performing pure file accesses,
67    *            reuse previous build state or connection to repositories).
68    *            Note: the name environment is responsible for implementing the
69    *            actual classpath rules.
70    * 
71    * @param policy
72    *            org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
73    *            Configurable part for problem handling, allowing the compiler
74    *            client to specify the rules for handling problems (stop on
75    *            first error or accumulate them all) and at the same time
76    *            perform some actions such as opening a dialog in UI when
77    *            compiling interactively.
78    * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
79    * 
80    * @param requestor
81    *            org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
82    *            Component which will receive and persist all compilation
83    *            results and is intended to consume them as they are produced.
84    *            Typically, in a batch compiler, it is responsible for writing
85    *            out the actual .class files to the file system.
86    * @see org.eclipse.jdt.internal.compiler.CompilationResult
87    * 
88    * @param problemFactory
89    *            org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
90    *            Factory used inside the compiler to create problem descriptors.
91    *            It allows the compiler client to supply its own representation
92    *            of compilation problems in order to avoid object conversions.
93    *            Note that the factory is not supposed to accumulate the created
94    *            problems, the compiler will gather them all and hand them back
95    *            as part of the compilation unit result.
96    */
97   public Compiler(INameEnvironment environment, IErrorHandlingPolicy policy,
98       Map settings, final ICompilerRequestor requestor,
99       IProblemFactory problemFactory) {
100     // create a problem handler given a handling policy
101     this.options = new CompilerOptions(settings);
102     // wrap requestor in DebugRequestor if one is specified
103     //          if(DebugRequestor == null) {
104     this.requestor = requestor;
105     //          } else {
106     //                  this.requestor = new ICompilerRequestor(){
107     //                          public void acceptResult(CompilationResult result){
108     //                                  if (DebugRequestor.isActive()){
109     //                                          DebugRequestor.acceptDebugResult(result);
110     //                                  }
111     //                                  requestor.acceptResult(result);
112     //                          }
113     //                  };
114     //          }
115     this.problemReporter = new ProblemReporter(policy, this.options,
116         problemFactory);
117     this.lookupEnvironment = new LookupEnvironment(this, problemReporter,
118         environment); //options, problemReporter, environment);
119     this.parser = new UnitParser(problemReporter);
120     //                          this.options.parseLiteralExpressionsAsConstants,
121     //                          options.sourceLevel >= CompilerOptions.JDK1_4);
122   }
123   /**
124    * Answer a new compiler using the given name environment and compiler
125    * options. The environment and options will be in effect for the lifetime of
126    * the compiler. When the compiler is run, compilation results are sent to
127    * the given requestor.
128    * 
129    * @param environment
130    *            org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
131    *            Environment used by the compiler in order to resolve type and
132    *            package names. The name environment implements the actual
133    *            connection of the compiler to the outside world (e.g. in batch
134    *            mode the name environment is performing pure file accesses,
135    *            reuse previous build state or connection to repositories).
136    *            Note: the name environment is responsible for implementing the
137    *            actual classpath rules.
138    * 
139    * @param policy
140    *            org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
141    *            Configurable part for problem handling, allowing the compiler
142    *            client to specify the rules for handling problems (stop on
143    *            first error or accumulate them all) and at the same time
144    *            perform some actions such as opening a dialog in UI when
145    *            compiling interactively.
146    * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
147    * 
148    * @param requestor
149    *            org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
150    *            Component which will receive and persist all compilation
151    *            results and is intended to consume them as they are produced.
152    *            Typically, in a batch compiler, it is responsible for writing
153    *            out the actual .class files to the file system.
154    * @see org.eclipse.jdt.internal.compiler.CompilationResult
155    * 
156    * @param problemFactory
157    *            org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
158    *            Factory used inside the compiler to create problem descriptors.
159    *            It allows the compiler client to supply its own representation
160    *            of compilation problems in order to avoid object conversions.
161    *            Note that the factory is not supposed to accumulate the created
162    *            problems, the compiler will gather them all and hand them back
163    *            as part of the compilation unit result.
164    * @param parseLiteralExpressionsAsConstants
165    *            <code>boolean</code> This parameter is used to optimize the
166    *            literals or leave them as they are in the source. If you put
167    *            true, "Hello" + " world" will be converted to "Hello world".
168    */
169   public Compiler(INameEnvironment environment, IErrorHandlingPolicy policy,
170       Map settings, final ICompilerRequestor requestor,
171       IProblemFactory problemFactory, boolean parseLiteralExpressionsAsConstants) {
172     // create a problem handler given a handling policy
173     this.options = new CompilerOptions(settings);
174     // wrap requestor in DebugRequestor if one is specified
175     //          if(DebugRequestor == null) {
176     this.requestor = requestor;
177     //          } else {
178     //                  this.requestor = new ICompilerRequestor(){
179     //                          public void acceptResult(CompilationResult result){
180     //                                  if (DebugRequestor.isActive()){
181     //                                          DebugRequestor.acceptDebugResult(result);
182     //                                  }
183     //                                  requestor.acceptResult(result);
184     //                          }
185     //                  };
186     //          }
187     this.problemReporter = new ProblemReporter(policy, this.options,
188         problemFactory);
189     this.lookupEnvironment = new LookupEnvironment(this, problemReporter,
190         environment);//options, problemReporter, environment);
191     this.parser = new UnitParser(problemReporter);
192     //                          parseLiteralExpressionsAsConstants,
193     //                          this.options.sourceLevel >= CompilerOptions.JDK1_4);
194   }
195   /**
196    * Add an additional binary type
197    */
198   public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
199     lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
200   }
201   /**
202    * Add an additional compilation unit into the loop -> build compilation unit
203    * declarations, their bindings and record their results.
204    */
205   public void accept(ICompilationUnit sourceUnit) {
206     // Switch the current policy and compilation result for this unit to the
207     // requested one.
208     CompilationResult unitResult = new CompilationResult(sourceUnit,
209         totalUnits, totalUnits, this.options.maxProblemsPerUnit);
210     try {
211       // diet parsing for large collection of unit
212       CompilationUnitDeclaration parsedUnit;
213       if (totalUnits < parseThreshold) {
214         parsedUnit = parser.parse(sourceUnit, unitResult, false);
215       } else {
216         parsedUnit = parser.dietParse(sourceUnit, unitResult);
217       }
218       if (options.verbose) {
219         String count = String.valueOf(totalUnits + 1);
220         System.out.println(Util.bind("compilation.request", //$NON-NLS-1$
221             new String[]{count, count, new String(sourceUnit.getFileName())}));
222       }
223       // initial type binding creation
224       lookupEnvironment.buildTypeBindings(parsedUnit);
225       this.addCompilationUnit(sourceUnit, parsedUnit);
226       // binding resolution
227       lookupEnvironment.completeTypeBindings(parsedUnit);
228     } catch (AbortCompilationUnit e) {
229       // at this point, currentCompilationUnitResult may not be sourceUnit, but
230       // some other
231       // one requested further along to resolve sourceUnit.
232       if (unitResult.compilationUnit == sourceUnit) { // only report once
233         requestor.acceptResult(unitResult.tagAsAccepted());
234       } else {
235         throw e; // want to abort enclosing request to compile
236       }
237     }
238   }
239   /**
240    * Add additional source types
241    */
242   public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
243     problemReporter.abortDueToInternalError(Util.bind(
244         "abort.againstSourceModel ", //$NON-NLS-1$
245         String.valueOf(sourceTypes[0].getName()), String.valueOf(sourceTypes[0]
246             .getFileName())));
247   }
248   protected void addCompilationUnit(ICompilationUnit sourceUnit,
249       CompilationUnitDeclaration parsedUnit) {
250     // append the unit to the list of ones to process later on
251     int size = unitsToProcess.length;
252     if (totalUnits == size)
253       // when growing reposition units starting at position 0
254       System.arraycopy(unitsToProcess, 0,
255           (unitsToProcess = new CompilationUnitDeclaration[size * 2]), 0,
256           totalUnits);
257     unitsToProcess[totalUnits++] = parsedUnit;
258   }
259   /**
260    * Add the initial set of compilation units into the loop -> build
261    * compilation unit declarations, their bindings and record their results.
262    */
263   protected void beginToCompile(ICompilationUnit[] sourceUnits) {
264     int maxUnits = sourceUnits.length;
265     totalUnits = 0;
266     unitsToProcess = new CompilationUnitDeclaration[maxUnits];
267     // Switch the current policy and compilation result for this unit to the
268     // requested one.
269     for (int i = 0; i < maxUnits; i++) {
270       CompilationUnitDeclaration parsedUnit;
271       CompilationResult unitResult = new CompilationResult(sourceUnits[i], i,
272           maxUnits, this.options.maxProblemsPerUnit);
273       try {
274         // diet parsing for large collection of units
275         if (totalUnits < parseThreshold) {
276           parsedUnit = parser.parse(sourceUnits[i], unitResult, false);
277         } else {
278           parsedUnit = parser.dietParse(sourceUnits[i], unitResult);
279         }
280         if (options.verbose) {
281           System.out.println(Util.bind("compilation.request", //$NON-NLS-1$
282               new String[]{String.valueOf(i + 1), String.valueOf(maxUnits),
283                   new String(sourceUnits[i].getFileName())}));
284         }
285         // initial type binding creation
286         //        lookupEnvironment.buildTypeBindings(parsedUnit);
287         this.addCompilationUnit(sourceUnits[i], parsedUnit);
288         //} catch (AbortCompilationUnit e) {
289         //requestor.acceptResult(unitResult.tagAsAccepted());
290       } finally {
291         sourceUnits[i] = null; // no longer hold onto the unit
292       }
293     }
294     // binding resolution
295     lookupEnvironment.completeTypeBindings();
296   }
297   /**
298    * General API -> compile each of supplied files -> recompile any required
299    * types for which we have an incomplete principle structure
300    */
301   public void compile(ICompilationUnit[] sourceUnits) {
302     CompilationUnitDeclaration unit = null;
303     int i = 0;
304     try {
305       // build and record parsed units
306       beginToCompile(sourceUnits);
307       // process all units (some more could be injected in the loop by the
308       // lookup environment)
309       for (; i < totalUnits; i++) {
310         unit = unitsToProcess[i];
311         try {
312           if (options.verbose)
313             System.out.println(Util.bind("compilation.process", //$NON-NLS-1$
314                 new String[]{String.valueOf(i + 1), String.valueOf(totalUnits),
315                     new String(unitsToProcess[i].getFileName())}));
316           process(unit, i);
317         } finally {
318           // cleanup compilation unit result
319           unit.cleanUp();
320           if (options.verbose)
321             System.out.println(Util.bind("compilation.done", //$NON-NLS-1$
322                 new String[]{String.valueOf(i + 1), String.valueOf(totalUnits),
323                     new String(unitsToProcess[i].getFileName())}));
324         }
325         unitsToProcess[i] = null; // release reference to processed unit
326         // declaration
327         requestor.acceptResult(unit.compilationResult.tagAsAccepted());
328       }
329     } catch (AbortCompilation e) { 
330       this.handleInternalException(e, unit);
331     } catch (Error e) {
332       this.handleInternalException(e, unit, null);
333       throw e; // rethrow
334     } catch (RuntimeException e) {
335       this.handleInternalException(e, unit, null);
336       throw e; // rethrow
337     } finally {
338       this.reset();
339     }
340     //          if (options.verbose) {
341     //                  if (totalUnits > 1) {
342     //                          System.out.println(
343     //                                  Util.bind("compilation.units" , String.valueOf(totalUnits)));
344     // //$NON-NLS-1$
345     //                  } else {
346     //                          System.out.println(
347     //                                  Util.bind("compilation.unit" , String.valueOf(totalUnits)));
348     // //$NON-NLS-1$
349     //                  }
350     //          }
351   }
352   protected void getMethodBodies(CompilationUnitDeclaration unit, int place) {
353     //fill the methods bodies in order for the code to be generated
354     if (unit.ignoreMethodBodies) {
355       unit.ignoreFurtherInvestigation = true;
356       return;
357       // if initial diet parse did not work, no need to dig into method bodies.
358     }
359     if (place < parseThreshold)
360       return; //work already done ...
361     //real parse of the method....
362     parser.scanner.setSource(unit.compilationResult.compilationUnit
363         .getContents());
364     if (unit.types != null) {
365       for (int i = unit.types.size(); --i >= 0;)
366         if (unit.types.get(i) instanceof TypeDeclaration) {
367           ((TypeDeclaration) unit.types.get(i)).parseMethod(parser, unit);
368         }
369     }
370   }
371   /*
372    * Compiler crash recovery in case of unexpected runtime exceptions
373    */
374   protected void handleInternalException(Throwable internalException,
375       CompilationUnitDeclaration unit, CompilationResult result) {
376     /* dump a stack trace to the console */
377     internalException.printStackTrace();
378     /* find a compilation result */
379     if ((unit != null)) // basing result upon the current unit if available
380       result = unit.compilationResult; // current unit being processed ?
381     if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
382       result = unitsToProcess[totalUnits - 1].compilationResult;
383     // last unit in beginToCompile ?
384     if (result != null) {
385       /* create and record a compilation problem */
386       StringWriter stringWriter = new StringWriter();
387       PrintWriter writer = new PrintWriter(stringWriter);
388       internalException.printStackTrace(writer);
389       StringBuffer buffer = stringWriter.getBuffer();
390       String[] pbArguments = new String[]{Util
391           .bind("compilation.internalError")
392           //$NON-NLS-1$
393           + "\n" //$NON-NLS-1$
394           + buffer.toString()};
395       result.record(problemReporter.createProblem(result.getFileName(),
396           IProblem.Unclassified, pbArguments, pbArguments, Error, // severity
397           0, // source start
398           0, // source end
399           0, // line number
400           unit, result), unit);
401       /* hand back the compilation result */
402       if (!result.hasBeenAccepted) {
403         requestor.acceptResult(result.tagAsAccepted());
404       }
405     }
406   }
407   /*
408    * Compiler recovery in case of internal AbortCompilation event
409    */
410   protected void handleInternalException(AbortCompilation abortException,
411       CompilationUnitDeclaration unit) {
412     /*
413      * special treatment for SilentAbort: silently cancelling the compilation
414      * process
415      */
416     if (abortException.isSilent) {
417       if (abortException.silentException == null) {
418         return;
419       } else {
420         throw abortException.silentException;
421       }
422     }
423     /* uncomment following line to see where the abort came from */
424     // abortException.printStackTrace();
425     // Exception may tell which compilation result it is related, and which
426     // problem caused it
427     CompilationResult result = abortException.compilationResult;
428     if ((result == null) && (unit != null))
429       result = unit.compilationResult; // current unit being processed ?
430     if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
431       result = unitsToProcess[totalUnits - 1].compilationResult;
432     // last unit in beginToCompile ?
433     if (result != null && !result.hasBeenAccepted) {
434       /* distant problem which could not be reported back there */
435       if (abortException.problemId != 0) {
436         result.record(problemReporter.createProblem(result.getFileName(),
437             abortException.problemId, abortException.problemArguments,
438             abortException.messageArguments, Error, // severity
439             0, // source start
440             0, // source end
441             0, // line number
442             unit, result), unit);
443       } else {
444         /* distant internal exception which could not be reported back there */
445         if (abortException.exception != null) {
446           this.handleInternalException(abortException.exception, null, result);
447           return;
448         }
449       }
450       /* hand back the compilation result */
451       if (!result.hasBeenAccepted) {
452         requestor.acceptResult(result.tagAsAccepted());
453       }
454     } else {
455       /*
456        * if (abortException.problemId != 0){ IProblem problem =
457        * problemReporter.createProblem( "???".toCharArray(),
458        * abortException.problemId, abortException.problemArguments, Error, //
459        * severity 0, // source start 0, // source end 0); // line number
460        * System.out.println(problem.getMessage()); }
461        */
462       abortException.printStackTrace();
463     }
464   }
465   /**
466    * Process a compilation unit already parsed and build.
467    */
468   public void process(CompilationUnitDeclaration unit, int i) {
469     getMethodBodies(unit, i);
470     // fault in fields & methods
471     if (unit.scope != null)
472       unit.scope.faultInTypes();
473     // verify inherited methods
474     //    if (unit.scope != null)
475     //      unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
476     // type checking
477     unit.resolve();
478     // flow analysis
479     unit.analyseCode();
480     // code generation
481     //          unit.generateCode();
482     // reference info
483     //          if (options.produceReferenceInfo && unit.scope != null)
484     //                  unit.scope.storeDependencyInfo();
485     // refresh the total number of units known at this stage
486     unit.compilationResult.totalUnitsKnown = totalUnits;
487   }
488   public void reset() {
489     lookupEnvironment.reset();
490     parser.scanner.source = null;
491     unitsToProcess = null;
492     //          if (DebugRequestor != null) DebugRequestor.reset();
493   }
494   /**
495          * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
496          */
497         public CompilationUnitDeclaration resolve(
498                         CompilationUnitDeclaration unit, 
499                         ICompilationUnit sourceUnit, 
500                         boolean verifyMethods,
501                         boolean analyzeCode) {
502                                 
503                 try {
504                         if (unit == null) {
505                                 // build and record parsed units
506                                 parseThreshold = 0; // will request a full parse
507                                 beginToCompile(new ICompilationUnit[] { sourceUnit });
508                                 // process all units (some more could be injected in the loop by the lookup environment)
509                                 unit = unitsToProcess[0];
510                         } else {
511                                 // initial type binding creation
512                                 lookupEnvironment.buildTypeBindings(unit);
513
514                                 // binding resolution
515                                 lookupEnvironment.completeTypeBindings();
516                         }
517                         // TODO : jsurfer check this
518 //                      this.parser.getMethodBodies(unit);
519                         getMethodBodies(unit, 0);
520                         
521                         if (unit.scope != null) {
522                                 // fault in fields & methods
523                                 unit.scope.faultInTypes();
524                                 if (unit.scope != null && verifyMethods) {
525                                         // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
526                                         // verify inherited methods
527                                         unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
528                                 }
529                                 // type checking
530                                 unit.resolve();         
531
532                                 // flow analysis
533 //                              if (analyzeCode) unit.analyseCode();
534                 
535                                 // code generation
536 //                              if (generateCode) unit.generateCode();
537                         }
538                         if (unitsToProcess != null) unitsToProcess[0] = null; // release reference to processed unit declaration
539                         requestor.acceptResult(unit.compilationResult.tagAsAccepted());
540                         return unit;
541                 } catch (AbortCompilation e) {
542                         this.handleInternalException(e, unit);
543                         return unit == null ? unitsToProcess[0] : unit;
544                 } catch (Error e) {
545                         this.handleInternalException(e, unit, null);
546                         throw e; // rethrow
547                 } catch (RuntimeException e) {
548                         this.handleInternalException(e, unit, null);
549                         throw e; // rethrow
550                 } finally {
551                         // No reset is performed there anymore since,
552                         // within the CodeAssist (or related tools),
553                         // the compiler may be called *after* a call
554                         // to this resolve(...) method. And such a call
555                         // needs to have a compiler with a non-empty
556                         // environment.
557                         // this.reset();
558                 }
559         }
560   /**
561    * Internal API used to resolve a given compilation unit. Can run a subset of
562    * the compilation process
563    */
564   public CompilationUnitDeclaration resolve(ICompilationUnit sourceUnit,
565       boolean verifyMethods, boolean analyzeCode) {
566     //                  boolean generateCode) {
567     CompilationUnitDeclaration unit = null;
568     try {
569       // build and record parsed units
570       parseThreshold = 0; // will request a full parse
571       beginToCompile(new ICompilationUnit[]{sourceUnit});
572       // process all units (some more could be injected in the loop by the
573       // lookup environment)
574       unit = unitsToProcess[0];
575       getMethodBodies(unit, 0);
576       if (unit.scope != null) {
577         //                              // fault in fields & methods
578         //                              unit.scope.faultInTypes();
579         //                              if (unit.scope != null && verifyMethods) {
580         //                                      // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
581         //                                      // verify inherited methods
582         //                                      unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
583         //                              }
584         //                              // type checking
585         //                              unit.resolve();
586         // flow analysis
587         //                              if (analyzeCode) unit.analyseCode();
588         // code generation
589         //                              if (generateCode) unit.generateCode();
590       }
591       unitsToProcess[0] = null; // release reference to processed unit
592       // declaration
593       requestor.acceptResult(unit.compilationResult.tagAsAccepted());
594       return unit;
595     } catch (AbortCompilation e) {
596       this.handleInternalException(e, unit);
597       return unit == null ? unitsToProcess[0] : unit;
598     } catch (Error e) {
599       this.handleInternalException(e, unit, null);
600       throw e; // rethrow
601     } catch (RuntimeException e) {
602       this.handleInternalException(e, unit, null);
603       throw e; // rethrow
604     } finally {
605       // No reset is performed there anymore since,
606       // within the CodeAssist (or related tools),
607       // the compiler may be called *after* a call
608       // to this resolve(...) method. And such a call
609       // needs to have a compiler with a non-empty
610       // environment.
611       // this.reset();
612     }
613   }
614
615 }