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