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