Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/eclipse/jdt/core/dom/CompilationUnitResolver.java


1   /*******************************************************************************
2    * Copyright (c) 2000, 2004 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  
12  package org.eclipse.jdt.core.dom;
13  
14  import java.util.Map;
15  
16  import org.eclipse.core.runtime.IProgressMonitor;
17  import org.eclipse.core.runtime.OperationCanceledException;
18  import org.eclipse.jdt.core.IJavaProject;
19  //import org.eclipse.jdt.core.JavaCore;
20  import org.eclipse.jdt.core.JavaModelException;
21  import org.eclipse.jdt.core.WorkingCopyOwner;
22  import org.eclipse.jdt.core.compiler.IProblem;
23  import org.eclipse.jdt.internal.codeassist.ISearchRequestor;
24  import org.eclipse.jdt.internal.compiler.CompilationResult;
25  import org.eclipse.jdt.internal.compiler.Compiler;
26  import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
27  import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
28  import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
29  import org.eclipse.jdt.internal.compiler.IProblemFactory;
30  import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
31  import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
32  import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
33  import org.eclipse.jdt.internal.compiler.env.ISourceType;
34  import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
35  import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
36  import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
37  import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
38  import org.eclipse.jdt.internal.compiler.parser.Parser;
39  import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
40  import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
41  import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
42  import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
43  import org.eclipse.jdt.internal.core.BasicCompilationUnit;
44  import org.eclipse.jdt.internal.core.JavaProject;
45  import org.eclipse.jdt.internal.core.SearchableEnvironment;
46  import org.eclipse.jdt.internal.core.util.CommentRecorderParser;
47  
48  class CompilationUnitResolver extends Compiler {
49    
50    static class CancelableNameEnvironment extends SearchableEnvironment {
51      IProgressMonitor monitor;
52  
53      CancelableNameEnvironment(JavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
54        super(project, owner);
55        this.monitor = monitor;
56      }
57  
58      private void checkCanceled() {
59        if (monitor != null && monitor.isCanceled()) 
60          throw new AbortCompilation(true/*silent*/, new OperationCanceledException());
61      }
62  
63      public void findPackages(char[] prefix, ISearchRequestor requestor) {
64        checkCanceled();
65        super.findPackages(prefix, requestor);
66      }
67  
68      public NameEnvironmentAnswer findType(char[] name, char[][] packageName) {
69        checkCanceled();
70        return super.findType(name, packageName);
71      }
72  
73      public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
74        checkCanceled();
75        return super.findType(compoundTypeName);
76      }
77  
78      public void findTypes(char[] prefix, ISearchRequestor storage) {
79        checkCanceled();
80        super.findTypes(prefix, storage);
81      }
82    }
83  
84    static class CancelableProblemFactory extends DefaultProblemFactory {
85      IProgressMonitor monitor;
86  
87      CancelableProblemFactory(IProgressMonitor monitor) {
88        super();
89        this.monitor = monitor;
90      }
91  
92      public IProblem createProblem(char[] originatingFileName, int problemId, String[] problemArguments, String[] messageArguments, int severity, int startPosition, int endPosition, int lineNumber) {
93        if (monitor != null && monitor.isCanceled()) 
94          throw new AbortCompilation(true/*silent*/, new OperationCanceledException());
95        return super.createProblem(originatingFileName, problemId, problemArguments, messageArguments, severity, startPosition, endPosition, lineNumber);
96      }
97    }
98  
99    /**
100    * Answer a new CompilationUnitVisitor using the given name environment and compiler options.
101    * The environment and options will be in effect for the lifetime of the compiler.
102    * When the compiler is run, compilation results are sent to the given requestor.
103    *
104    *  @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
105    *      Environment used by the compiler in order to resolve type and package
106    *      names. The name environment implements the actual connection of the compiler
107    *      to the outside world (for example, in batch mode the name environment is performing
108    *      pure file accesses, reuse previous build state or connection to repositories).
109    *      Note: the name environment is responsible for implementing the actual classpath
110    *            rules.
111    *
112    *  @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
113    *      Configurable part for problem handling, allowing the compiler client to
114    *      specify the rules for handling problems (stop on first error or accumulate
115    *      them all) and at the same time perform some actions such as opening a dialog
116    *      in UI when compiling interactively.
117    *      @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
118    * 
119    *  @param settings The settings to use for the resolution.
120    *      
121    *  @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
122    *      Component which will receive and persist all compilation results and is intended
123    *      to consume them as they are produced. Typically, in a batch compiler, it is 
124    *      responsible for writing out the actual .class files to the file system.
125    *      @see org.eclipse.jdt.internal.compiler.CompilationResult
126    *
127    *  @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
128    *      Factory used inside the compiler to create problem descriptors. It allows the
129    *      compiler client to supply its own representation of compilation problems in
130    *      order to avoid object conversions. Note that the factory is not supposed
131    *      to accumulate the created problems, the compiler will gather them all and hand
132    *      them back as part of the compilation unit result.
133    */
134   public CompilationUnitResolver(
135     INameEnvironment environment,
136     IErrorHandlingPolicy policy,
137     Map settings,
138     ICompilerRequestor requestor,
139     IProblemFactory problemFactory) {
140 
141     super(environment, policy, settings, requestor, problemFactory, false);
142   }
143   
144   /*
145    * Add additional source types
146    */
147   public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
148     CompilationResult result =
149       new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.options.maxProblemsPerUnit);
150     // need to hold onto this
151     CompilationUnitDeclaration unit =
152       SourceTypeConverter.buildCompilationUnit(
153         sourceTypes,//sourceTypes[0] is always toplevel here
154         SourceTypeConverter.FIELD_AND_METHOD // need field and methods
155         | SourceTypeConverter.MEMBER_TYPE // need member types
156         | SourceTypeConverter.FIELD_INITIALIZATION, // need field initialization: see bug 40476
157         this.lookupEnvironment.problemReporter,
158         result);
159 
160     if (unit != null) {
161       this.lookupEnvironment.buildTypeBindings(unit);
162       this.lookupEnvironment.completeTypeBindings(unit, true);
163     }
164   }
165 
166   /*
167    *  Low-level API performing the actual compilation
168    */
169   protected static IErrorHandlingPolicy getHandlingPolicy() {
170 
171     // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)  
172     return new IErrorHandlingPolicy() {
173       public boolean stopOnFirstError() {
174         return false;
175       }
176       public boolean proceedOnErrors() {
177         return false; // stop if there are some errors 
178       }
179     };
180   }
181 
182   /*
183    * Answer the component to which will be handed back compilation results from the compiler
184    */
185   protected static ICompilerRequestor getRequestor() {
186     return new ICompilerRequestor() {
187       public void acceptResult(CompilationResult compilationResult) {
188         // do nothing
189       }
190     };
191   }
192 
193   /* (non-Javadoc)
194    * @see org.eclipse.jdt.internal.compiler.Compiler#initializeParser()
195    */
196   public void initializeParser() {
197     this.parser = new CommentRecorderParser(this.problemReporter, false);
198   }
199   /*
200    * Compiler crash recovery in case of unexpected runtime exceptions
201    */
202   protected void handleInternalException(
203       Throwable internalException,
204       CompilationUnitDeclaration unit,
205       CompilationResult result) {
206     super.handleInternalException(internalException, unit, result);
207     if (unit != null) {
208       removeUnresolvedBindings(unit);
209     }
210   }
211   
212   /*
213    * Compiler recovery in case of internal AbortCompilation event
214    */
215   protected void handleInternalException(
216       AbortCompilation abortException,
217       CompilationUnitDeclaration unit) {
218     super.handleInternalException(abortException, unit);
219     if (unit != null) {
220       removeUnresolvedBindings(unit);
221     }
222   }  
223   
224   public static CompilationUnitDeclaration parse(char[] source, NodeSearcher nodeSearcher, Map settings) {
225     if (source == null) {
226       throw new IllegalArgumentException();
227     }
228     CompilerOptions compilerOptions = new CompilerOptions(settings);
229     Parser parser = new CommentRecorderParser(
230       new ProblemReporter(
231           DefaultErrorHandlingPolicies.proceedWithAllProblems(), 
232           compilerOptions, 
233           new DefaultProblemFactory()),
234       false);
235     org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = 
236       new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(
237         source, 
238         "", //$NON-NLS-1$
239         compilerOptions.defaultEncoding);
240     CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit));
241     
242     if (compilationUnitDeclaration.ignoreMethodBodies) {
243       compilationUnitDeclaration.ignoreFurtherInvestigation = true;
244       // if initial diet parse did not work, no need to dig into method bodies.
245       return null; 
246     }
247     
248     if (nodeSearcher != null) {
249       int searchPosition = nodeSearcher.position;
250       if (searchPosition < 0 || searchPosition > source.length) {
251         // the position is out of range. There is no need to search for a node.
252          return compilationUnitDeclaration;
253       }
254     
255       compilationUnitDeclaration.traverse(nodeSearcher, compilationUnitDeclaration.scope);
256       
257       org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
258        if (node == null) {
259          return compilationUnitDeclaration;
260        }
261        
262        org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
263        
264       if (node instanceof AbstractMethodDeclaration) {
265         ((AbstractMethodDeclaration)node).parseStatements(parser, compilationUnitDeclaration);
266       } else if (enclosingTypeDeclaration != null) {
267         if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
268           ((org.eclipse.jdt.internal.compiler.ast.Initializer) node).parseStatements(parser, enclosingTypeDeclaration, compilationUnitDeclaration);
269         } else {            
270           ((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)node).parseMethod(parser, compilationUnitDeclaration);
271         }         
272       }
273     } else {
274       //fill the methods bodies in order for the code to be generated
275       //real parse of the method....
276       parser.scanner.setSource(source);
277       org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
278       if (types != null) {
279         for (int i = types.length; --i >= 0;)
280           types[i].parseMethod(parser, compilationUnitDeclaration);
281       }
282     }
283     return compilationUnitDeclaration;
284   }
285 
286   public static CompilationUnitDeclaration resolve(
287     char[] source,
288     char[][] packageName,
289     String unitName,
290     IJavaProject javaProject,
291     NodeSearcher nodeSearcher,
292     Map options,
293     boolean cleanUp,
294     WorkingCopyOwner owner,
295     IProgressMonitor monitor)
296     throws JavaModelException {
297   
298     CompilationUnitDeclaration unit = null;
299     CancelableNameEnvironment environment = null;
300     CancelableProblemFactory problemFactory = null;
301     try {
302       environment = new CancelableNameEnvironment(((JavaProject)javaProject), owner, monitor);
303       problemFactory = new CancelableProblemFactory(monitor);
304       CompilationUnitResolver resolver =
305         new CompilationUnitResolver(
306           environment,
307           getHandlingPolicy(),
308           options,
309           getRequestor(),
310           problemFactory);
311 
312       unit = 
313         resolver.resolve(
314           null, // no existing compilation unit declaration
315           new BasicCompilationUnit(
316             source,
317             packageName,
318             unitName,
319             javaProject),
320           nodeSearcher,
321           true, // method verification
322           true, // analyze code
323           true); // generate code          
324       return unit;
325     } finally {
326       if (environment != null) {
327         environment.monitor = null; // don't hold a reference to this external object
328       }
329       if (problemFactory != null) {
330         problemFactory.monitor = null; // don't hold a reference to this external object
331       }
332       if (cleanUp && unit != null) {
333         unit.cleanUp();
334       }
335     }
336   }
337   /*
338    * When unit result is about to be accepted, removed back pointers
339    * to unresolved bindings
340    */
341   public void removeUnresolvedBindings(CompilationUnitDeclaration compilationUnitDeclaration) {
342     final org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
343     if (types != null) {
344       for (int i = 0, max = types.length; i < max; i++) {
345         removeUnresolvedBindings(types[i]);
346       }
347     }
348   }
349   private void removeUnresolvedBindings(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration type) {
350     final org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] memberTypes = type.memberTypes;
351     if (memberTypes != null) {
352       for (int i = 0, max = memberTypes.length; i < max; i++){
353         removeUnresolvedBindings(memberTypes[i]);
354       }
355     }
356     if (type.binding != null && (type.binding.modifiers & CompilerModifiers.AccUnresolved) != 0) {
357       type.binding = null;
358     }
359     
360     final org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = type.fields;
361     if (fields != null) {
362       for (int i = 0, max = fields.length; i < max; i++){
363         if (fields[i].binding != null && (fields[i].binding.modifiers & CompilerModifiers.AccUnresolved) != 0) {
364           fields[i].binding = null;
365         }
366       }
367     }
368   
369     final AbstractMethodDeclaration[] methods = type.methods;
370     if (methods != null) {
371       for (int i = 0, max = methods.length; i < max; i++){
372         if (methods[i].binding !=  null && (methods[i].binding.modifiers & CompilerModifiers.AccUnresolved) != 0) {
373           methods[i].binding = null;
374         }
375       }
376     }
377   }
378 
379   private CompilationUnitDeclaration resolve(
380       CompilationUnitDeclaration unit,
381       org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
382       NodeSearcher nodeSearcher,
383       boolean verifyMethods,
384       boolean analyzeCode,
385       boolean generateCode) {
386 
387     try {
388 
389       if (unit == null) {
390         // build and record parsed units
391         this.parseThreshold = 0; // will request a full parse
392         beginToCompile(new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] { sourceUnit });
393         // process all units (some more could be injected in the loop by the lookup environment)
394         unit = this.unitsToProcess[0];
395       } else {
396         // initial type binding creation
397         this.lookupEnvironment.buildTypeBindings(unit);
398 
399         // binding resolution
400         this.lookupEnvironment.completeTypeBindings();
401       }
402 
403       if (nodeSearcher == null) {
404         this.parser.getMethodBodies(unit); // no-op if method bodies have already been parsed
405       } else {
406         int searchPosition = nodeSearcher.position;
407         if (searchPosition >= 0 && searchPosition <= sourceUnit.getContents().length) {
408           unit.traverse(nodeSearcher, unit.scope);
409           
410           org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
411           
412            if (node != null) {
413             org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
414               if (node instanceof AbstractMethodDeclaration) {
415               ((AbstractMethodDeclaration)node).parseStatements(this.parser, unit);
416              } else if (enclosingTypeDeclaration != null) {
417               if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
418                  ((org.eclipse.jdt.internal.compiler.ast.Initializer) node).parseStatements(this.parser, enclosingTypeDeclaration, unit);
419                } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {            
420                 ((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)node).parseMethod(this.parser, unit);
421               }         
422              }
423            }
424         }
425       }
426       
427       if (unit.scope != null) {
428         // fault in fields & methods
429         unit.scope.faultInTypes();
430         if (unit.scope != null && verifyMethods) {
431           // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
432            // verify inherited methods
433           unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier());
434         }
435         // type checking
436         unit.resolve();    
437 
438         // flow analysis
439         if (analyzeCode) unit.analyseCode();
440     
441         // code generation
442         if (generateCode) unit.generateCode();
443       }
444       if (this.unitsToProcess != null) this.unitsToProcess[0] = null; // release reference to processed unit declaration
445       this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
446       return unit;
447     } catch (AbortCompilation e) {
448       this.handleInternalException(e, unit);
449       return unit == null ? this.unitsToProcess[0] : unit;
450     } catch (Error e) {
451       this.handleInternalException(e, unit, null);
452       throw e; // rethrow
453     } catch (RuntimeException e) {
454       this.handleInternalException(e, unit, null);
455       throw e; // rethrow
456     } finally {
457       // No reset is performed there anymore since,
458       // within the CodeAssist (or related tools),
459       // the compiler may be called *after* a call
460       // to this resolve(...) method. And such a call
461       // needs to have a compiler with a non-empty
462       // environment.
463       // this.reset();
464     }
465   }
466   /*
467    * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
468    */
469   public CompilationUnitDeclaration resolve(
470       org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit, 
471       boolean verifyMethods,
472       boolean analyzeCode,
473       boolean generateCode) {
474         
475     return resolve(
476       null, /* no existing compilation unit declaration*/
477       sourceUnit,
478       null/*no node searcher*/, 
479       verifyMethods,
480       analyzeCode,
481       generateCode);
482   }
483 
484   /*
485    * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
486    */
487   public CompilationUnitDeclaration resolve(
488       CompilationUnitDeclaration unit, 
489       org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit, 
490       boolean verifyMethods,
491       boolean analyzeCode,
492       boolean generateCode) {
493     
494     return resolve(
495       unit, 
496       sourceUnit, 
497       null/*no node searcher*/, 
498       verifyMethods, 
499       analyzeCode, 
500       generateCode);
501   }
502 }