KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > Compiler


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler;
12
13 import org.eclipse.jdt.core.compiler.*;
14 import org.eclipse.jdt.internal.compiler.env.*;
15 import org.eclipse.jdt.internal.compiler.impl.*;
16 import org.eclipse.jdt.internal.compiler.ast.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
18 import org.eclipse.jdt.internal.compiler.parser.*;
19 import org.eclipse.jdt.internal.compiler.problem.*;
20 import org.eclipse.jdt.internal.compiler.util.*;
21
22 import java.io.*;
23 import java.util.*;
24
25 public class Compiler implements ITypeRequestor, ProblemSeverities {
26     public Parser parser;
27     public ICompilerRequestor requestor;
28     public CompilerOptions options;
29     public ProblemReporter problemReporter;
30     protected PrintWriter out; // output for messages that are not sent to problemReporter
31

32     // management of unit to be processed
33
//public CompilationUnitResult currentCompilationUnitResult;
34
public CompilationUnitDeclaration[] unitsToProcess;
35     public int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess
36

37     // name lookup
38
public LookupEnvironment lookupEnvironment;
39
40     // ONCE STABILIZED, THESE SHOULD RETURN TO A FINAL FIELD
41
public static boolean DEBUG = false;
42     public int parseThreshold = -1;
43     
44     public AbstractAnnotationProcessorManager annotationProcessorManager;
45     public ReferenceBinding[] referenceBindings;
46
47     // number of initial units parsed at once (-1: none)
48

49     /*
50      * Static requestor reserved to listening compilation results in debug mode,
51      * so as for example to monitor compiler activity independantly from a particular
52      * builder implementation. It is reset at the end of compilation, and should not
53      * persist any information after having been reset.
54      */

55     public static IDebugRequestor DebugRequestor = null;
56
57     /**
58      * Answer a new compiler using the given name environment and compiler options.
59      * The environment and options will be in effect for the lifetime of the compiler.
60      * When the compiler is run, compilation results are sent to the given requestor.
61      *
62      * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
63      * Environment used by the compiler in order to resolve type and package
64      * names. The name environment implements the actual connection of the compiler
65      * to the outside world (e.g. in batch mode the name environment is performing
66      * pure file accesses, reuse previous build state or connection to repositories).
67      * Note: the name environment is responsible for implementing the actual classpath
68      * rules.
69      *
70      * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
71      * Configurable part for problem handling, allowing the compiler client to
72      * specify the rules for handling problems (stop on first error or accumulate
73      * them all) and at the same time perform some actions such as opening a dialog
74      * in UI when compiling interactively.
75      * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
76      *
77      * @param settings java.util.Map
78      * The settings that control the compiler behavior.
79      *
80      * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
81      * Component which will receive and persist all compilation results and is intended
82      * to consume them as they are produced. Typically, in a batch compiler, it is
83      * responsible for writing out the actual .class files to the file system.
84      * @see org.eclipse.jdt.internal.compiler.CompilationResult
85      *
86      * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
87      * Factory used inside the compiler to create problem descriptors. It allows the
88      * compiler client to supply its own representation of compilation problems in
89      * order to avoid object conversions. Note that the factory is not supposed
90      * to accumulate the created problems, the compiler will gather them all and hand
91      * them back as part of the compilation unit result.
92      *
93      * @deprecated this constructor is kept to preserve 3.1 and 3.2M4 compatibility
94      */

95     public Compiler(
96         INameEnvironment environment,
97         IErrorHandlingPolicy policy,
98         Map settings,
99         final ICompilerRequestor requestor,
100         IProblemFactory problemFactory) {
101         this(environment, policy, new CompilerOptions(settings), requestor, problemFactory, null);
102     }
103     
104     /**
105      * Answer a new compiler using the given name environment and compiler options.
106      * The environment and options will be in effect for the lifetime of the compiler.
107      * When the compiler is run, compilation results are sent to the given requestor.
108      *
109      * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
110      * Environment used by the compiler in order to resolve type and package
111      * names. The name environment implements the actual connection of the compiler
112      * to the outside world (e.g. in batch mode the name environment is performing
113      * pure file accesses, reuse previous build state or connection to repositories).
114      * Note: the name environment is responsible for implementing the actual classpath
115      * rules.
116      *
117      * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
118      * Configurable part for problem handling, allowing the compiler client to
119      * specify the rules for handling problems (stop on first error or accumulate
120      * them all) and at the same time perform some actions such as opening a dialog
121      * in UI when compiling interactively.
122      * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
123      *
124      * @param settings java.util.Map
125      * The settings that control the compiler behavior.
126      *
127      * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
128      * Component which will receive and persist all compilation results and is intended
129      * to consume them as they are produced. Typically, in a batch compiler, it is
130      * responsible for writing out the actual .class files to the file system.
131      * @see org.eclipse.jdt.internal.compiler.CompilationResult
132      *
133      * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
134      * Factory used inside the compiler to create problem descriptors. It allows the
135      * compiler client to supply its own representation of compilation problems in
136      * order to avoid object conversions. Note that the factory is not supposed
137      * to accumulate the created problems, the compiler will gather them all and hand
138      * them back as part of the compilation unit result.
139      *
140      * @param parseLiteralExpressionsAsConstants <code>boolean</code>
141      * This parameter is used to optimize the literals or leave them as they are in the source.
142      * If you put true, "Hello" + " world" will be converted to "Hello world".
143      *
144      * @deprecated this constructor is kept to preserve 3.1 and 3.2M4 compatibility
145      */

146     public Compiler(
147         INameEnvironment environment,
148         IErrorHandlingPolicy policy,
149         Map settings,
150         final ICompilerRequestor requestor,
151         IProblemFactory problemFactory,
152         boolean parseLiteralExpressionsAsConstants) {
153         this(environment, policy, new CompilerOptions(settings, parseLiteralExpressionsAsConstants), requestor, problemFactory, null);
154     }
155     
156     /**
157      * Answer a new compiler using the given name environment and compiler options.
158      * The environment and options will be in effect for the lifetime of the compiler.
159      * When the compiler is run, compilation results are sent to the given requestor.
160      *
161      * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
162      * Environment used by the compiler in order to resolve type and package
163      * names. The name environment implements the actual connection of the compiler
164      * to the outside world (e.g. in batch mode the name environment is performing
165      * pure file accesses, reuse previous build state or connection to repositories).
166      * Note: the name environment is responsible for implementing the actual classpath
167      * rules.
168      *
169      * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
170      * Configurable part for problem handling, allowing the compiler client to
171      * specify the rules for handling problems (stop on first error or accumulate
172      * them all) and at the same time perform some actions such as opening a dialog
173      * in UI when compiling interactively.
174      * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
175      *
176      * @param options org.eclipse.jdt.internal.compiler.impl.CompilerOptions
177      * The options that control the compiler behavior.
178      *
179      * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
180      * Component which will receive and persist all compilation results and is intended
181      * to consume them as they are produced. Typically, in a batch compiler, it is
182      * responsible for writing out the actual .class files to the file system.
183      * @see org.eclipse.jdt.internal.compiler.CompilationResult
184      *
185      * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
186      * Factory used inside the compiler to create problem descriptors. It allows the
187      * compiler client to supply its own representation of compilation problems in
188      * order to avoid object conversions. Note that the factory is not supposed
189      * to accumulate the created problems, the compiler will gather them all and hand
190      * them back as part of the compilation unit result.
191      */

192     public Compiler(
193         INameEnvironment environment,
194         IErrorHandlingPolicy policy,
195         CompilerOptions options,
196         final ICompilerRequestor requestor,
197         IProblemFactory problemFactory) {
198         this(environment, policy, options, requestor, problemFactory, null);
199     }
200
201     /**
202      * Answer a new compiler using the given name environment and compiler options.
203      * The environment and options will be in effect for the lifetime of the compiler.
204      * When the compiler is run, compilation results are sent to the given requestor.
205      *
206      * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
207      * Environment used by the compiler in order to resolve type and package
208      * names. The name environment implements the actual connection of the compiler
209      * to the outside world (e.g. in batch mode the name environment is performing
210      * pure file accesses, reuse previous build state or connection to repositories).
211      * Note: the name environment is responsible for implementing the actual classpath
212      * rules.
213      *
214      * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
215      * Configurable part for problem handling, allowing the compiler client to
216      * specify the rules for handling problems (stop on first error or accumulate
217      * them all) and at the same time perform some actions such as opening a dialog
218      * in UI when compiling interactively.
219      * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
220      *
221      * @param options org.eclipse.jdt.internal.compiler.impl.CompilerOptions
222      * The options that control the compiler behavior.
223      *
224      * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
225      * Component which will receive and persist all compilation results and is intended
226      * to consume them as they are produced. Typically, in a batch compiler, it is
227      * responsible for writing out the actual .class files to the file system.
228      * @see org.eclipse.jdt.internal.compiler.CompilationResult
229      *
230      * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
231      * Factory used inside the compiler to create problem descriptors. It allows the
232      * compiler client to supply its own representation of compilation problems in
233      * order to avoid object conversions. Note that the factory is not supposed
234      * to accumulate the created problems, the compiler will gather them all and hand
235      * them back as part of the compilation unit result.
236      */

237     public Compiler(
238             INameEnvironment environment,
239             IErrorHandlingPolicy policy,
240             CompilerOptions options,
241             final ICompilerRequestor requestor,
242             IProblemFactory problemFactory,
243             PrintWriter out) {
244         
245         this.options = options;
246         
247         // wrap requestor in DebugRequestor if one is specified
248
if(DebugRequestor == null) {
249             this.requestor = requestor;
250         } else {
251             this.requestor = new ICompilerRequestor(){
252                 public void acceptResult(CompilationResult result){
253                     if (DebugRequestor.isActive()){
254                         DebugRequestor.acceptDebugResult(result);
255                     }
256                     requestor.acceptResult(result);
257                 }
258             };
259         }
260         this.problemReporter = new ProblemReporter(policy, this.options, problemFactory);
261         this.lookupEnvironment = new LookupEnvironment(this, this.options, problemReporter, environment);
262         this.out = out == null ? new PrintWriter(System.out, true) : out;
263         initializeParser();
264     }
265     
266     /**
267      * Add an additional binary type
268      */

269     public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
270         if (this.options.verbose) {
271             this.out.println(
272                 Messages.bind(Messages.compilation_loadBinary, new String JavaDoc(binaryType.getName())));
273 // new Exception("TRACE BINARY").printStackTrace(System.out);
274
// System.out.println();
275
}
276         lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
277     }
278
279     /**
280      * Add an additional compilation unit into the loop
281      * -> build compilation unit declarations, their bindings and record their results.
282      */

283     public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
284         // Switch the current policy and compilation result for this unit to the requested one.
285
CompilationResult unitResult =
286             new CompilationResult(sourceUnit, totalUnits, totalUnits, this.options.maxProblemsPerUnit);
287         try {
288             if (options.verbose) {
289                 String JavaDoc count = String.valueOf(totalUnits + 1);
290                 this.out.println(
291                     Messages.bind(Messages.compilation_request,
292                         new String JavaDoc[] {
293                             count,
294                             count,
295                             new String JavaDoc(sourceUnit.getFileName())
296                         }));
297             }
298             // diet parsing for large collection of unit
299
CompilationUnitDeclaration parsedUnit;
300             if (totalUnits < parseThreshold) {
301                 parsedUnit = parser.parse(sourceUnit, unitResult);
302             } else {
303                 parsedUnit = parser.dietParse(sourceUnit, unitResult);
304             }
305             parsedUnit.bits |= ASTNode.IsImplicitUnit;
306             // initial type binding creation
307
lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction);
308             this.addCompilationUnit(sourceUnit, parsedUnit);
309
310             // binding resolution
311
lookupEnvironment.completeTypeBindings(parsedUnit);
312         } catch (AbortCompilationUnit e) {
313             // at this point, currentCompilationUnitResult may not be sourceUnit, but some other
314
// one requested further along to resolve sourceUnit.
315
if (unitResult.compilationUnit == sourceUnit) { // only report once
316
requestor.acceptResult(unitResult.tagAsAccepted());
317             } else {
318                 throw e; // want to abort enclosing request to compile
319
}
320         }
321     }
322
323     /**
324      * Add additional source types
325      */

326     public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
327         problemReporter.abortDueToInternalError(
328             Messages.bind(Messages.abort_againstSourceModel, new String JavaDoc[] { String.valueOf(sourceTypes[0].getName()), String.valueOf(sourceTypes[0].getFileName()) }));
329     }
330
331     protected void addCompilationUnit(
332         ICompilationUnit sourceUnit,
333         CompilationUnitDeclaration parsedUnit) {
334
335         // append the unit to the list of ones to process later on
336
int size = unitsToProcess.length;
337         if (totalUnits == size)
338             // when growing reposition units starting at position 0
339
System.arraycopy(
340                 unitsToProcess,
341                 0,
342                 (unitsToProcess = new CompilationUnitDeclaration[size * 2]),
343                 0,
344                 totalUnits);
345         unitsToProcess[totalUnits++] = parsedUnit;
346     }
347
348     /**
349      * Add the initial set of compilation units into the loop
350      * -> build compilation unit declarations, their bindings and record their results.
351      */

352     protected void beginToCompile(ICompilationUnit[] sourceUnits) {
353         int maxUnits = sourceUnits.length;
354         this.totalUnits = 0;
355         this.unitsToProcess = new CompilationUnitDeclaration[maxUnits];
356
357         internalBeginToCompile(sourceUnits, maxUnits);
358     }
359
360     /**
361      * General API
362      * -> compile each of supplied files
363      * -> recompile any required types for which we have an incomplete principle structure
364      */

365     public void compile(ICompilationUnit[] sourceUnits) {
366         CompilationUnitDeclaration unit = null;
367         int i = 0;
368         try {
369             // build and record parsed units
370

371             beginToCompile(sourceUnits);
372
373             if (this.annotationProcessorManager != null) {
374                 processAnnotations();
375                 if (!options.generateClassFiles) {
376                     // -proc:only was set on the command line
377
return;
378                 }
379             }
380             // process all units (some more could be injected in the loop by the lookup environment)
381
for (; i < this.totalUnits; i++) {
382                 unit = unitsToProcess[i];
383                 try {
384                     if (options.verbose)
385                         this.out.println(
386                             Messages.bind(Messages.compilation_process,
387                             new String JavaDoc[] {
388                                 String.valueOf(i + 1),
389                                 String.valueOf(this.totalUnits),
390                                 new String JavaDoc(unitsToProcess[i].getFileName())
391                             }));
392                     process(unit, i);
393                 } finally {
394                     // cleanup compilation unit result
395
unit.cleanUp();
396                 }
397                 unitsToProcess[i] = null; // release reference to processed unit declaration
398
requestor.acceptResult(unit.compilationResult.tagAsAccepted());
399                 if (options.verbose)
400                     this.out.println(
401                         Messages.bind(Messages.compilation_done,
402                         new String JavaDoc[] {
403                             String.valueOf(i + 1),
404                             String.valueOf(this.totalUnits),
405                             new String JavaDoc(unit.getFileName())
406                         }));
407             }
408         } catch (AbortCompilation e) {
409             this.handleInternalException(e, unit);
410         } catch (Error JavaDoc e) {
411             this.handleInternalException(e, unit, null);
412             throw e; // rethrow
413
} catch (RuntimeException JavaDoc e) {
414             this.handleInternalException(e, unit, null);
415             throw e; // rethrow
416
} finally {
417             this.reset();
418         }
419         if (options.verbose) {
420             if (this.totalUnits > 1) {
421                 this.out.println(
422                     Messages.bind(Messages.compilation_units, String.valueOf(this.totalUnits)));
423             } else {
424                 this.out.println(
425                     Messages.bind(Messages.compilation_unit, String.valueOf(this.totalUnits)));
426             }
427         }
428     }
429     
430     public void setBinaryTypes(ReferenceBinding[] binaryTypes) {
431         this.referenceBindings = binaryTypes;
432     }
433     /*
434      * Compiler crash recovery in case of unexpected runtime exceptions
435      */

436     protected void handleInternalException(
437         Throwable JavaDoc internalException,
438         CompilationUnitDeclaration unit,
439         CompilationResult result) {
440
441         if ((result == null) && (unit != null)) {
442             result = unit.compilationResult; // current unit being processed ?
443
}
444         // Lookup environment may be in middle of connecting types
445
if ((result == null) && lookupEnvironment.unitBeingCompleted != null) {
446             result = lookupEnvironment.unitBeingCompleted.compilationResult;
447         }
448         // Lookup environment may be in middle of connecting types
449
if ((result == null) && lookupEnvironment.unitBeingCompleted != null) {
450             result = lookupEnvironment.unitBeingCompleted.compilationResult;
451         }
452         if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
453             result = unitsToProcess[totalUnits - 1].compilationResult;
454         // last unit in beginToCompile ?
455

456         boolean needToPrint = true;
457         if (result != null) {
458             /* create and record a compilation problem */
459             StringWriter stringWriter = new StringWriter();
460             PrintWriter writer = new PrintWriter(stringWriter);
461             internalException.printStackTrace(writer);
462             StringBuffer JavaDoc buffer = stringWriter.getBuffer();
463
464             String JavaDoc[] pbArguments = new String JavaDoc[] {
465                 Messages.compilation_internalError
466                     + "\n" //$NON-NLS-1$
467
+ buffer.toString()};
468
469             result
470                 .record(
471                     problemReporter
472                     .createProblem(
473                         result.getFileName(),
474                         IProblem.Unclassified,
475                         pbArguments,
476                         pbArguments,
477                         Error, // severity
478
0, // source start
479
0, // source end
480
0, // line number
481
0),// column number
482
unit);
483
484             /* hand back the compilation result */
485             if (!result.hasBeenAccepted) {
486                 requestor.acceptResult(result.tagAsAccepted());
487                 needToPrint = false;
488             }
489         }
490         if (needToPrint) {
491             /* dump a stack trace to the console */
492             internalException.printStackTrace();
493         }
494     }
495
496     /*
497      * Compiler recovery in case of internal AbortCompilation event
498      */

499     protected void handleInternalException(
500         AbortCompilation abortException,
501         CompilationUnitDeclaration unit) {
502
503         /* special treatment for SilentAbort: silently cancelling the compilation process */
504         if (abortException.isSilent) {
505             if (abortException.silentException == null) {
506                 return;
507             }
508             throw abortException.silentException;
509         }
510
511         /* uncomment following line to see where the abort came from */
512         // abortException.printStackTrace();
513

514         // Exception may tell which compilation result it is related, and which problem caused it
515
CompilationResult result = abortException.compilationResult;
516         if ((result == null) && (unit != null)) {
517             result = unit.compilationResult; // current unit being processed ?
518
}
519         // Lookup environment may be in middle of connecting types
520
if ((result == null) && lookupEnvironment.unitBeingCompleted != null) {
521             result = lookupEnvironment.unitBeingCompleted.compilationResult;
522         }
523         if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
524             result = unitsToProcess[totalUnits - 1].compilationResult;
525         // last unit in beginToCompile ?
526
if (result != null && !result.hasBeenAccepted) {
527             /* distant problem which could not be reported back there? */
528             if (abortException.problem != null) {
529                 recordDistantProblem: {
530                 CategorizedProblem distantProblem = abortException.problem;
531                 CategorizedProblem[] knownProblems = result.problems;
532                     for (int i = 0; i < result.problemCount; i++) {
533                         if (knownProblems[i] == distantProblem) { // already recorded
534
break recordDistantProblem;
535                         }
536                     }
537                     if (distantProblem instanceof DefaultProblem) { // fixup filename TODO (philippe) should improve API to make this official
538
((DefaultProblem) distantProblem).setOriginatingFileName(result.getFileName());
539                     }
540                     result.record(distantProblem, unit);
541                 }
542             } else {
543                 /* distant internal exception which could not be reported back there */
544                 if (abortException.exception != null) {
545                     this.handleInternalException(abortException.exception, null, result);
546                     return;
547                 }
548             }
549             /* hand back the compilation result */
550             if (!result.hasBeenAccepted) {
551                 requestor.acceptResult(result.tagAsAccepted());
552             }
553         } else {
554             abortException.printStackTrace();
555         }
556     }
557
558     public void initializeParser() {
559
560         this.parser = new Parser(this.problemReporter, this.options.parseLiteralExpressionsAsConstants);
561     }
562     
563     /**
564      * Add the initial set of compilation units into the loop
565      * -> build compilation unit declarations, their bindings and record their results.
566      */

567     protected void internalBeginToCompile(ICompilationUnit[] sourceUnits, int maxUnits) {
568         // Switch the current policy and compilation result for this unit to the requested one.
569
for (int i = 0; i < maxUnits; i++) {
570             CompilationUnitDeclaration parsedUnit;
571             CompilationResult unitResult =
572                 new CompilationResult(sourceUnits[i], i, maxUnits, this.options.maxProblemsPerUnit);
573             try {
574                 if (options.verbose) {
575                     this.out.println(
576                         Messages.bind(Messages.compilation_request,
577                         new String JavaDoc[] {
578                             String.valueOf(i + 1),
579                             String.valueOf(maxUnits),
580                             new String JavaDoc(sourceUnits[i].getFileName())
581                         }));
582                 }
583                 // diet parsing for large collection of units
584
if (totalUnits < parseThreshold) {
585                     parsedUnit = parser.parse(sourceUnits[i], unitResult);
586                 } else {
587                     parsedUnit = parser.dietParse(sourceUnits[i], unitResult);
588                 }
589                 // initial type binding creation
590
lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
591                 this.addCompilationUnit(sourceUnits[i], parsedUnit);
592                 ImportReference currentPackage = parsedUnit.currentPackage;
593                 if (currentPackage != null) {
594                     unitResult.recordPackageName(currentPackage.tokens);
595                 }
596                 //} catch (AbortCompilationUnit e) {
597
// requestor.acceptResult(unitResult.tagAsAccepted());
598
} finally {
599                 sourceUnits[i] = null; // no longer hold onto the unit
600
}
601         }
602         // binding resolution
603
lookupEnvironment.completeTypeBindings();
604     }
605
606     /**
607      * Process a compilation unit already parsed and build.
608      */

609     public void process(CompilationUnitDeclaration unit, int i) {
610         this.lookupEnvironment.unitBeingCompleted = unit;
611
612         this.parser.getMethodBodies(unit);
613
614         // fault in fields & methods
615
if (unit.scope != null)
616             unit.scope.faultInTypes();
617
618         // verify inherited methods
619
if (unit.scope != null)
620             unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
621
622         // type checking
623
unit.resolve();
624
625         // flow analysis
626
unit.analyseCode();
627
628         // code generation
629
unit.generateCode();
630
631         // reference info
632
if (options.produceReferenceInfo && unit.scope != null)
633             unit.scope.storeDependencyInfo();
634
635         // refresh the total number of units known at this stage
636
unit.compilationResult.totalUnitsKnown = totalUnits;
637
638         this.lookupEnvironment.unitBeingCompleted = null;
639     }
640
641     protected void processAnnotations() {
642         int newUnitSize = 0;
643         int newClassFilesSize = 0;
644         int bottom = 0;
645         int top = this.unitsToProcess.length;
646         ReferenceBinding[] binaryTypeBindingsTemp = this.referenceBindings;
647         if (top == 0 && binaryTypeBindingsTemp == null) return;
648         this.referenceBindings = null;
649         do {
650             // extract units to process
651
int length = top - bottom;
652             CompilationUnitDeclaration[] currentUnits = new CompilationUnitDeclaration[length];
653             int index = 0;
654             for (int i = bottom; i < top; i++) {
655                 CompilationUnitDeclaration currentUnit = this.unitsToProcess[i];
656                 if ((currentUnit.bits & ASTNode.IsImplicitUnit) == 0) {
657                     currentUnits[index++] = currentUnit;
658                 }
659             }
660             if (index != length) {
661                 System.arraycopy(currentUnits, 0, (currentUnits = new CompilationUnitDeclaration[index]), 0, index);
662             }
663             this.annotationProcessorManager.processAnnotations(currentUnits, binaryTypeBindingsTemp, false);
664             ICompilationUnit[] newUnits = this.annotationProcessorManager.getNewUnits();
665             newUnitSize = newUnits.length;
666             ReferenceBinding[] newClassFiles = this.annotationProcessorManager.getNewClassFiles();
667             binaryTypeBindingsTemp = newClassFiles;
668             newClassFilesSize = newClassFiles.length;
669             if (newUnitSize != 0) {
670                 // we reset the compiler in order to restart with the new units
671
internalBeginToCompile(newUnits, newUnitSize);
672                 bottom = top;
673                 top = this.totalUnits; // last unit added
674
} else {
675                 bottom = top;
676             }
677             this.annotationProcessorManager.reset();
678         } while (newUnitSize != 0 || newClassFilesSize != 0);
679         // one more loop to create possible resources
680
// this loop cannot create any java source files
681
// TODO (olivier) we should check if we should pass any unit at all for the last round
682
this.annotationProcessorManager.processAnnotations(null, null, true);
683         // TODO we might want to check if this loop created new units
684
}
685
686     public void reset() {
687         lookupEnvironment.reset();
688         parser.scanner.source = null;
689         unitsToProcess = null;
690         if (DebugRequestor != null) DebugRequestor.reset();
691         this.problemReporter.reset();
692     }
693
694     /**
695      * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
696      */

697     public CompilationUnitDeclaration resolve(
698             CompilationUnitDeclaration unit,
699             ICompilationUnit sourceUnit,
700             boolean verifyMethods,
701             boolean analyzeCode,
702             boolean generateCode) {
703                 
704         try {
705             if (unit == null) {
706                 // build and record parsed units
707
parseThreshold = 0; // will request a full parse
708
beginToCompile(new ICompilationUnit[] { sourceUnit });
709                 // process all units (some more could be injected in the loop by the lookup environment)
710
unit = unitsToProcess[0];
711             } else {
712                 // initial type binding creation
713
lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);
714
715                 // binding resolution
716
lookupEnvironment.completeTypeBindings();
717             }
718             this.lookupEnvironment.unitBeingCompleted = unit;
719             this.parser.getMethodBodies(unit);
720             if (unit.scope != null) {
721                 // fault in fields & methods
722
unit.scope.faultInTypes();
723                 if (unit.scope != null && verifyMethods) {
724                     // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
725
// verify inherited methods
726
unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
727                 }
728                 // type checking
729
unit.resolve();
730
731                 // flow analysis
732
if (analyzeCode) unit.analyseCode();
733         
734                 // code generation
735
if (generateCode) unit.generateCode();
736             }
737             if (unitsToProcess != null) unitsToProcess[0] = null; // release reference to processed unit declaration
738
requestor.acceptResult(unit.compilationResult.tagAsAccepted());
739             return unit;
740         } catch (AbortCompilation e) {
741             this.handleInternalException(e, unit);
742             return unit == null ? unitsToProcess[0] : unit;
743         } catch (Error JavaDoc e) {
744             this.handleInternalException(e, unit, null);
745             throw e; // rethrow
746
} catch (RuntimeException JavaDoc e) {
747             this.handleInternalException(e, unit, null);
748             throw e; // rethrow
749
} finally {
750             // leave this.lookupEnvironment.unitBeingCompleted set to the unit, until another unit is resolved
751
// other calls to dom can cause classpath errors to be detected, resulting in AbortCompilation exceptions
752

753             // No reset is performed there anymore since,
754
// within the CodeAssist (or related tools),
755
// the compiler may be called *after* a call
756
// to this resolve(...) method. And such a call
757
// needs to have a compiler with a non-empty
758
// environment.
759
// this.reset();
760
}
761     }
762     /**
763      * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
764      */

765     public CompilationUnitDeclaration resolve(
766             ICompilationUnit sourceUnit,
767             boolean verifyMethods,
768             boolean analyzeCode,
769             boolean generateCode) {
770                 
771         return resolve(
772             null,
773             sourceUnit,
774             verifyMethods,
775             analyzeCode,
776             generateCode);
777     }
778 }
779
Popular Tags