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