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/ASTParser.java


1   /*******************************************************************************
2    * Copyright (c) 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  package org.eclipse.jdt.core.dom;
12  
13  import java.util.Map;
14  
15  import org.eclipse.core.runtime.IProgressMonitor;
16  import org.eclipse.jdt.core.IClassFile;
17  import org.eclipse.jdt.core.ICompilationUnit;
18  import org.eclipse.jdt.core.IJavaElement;
19  import org.eclipse.jdt.core.IJavaProject;
20  import org.eclipse.jdt.core.IPackageFragment;
21  import org.eclipse.jdt.core.JavaCore;
22  import org.eclipse.jdt.core.JavaModelException;
23  import org.eclipse.jdt.core.WorkingCopyOwner;
24  import org.eclipse.jdt.core.compiler.CharOperation;
25  import org.eclipse.jdt.core.compiler.IProblem;
26  import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
27  import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
28  import org.eclipse.jdt.internal.compiler.ast.Statement;
29  import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
30  import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
31  import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil;
32  import org.eclipse.jdt.internal.core.util.RecordedParsingInformation;
33  
34  /**
35   * A Java language parser for creating abstract syntax trees (ASTs).
36   * <p>
37   * Example: Create basic AST from source string
38   * <pre>
39   * char[] source = ...;
40   * ASTParser parser = ASTParser.newParser(AST.JLS2);  // handles JLS2 (J2SE 1.4)
41   * parser.setSource(source);
42   * CompilationUnit result = (CompilationUnit) parser.createAST(null);
43   * </pre>
44   * Once a configured parser instance has been used to create an AST,
45   * the settings are automicatically returned to their defaults,
46   * ready for the parser instance to be reused.
47   * </p>
48   * <p>
49   * There are a number of configurable features:
50   * <ul>
51   * <li>Source string from {@link #setSource(char[]) char[]},
52   * {@link #setSource(ICompilationUnit) ICompilationUnit},
53   * or {@link #setSource(IClassFile) IClassFile}, and limited
54   * to a specified {@linkplain #setSourceRange(int,int) subrange}.</li>
55   * <li>Whether {@linkplain #setResolveBindings(boolean) bindings} will be created.</li>
56   * <li>Which {@linkplain #setWorkingCopyOwner(WorkingCopyOwner)
57   * working set owner} to use when resolving bindings).</li>
58   * <li>A hypothetical {@linkplain #setUnitName(String) compilation unit file name}
59   * and {@linkplain #setProject(IJavaProject) Java project}
60   * for locating a raw source string in the Java model (when
61   * resolving bindings)</li>
62   * <li>Which {@linkplain #setCompilerOptions(Map) compiler options}
63   * to use.</li>
64   * <li>Whether to parse just {@linkplain #setKind(int) an expression, statements,
65   * or body declarations} rather than an entire compilation unit.</li>
66   * <li>Whether to return a {@linkplain #setFocalPosition(int) abridged AST}
67   * focused on the declaration containing a given source position.</li>
68   * </ul>
69   * </p>
70   * 
71   * @since 3.0
72   */
73  public class ASTParser {
74  
75    /**
76     * Kind constant used to request that the source be parsed
77       * as a single expression.
78     */
79    public static final int K_EXPRESSION = 0x01;
80  
81    /**
82     * Kind constant used to request that the source be parsed
83       * as a sequence of statements.
84     */
85    public static final int K_STATEMENTS = 0x02;
86    
87    /**
88     * Kind constant used to request that the source be parsed
89     * as a sequence of class body declarations.
90     */
91    public static final int K_CLASS_BODY_DECLARATIONS = 0x04;
92    
93    /**
94     * Kind constant used to request that the source be parsed
95     * as a compilation unit.
96     */
97    public static final int K_COMPILATION_UNIT = 0x08;
98    
99    /**
100    * Creates a new object for creating a Java abstract syntax tree
101      * (AST) following the specified set of API rules.
102      * <p>
103      * <b>NOTE:</b>In Eclipse 3.0, there is no parser support for
104      * AST.JLS3. This support is planned for the follow-on release of
105      * Eclipse which includes support for J2SE 1.5.
106      * </p>
107      *  
108     * @param level the API level; one of the LEVEL constants
109      * declared on <code>AST</code>
110    * @return new ASTParser instance
111    */
112   public static ASTParser newParser(int level) {
113     return new ASTParser(level);
114   }
115 
116   /**
117    * Level of AST API desired.
118    */
119   private final int apiLevel;
120 
121   /**
122    * Kind of parse requested. Defaults to an entire compilation unit.
123    */
124   private int astKind;
125   
126   /**
127    * Compiler options. Defaults to JavaCore.getOptions().
128    */
129   private Map compilerOptions;
130   
131   /**
132    * Request for bindings. Defaults to <code>false</code>.
133      */
134   private boolean resolveBindings;
135 
136   /**
137    * Request for a partial AST. Defaults to <code>false</code>.
138      */
139   private boolean partial = false;
140 
141   /**
142    * The focal point for a partial AST request.
143      * Only used when <code>partial</code> is <code>true</code>.
144      */
145   private int focalPointPosition;
146 
147     /**
148      * Source string. 
149      */
150     private char[] rawSource = null;
151     
152     /**
153      * Java mode compilation unit supplying the source.
154      */
155     private ICompilationUnit compilationUnitSource = null;
156     
157     /**
158      * Java model class file supplying the source.
159      */
160     private IClassFile classFileSource = null;
161     
162     /**
163      * Character-based offset into the source string where parsing is to
164      * begin. Defaults to 0.
165      */
166   private int sourceOffset = 0;
167   
168     /**
169      * Character-based length limit, or -1 if unlimited.
170      * All characters in the source string between <code>offset</code>
171      * and <code>offset+length-1</code> inclusive are parsed. Defaults to -1, 
172      * which means the rest of the source string.
173      */
174   private int sourceLength = -1;
175 
176     /**
177      * Working copy owner. Defaults to primary owner.
178      */
179   private WorkingCopyOwner workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
180   
181     /**
182    * Java project used to resolve names, or <code>null</code> if none.
183      * Defaults to none.
184      */
185   private IJavaProject project = null;
186   
187     /**
188    * Name of the compilation unit for resolving bindings, or 
189    * <code>null</code> if none. Defaults to none.
190      */
191   private String unitName = null; 
192 
193    /**
194    * Creates a new AST parser for the given API level.
195    * <p>
196    * N.B. This constructor is package-private.
197    * </p>
198    * 
199    * @param level the API level; one of the LEVEL constants
200      * declared on <code>AST</code>
201    */
202   ASTParser(int level) {
203     if ((level != AST.JLS2)
204       && (level != AST.JLS3)) {
205       throw new IllegalArgumentException();
206     }
207     this.apiLevel = level;
208        initializeDefaults();
209   }
210 
211   /**
212    * Sets all the setting to their default values.
213    */
214   private void initializeDefaults() {
215      this.astKind = K_COMPILATION_UNIT;
216      this.rawSource = null;
217      this.classFileSource = null;
218      this.compilationUnitSource = null;
219      this.resolveBindings = false;
220      this.sourceLength = -1;
221      this.sourceOffset = 0;
222      this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
223      this.unitName = null;
224      this.project = null;
225      this.partial = false;
226      this.compilerOptions = JavaCore.getOptions();
227   }
228      
229   /**
230    * Sets the compiler options to be used when parsing.
231      * <p>
232      * The compiler options default to {@link JavaCore#getOptions()}.
233      * </p>
234    * 
235    * @param options the table of options (key type: <code>String</code>;
236    * value type: <code>String</code>), or <code>null</code>
237      * to set it back to the default
238    */
239   public void setCompilerOptions(Map options) {
240      if (options == null) {
241         this.compilerOptions = JavaCore.getOptions();
242      }
243      this.compilerOptions = options;
244   }
245   
246   /**
247    * Requests that the compiler should provide binding information for
248      * the AST nodes it creates.
249      * <p>
250      * Default to <code>false</code> (no bindings).
251      * </p>
252    * <p>
253    * If <code>setResolveBindings(true)</code>, the various names
254    * and types appearing in the AST can be resolved to "bindings"
255    * by calling the <code>resolveBinding</code> methods. These bindings 
256    * draw connections between the different parts of a program, and 
257    * generally afford a more powerful vantage point for clients who wish to
258    * analyze a program's structure more deeply. These bindings come at a 
259    * considerable cost in both time and space, however, and should not be
260    * requested frivolously. The additional space is not reclaimed until the 
261    * AST, all its nodes, and all its bindings become garbage. So it is very
262    * important to not retain any of these objects longer than absolutely
263    * necessary. Bindings are resolved at the time the AST is created. Subsequent
264    * modifications to the AST do not affect the bindings returned by
265    * <code>resolveBinding</code> methods in any way; these methods return the
266    * same binding as before the AST was modified (including modifications
267    * that rearrange subtrees by reparenting nodes).
268    * If <code>setResolveBindings(false)</code> (the default), the analysis 
269    * does not go beyond parsing and building the tree, and all 
270    * <code>resolveBinding</code> methods return <code>null</code> from the 
271    * outset.
272    * </p>
273    * <p>
274    * When bindings are requested, instead of considering compilation units on disk only
275    * one can supply a <code>WorkingCopyOwner</code>. Working copies owned 
276    * by this owner take precedence over the underlying compilation units when looking
277    * up names and drawing the connections.
278    * </p>
279    * <p>
280      * Binding information is obtained from the Java model.
281      * This means that the compilation unit must be located relative to the
282      * Java model. This happens automatically when the source code comes from
283      * either {@link #setSource(ICompilationUnit) setSource(ICompilationUnit)}
284      * or {@link #setSource(IClassFile) setSource(IClassFile)}.
285      * When source is supplied by {@link #setSource(char[]) setSource(char[])},
286      * the location must be extablished explicitly by calling 
287      * {@link #setProject(IJavaProject)} and  {@link #setUnitName(String)}.
288    * Note that the compiler options that affect doc comment checking may also
289    * affect whether any bindings are resolved for nodes within doc comments.
290    * </p>
291    * 
292    * @param bindings <code>true</code> if bindings are wanted, 
293    *   and <code>false</code> if bindings are not of interest
294    */
295   public void setResolveBindings(boolean bindings) {
296     this.resolveBindings = bindings;
297   }
298   
299   /**
300      * Requests an abridged abstract syntax tree. 
301      * By default, complete ASTs are returned.
302      *
303      * When <code>true</code> the resulting AST does not have nodes for
304      * the entire compilation unit. Rather, the AST is only fleshed out
305      * for the node that include the given source position. This kind of limited
306      * AST is sufficient for certain purposes but totally unsuitable for others.
307      * In places where it can be used, the limited AST offers the advantage of
308      * being smaller and faster to construct.
309    * </p>
310    * <p>
311    * The AST will include nodes for all of the compilation unit's
312    * package, import, and top-level type declarations. It will also always contain
313    * nodes for all the body declarations for those top-level types, as well
314    * as body declarations for any member types. However, some of the body
315    * declarations may be abridged. In particular, the statements ordinarily
316    * found in the body of a method declaration node will not be included
317    * (the block will be empty) unless the source position falls somewhere
318    * within the source range of that method declaration node. The same is true
319    * for initializer declarations; the statements ordinarily found in the body
320    * of initializer node will not be included unless the source position falls
321    * somewhere within the source range of that initializer declaration node.
322    * Field declarations are never abridged. Note that the AST for the body of
323    * that one unabridged method (or initializer) is 100% complete; it has all
324    * its statements, including any local or anonymous type declarations 
325    * embedded within them. When the the given position is not located within
326    * the source range of any body declaration of a top-level type, the AST
327    * returned will be a skeleton that includes nodes for all and only the major
328    * declarations; this kind of AST is still quite useful because it contains
329    * all the constructs that introduce names visible to the world outside the
330    * compilation unit.
331    * </p>
332    * 
333    * @param position a position into the corresponding body declaration
334    */
335   public void setFocalPosition(int position) {
336     this.partial = true;
337     this.focalPointPosition = position;
338   }
339   
340   /**
341    * Sets the kind of constructs to be parsed from the source.
342      * Defaults to an entire compilation unit.
343    * <p>
344    * When the parse is successful the result returned includes the ASTs for the
345    * requested source:
346    * <ul>
347    * <li>{@link #K_COMPILATION_UNIT}: The result node
348    * is a {@link CompilationUnit}.</li>
349    * <li>{@link #K_CLASS_BODY_DECLARATIONS}: The result node
350    * is a {@link TypeDeclaration} whose
351    * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
352    * are the new trees. Other aspects of the type declaration are unspecified.</li>
353    * <li>{@link #K_STATEMENTS}: The result node is a
354    * {@link Block Block} whose {@link Block#statements() statements}
355    * are the new trees. Other aspects of the block are unspecified.</li>
356    * <li>{@link #K_EXPRESSION}: The result node is a subclass of
357    * {@link Expression Expression}. Other aspects of the expression are unspecified.</li>
358    * </ul>
359    * The resulting AST node is rooted under (possibly contrived)
360    * {@link CompilationUnit CompilationUnit} node, to allow the
361    * client to retrieve the following pieces of information 
362    * available there:
363    * <ul>
364    * <li>{@linkplain CompilationUnit#lineNumber(int) Line number map}. Line
365    * numbers start at 1 and only cover the subrange scanned
366    * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
367    * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
368    * and {@linkplain CompilationUnit#getProblems() detailed problem reports}.
369    * Character positions are relative to the start of 
370    * <code>source</code>; line positions are for the subrange scanned.</li>
371    * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
372    * for the subrange scanned.</li>
373    * </ul>
374    * The contrived nodes do not have source positions. Other aspects of the
375    * {@link CompilationUnit CompilationUnit} node are unspecified, including
376    * the exact arrangment of intervening nodes.
377    * </p>
378    * <p>
379    * Lexical or syntax errors detected while parsing can result in
380    * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
381    * In more severe failure cases where the parser is unable to
382    * recognize the input, this method returns 
383    * a {@link CompilationUnit CompilationUnit} node with at least the
384    * compiler messages.
385    * </p>
386    * <p>Each node in the subtree (other than the contrived nodes) 
387    * carries source range(s) information relating back
388    * to positions in the given source (the given source itself
389    * is not remembered with the AST). 
390    * The source range usually begins at the first character of the first token 
391    * corresponding to the node; leading whitespace and comments are <b>not</b>
392    * included. The source range usually extends through the last character of
393    * the last token corresponding to the node; trailing whitespace and
394    * comments are <b>not</b> included. There are a handful of exceptions
395    * (including the various body declarations); the
396    * specification for these node type spells out the details.
397    * Source ranges nest properly: the source range for a child is always
398    * within the source range of its parent, and the source ranges of sibling
399    * nodes never overlap.
400    * </p>
401    * <p>
402    * Binding information is only computed when <code>kind</code> is 
403      * <code>K_COMPILATION_UNIT</code>.
404    * </p>
405    *  
406    * @param kind the kind of construct to parse: one of 
407    * {@link #K_COMPILATION_UNIT},
408    * {@link #K_CLASS_BODY_DECLARATIONS},
409    * {@link #K_EXPRESSION},
410    * {@link #K_STATEMENTS}
411    */
412   public void setKind(int kind) {
413       if ((kind != K_COMPILATION_UNIT)
414         && (kind != K_CLASS_BODY_DECLARATIONS)
415         && (kind != K_EXPRESSION)
416         && (kind != K_STATEMENTS)) {
417         throw new IllegalArgumentException();
418       }
419     this.astKind = kind;
420   }
421   
422   /**
423      * Sets the source code to be parsed.
424      *
425    * @param source the source string to be parsed,
426      * or <code>null</code> if none
427      */
428   public void setSource(char[] source) {
429     this.rawSource = source;
430     // clear the others
431     this.compilationUnitSource = null;
432     this.classFileSource = null;
433   }
434 
435   /**
436      * Sets the source code to be parsed.
437      * This method automatically sets the project (and compiler
438      * options) based on the given compilation unit, in a manner
439      * equivalent to <code>setProject(source.getJavaProject())</code>
440      *
441    * @param source the Java model compilation unit whose source code
442      * is to be parsed, or <code>null</code> if none
443       */
444   public void setSource(ICompilationUnit source) {
445     this.compilationUnitSource = source;
446     // clear the others
447     this.rawSource = null;
448     this.classFileSource = null;
449     if (source != null) {
450       this.project = source.getJavaProject();
451       this.compilerOptions = this.project.getOptions(true);
452     }
453   }
454   
455   /**
456      * Sets the source code to be parsed.
457      * This method automatically sets the project (and compiler
458      * options) based on the given compilation unit, in a manner
459      * equivalent to <code>setProject(source.getJavaProject())</code>
460      *
461    * @param source the Java model class file whose corresponding source code
462      * is to be parsed, or <code>null</code> if none
463      */
464   public void setSource(IClassFile source) {
465     this.classFileSource = source;
466     // clear the others
467     this.rawSource = null;
468     this.compilationUnitSource = null;
469     if (source != null) {
470       this.project = source.getJavaProject();
471       this.compilerOptions = this.project.getOptions(true);
472     }
473   }
474   
475   /**
476      * Sets the subrange of the source code to be parsed.
477      * By default, the entire source string will be parsed
478      * (<code>offset</code> 0 and <code>length</code> -1).
479      *
480      * @param offset the index of the first character to parse
481      * @param length the number of characters to parse, or -1 if
482      * the remainder of the source string is 
483      */
484   public void setSourceRange(int offset, int length) {
485     if (offset < 0 || length < -1) {
486       throw new IllegalArgumentException();
487     }
488     this.sourceOffset = offset;
489     this.sourceLength = length;
490   }
491   
492     /**
493      * Sets the working copy owner using when resolving bindings, where
494      * <code>null</code> means the primary owner. Defaults to the primary owner.
495      *
496    * @param owner the owner of working copies that take precedence over underlying 
497    *   compilation units, or <code>null</code> if the primary owner should be used
498      */
499   public void setWorkingCopyOwner(WorkingCopyOwner owner) {
500       if (owner == null) {
501       this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
502     } else {
503       this.workingCopyOwner = owner;
504      }
505   }
506 
507   /**
508      * Sets the name of the compilation unit that would hypothetically contains
509      * the source string. This is used in conjunction with
510      * <code>setSource(char[])</code> and <code>setProject</code> to locate the
511      * compilation unit relative to a Java project.
512      * Defaults to none (<code>null</code>).
513    * <p>
514    * The name of the compilation unit must be supplied for resolving bindings.
515    * This name should include the ".java" suffix and match the name of the main
516    * (public) class or interface declared in the source. For example, if the source
517    * declares a public class named "Foo", the name of the compilation should be
518    * "Foo.java".
519    * </p>
520      *
521    * @param unitName the name of the compilation unit that would contain the source
522    *    string, or <code>null</code> if none
523      */
524   public void setUnitName(String unitName) {
525     this.unitName = unitName;
526   }
527   
528   /**
529      * Sets the Java project used when resolving bindings.
530      * This method automatically sets the compiler
531      * options based on the given project:
532      * <pre>
533      * setCompilerOptions(project.getOptions(true));
534      * </pre>
535      * This setting is used in conjunction with <code>setSource(char[])</code>.
536      * For the purposes of resolving bindings, types declared in the
537    * source string will hide types by the same name available
538      * through the classpath of the given project.
539      * Defaults to none (<code>null</code>).
540      * 
541    * @param project the Java project used to resolve names, or 
542    *    <code>null</code> if none
543      */
544   public void setProject(IJavaProject project) {
545     this.project = project;
546     if (project != null) {
547       this.compilerOptions = project.getOptions(true);
548     }
549   }
550   
551   /**
552      * Creates an abstract syntax tree.
553      * <p>
554      * A successful call to this method returns all settings to their
555      * default values so the object is ready to be reused.
556      * </p>
557      * 
558    * @param monitor the progress monitor used to report progress and request cancelation,
559    *   or <code>null</code> if none
560    * @return an AST node whose type depends on the kind of parse
561    *  requested, with a fallback to a <code>CompilationUnit</code>
562    *  in the case of severe parsing errors
563    * @exception IllegalStateException if the settings provided
564    * are insufficient, contradictory, or otherwise unsupported
565      */
566   public ASTNode createAST(IProgressMonitor monitor) {
567      ASTNode result = null;
568     try {
569       if ((this.rawSource == null)
570            && (this.compilationUnitSource == null)
571            && (this.classFileSource == null)) {
572            throw new IllegalStateException("source not specified"); //$NON-NLS-1$
573        }
574          result = internalCreateAST(monitor);
575     } finally {
576           // re-init defaults to allow reuse (and avoid leaking)
577           initializeDefaults();
578     }
579         return result;
580   }
581   
582   private ASTNode internalCreateAST(IProgressMonitor monitor) {
583     boolean needToResolveBindings = this.resolveBindings;
584     switch(this.astKind) {
585       case K_CLASS_BODY_DECLARATIONS :
586       case K_EXPRESSION :
587       case K_STATEMENTS :
588         if (this.rawSource != null) {
589           if (this.sourceOffset + this.sourceLength > this.rawSource.length) {
590               throw new IllegalStateException();
591           }
592           return internalCreateASTForKind();
593         }
594         break;
595       case K_COMPILATION_UNIT :
596         CompilationUnitDeclaration compilationUnitDeclaration = null;
597         try {
598           char[] source = null;
599           NodeSearcher searcher = null;
600           char[][] packageName = null;
601           String fileName = null;
602           if (this.compilationUnitSource != null) {
603             try {
604               source = this.compilationUnitSource.getSource().toCharArray();
605             } catch(JavaModelException e) {
606               // no source, then we cannot build anything
607               throw new IllegalStateException();
608             }
609             IPackageFragment packageFragment = (IPackageFragment)this.compilationUnitSource.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
610             if (packageFragment != null){
611               packageName = CharOperation.splitOn('.', packageFragment.getElementName().toCharArray());
612             }
613             fileName = this.compilationUnitSource.getElementName();
614           } else if (this.classFileSource != null) {
615             String sourceString = null;
616             try {
617               sourceString = this.classFileSource.getSource();
618             } catch (JavaModelException e) {
619               // nothing to do
620             }
621           
622             if (sourceString == null) {
623               throw new IllegalStateException();
624             }
625             source = sourceString.toCharArray();
626             try {
627               packageName = CharOperation.splitOn('.', this.classFileSource.getType().getPackageFragment().getElementName().toCharArray());
628               StringBuffer buffer = new StringBuffer(SuffixConstants.SUFFIX_STRING_java);
629               String classFileName = this.classFileSource.getElementName(); // this includes the trailing .class
630               buffer.insert(0, classFileName.toCharArray(), 0, classFileName.indexOf('.'));
631               fileName = String.valueOf(buffer);
632             } catch(JavaModelException e) {
633               needToResolveBindings = false;
634             }
635           } else if (this.rawSource != null) {
636             source = this.rawSource;
637             if (this.unitName == null || this.project == null || this.compilerOptions == null) {
638               needToResolveBindings = false;
639             } else {
640               fileName = this.unitName;
641               needToResolveBindings = true;
642             }
643           }
644           if (source == null) {
645             throw new IllegalStateException();
646           }
647           if (this.sourceLength == -1) {
648             this.sourceLength = source.length;
649           }
650           if (this.partial) {
651             searcher = new NodeSearcher(this.focalPointPosition);
652           }
653           if (needToResolveBindings && this.project != null) {
654             try {
655               // parse and resolve
656               compilationUnitDeclaration = 
657                 CompilationUnitResolver.resolve(
658                   source,
659                   packageName,
660                   fileName,
661                   this.project,
662                   searcher,
663                   this.compilerOptions,
664                   false,
665                   this.workingCopyOwner,
666                   monitor);
667             } catch (JavaModelException e) {
668               compilationUnitDeclaration = CompilationUnitResolver.parse(
669                   source,
670                   searcher,
671                   this.compilerOptions);
672               needToResolveBindings = false;
673             }
674           } else {
675             compilationUnitDeclaration = CompilationUnitResolver.parse(
676                 source,
677                 searcher,
678                 this.compilerOptions);
679             needToResolveBindings = false;
680           }
681           return convert(monitor, compilationUnitDeclaration, source, needToResolveBindings);
682         } finally {
683           if (compilationUnitDeclaration != null && this.resolveBindings) {
684             compilationUnitDeclaration.cleanUp();
685           }
686         }          
687     }
688     throw new IllegalStateException();
689   }
690 
691   /**
692    * @param monitor IProgressMonitor
693    * @param compilationUnitDeclaration CompilationUnitDeclaration
694    * @param source char[]
695    * @return ASTNode
696    */
697   private ASTNode convert(IProgressMonitor monitor, CompilationUnitDeclaration compilationUnitDeclaration, char[] source, boolean needToResolveBindings) {
698     BindingResolver resolver = null;
699     AST ast = AST.newAST(this.apiLevel);
700     ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
701     CompilationUnit compilationUnit = null;
702     if (AST.JLS2 == this.apiLevel) {
703       ASTConverter converter = new ASTConverter(this.compilerOptions, needToResolveBindings, monitor);
704       if (needToResolveBindings) {
705         resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope);
706       } else {
707         resolver = new BindingResolver();
708       }
709       ast.setBindingResolver(resolver);
710       converter.setAST(ast);
711       compilationUnit = converter.convert(compilationUnitDeclaration, source);
712       compilationUnit.setLineEndTable(compilationUnitDeclaration.compilationResult.lineSeparatorPositions);
713     } else {
714       throw new RuntimeException("J2SE 1.5 parser not implemented yet"); //$NON-NLS-1$
715     }
716     ast.setDefaultNodeFlag(0);
717     ast.setOriginalModificationCount(ast.modificationCount());
718     return compilationUnit;
719   }
720 
721   /**
722    * Parses the given source between the bounds specified by the given offset (inclusive)
723    * and the given length and creates and returns a corresponding abstract syntax tree.
724    * <p>
725    * When the parse is successful the result returned includes the ASTs for the
726    * requested source:
727    * <ul>
728    * <li>{@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
729    * is a {@link TypeDeclaration TypeDeclaration} whose
730    * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
731    * are the new trees. Other aspects of the type declaration are unspecified.</li>
732    * <li>{@link #K_STATEMENTS K_STATEMENTS}: The result node is a
733    * {@link Block Block} whose {@link Block#statements() statements}
734    * are the new trees. Other aspects of the block are unspecified.</li>
735    * <li>{@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
736    * {@link Expression Expression}. Other aspects of the expression are unspecified.</li>
737    * </ul>
738    * The resulting AST node is rooted under an contrived
739    * {@link CompilationUnit CompilationUnit} node, to allow the
740    * client to retrieve the following pieces of information 
741    * available there:
742    * <ul>
743    * <li>{@linkplain CompilationUnit#lineNumber(int) Line number map}. Line
744    * numbers start at 1 and only cover the subrange scanned
745    * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
746    * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
747    * and {@linkplain CompilationUnit#getProblems() detailed problem reports}.
748    * Character positions are relative to the start of 
749    * <code>source</code>; line positions are for the subrange scanned.</li>
750    * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
751    * for the subrange scanned.</li>
752    * </ul>
753    * The contrived nodes do not have source positions. Other aspects of the
754    * {@link CompilationUnit CompilationUnit} node are unspecified, including
755    * the exact arrangment of intervening nodes.
756    * </p>
757    * <p>
758    * Lexical or syntax errors detected while parsing can result in
759    * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
760    * In more severe failure cases where the parser is unable to
761    * recognize the input, this method returns 
762    * a {@link CompilationUnit CompilationUnit} node with at least the
763    * compiler messages.
764    * </p>
765    * <p>Each node in the subtree (other than the contrived nodes) 
766    * carries source range(s) information relating back
767    * to positions in the given source (the given source itself
768    * is not remembered with the AST). 
769    * The source range usually begins at the first character of the first token 
770    * corresponding to the node; leading whitespace and comments are <b>not</b>
771    * included. The source range usually extends through the last character of
772    * the last token corresponding to the node; trailing whitespace and
773    * comments are <b>not</b> included. There are a handful of exceptions
774    * (including the various body declarations); the
775    * specification for these node type spells out the details.
776    * Source ranges nest properly: the source range for a child is always
777    * within the source range of its parent, and the source ranges of sibling
778    * nodes never overlap.
779    * </p>
780    * <p>
781    * This method does not compute binding information; all <code>resolveBinding</code>
782    * methods applied to nodes of the resulting AST return <code>null</code>.
783    * </p>
784    * 
785    * @return an AST node whose type depends on the kind of parse
786    *  requested, with a fallback to a <code>CompilationUnit</code>
787    *  in the case of severe parsing errors
788    * @see ASTNode#getStartPosition()
789    * @see ASTNode#getLength()
790    */
791   private ASTNode internalCreateASTForKind() {
792     ASTConverter converter = new ASTConverter(this.compilerOptions, false, null);
793     converter.compilationUnitSource = this.rawSource;
794     converter.scanner.setSource(this.rawSource);
795     
796     AST ast = AST.newAST(this.apiLevel);
797     ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
798     ast.setBindingResolver(new BindingResolver());
799     converter.setAST(ast);
800     CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil();
801     CompilationUnit compilationUnit = ast.newCompilationUnit();
802     if (this.sourceLength == -1) {
803       this.sourceLength = this.rawSource.length;
804     }
805     switch(this.astKind) {
806       case K_STATEMENTS :
807         ConstructorDeclaration constructorDeclaration = codeSnippetParsingUtil.parseStatements(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true);
808         RecordedParsingInformation recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
809         int[][] comments = recordedParsingInformation.commentPositions;
810         if (comments != null) {
811           converter.buildCommentsTable(compilationUnit, comments);
812         }
813         compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
814         if (constructorDeclaration != null) {
815           Block block = ast.newBlock();
816           Statement[] statements = constructorDeclaration.statements;
817           if (statements != null) {
818             int statementsLength = statements.length;
819             for (int i = 0; i < statementsLength; i++) {
820               block.statements().add(converter.convert(statements[i]));
821             }
822           }
823           rootNodeToCompilationUnit(ast, compilationUnit, block, recordedParsingInformation);
824           ast.setDefaultNodeFlag(0);
825           ast.setOriginalModificationCount(ast.modificationCount());
826           return block;
827         } else {
828           IProblem[] problems = recordedParsingInformation.problems;
829           if (problems != null) {
830             compilationUnit.setProblems(problems);
831           }
832           ast.setDefaultNodeFlag(0);
833           ast.setOriginalModificationCount(ast.modificationCount());
834           return compilationUnit;
835         }
836       case K_EXPRESSION :
837         org.eclipse.jdt.internal.compiler.ast.Expression expression = codeSnippetParsingUtil.parseExpression(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true);
838         recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
839         comments = recordedParsingInformation.commentPositions;
840         if (comments != null) {
841           converter.buildCommentsTable(compilationUnit, comments);
842         }
843         compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
844         if (expression != null) {
845           Expression expression2 = converter.convert(expression);
846           rootNodeToCompilationUnit(expression2.getAST(), compilationUnit, expression2, codeSnippetParsingUtil.recordedParsingInformation);
847           ast.setDefaultNodeFlag(0);
848           ast.setOriginalModificationCount(ast.modificationCount());
849           return expression2;
850         } else {
851           IProblem[] problems = recordedParsingInformation.problems;
852           if (problems != null) {
853             compilationUnit.setProblems(problems);
854           }
855           ast.setDefaultNodeFlag(0);
856           ast.setOriginalModificationCount(ast.modificationCount());
857           return compilationUnit;
858         }
859       case K_CLASS_BODY_DECLARATIONS :
860         final org.eclipse.jdt.internal.compiler.ast.ASTNode[] nodes = codeSnippetParsingUtil.parseClassBodyDeclarations(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true);
861         recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
862         comments = recordedParsingInformation.commentPositions;
863         if (comments != null) {
864           converter.buildCommentsTable(compilationUnit, comments);
865         }
866         compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
867         if (nodes != null) {
868           TypeDeclaration typeDeclaration = converter.convert(nodes);
869           rootNodeToCompilationUnit(typeDeclaration.getAST(), compilationUnit, typeDeclaration, codeSnippetParsingUtil.recordedParsingInformation);
870           ast.setDefaultNodeFlag(0);
871           ast.setOriginalModificationCount(ast.modificationCount());
872           return typeDeclaration;
873         } else {
874           IProblem[] problems = recordedParsingInformation.problems;
875           if (problems != null) {
876             compilationUnit.setProblems(problems);
877           }
878           ast.setDefaultNodeFlag(0);
879           ast.setOriginalModificationCount(ast.modificationCount());
880           return compilationUnit;
881         }
882     }
883     throw new IllegalStateException();
884   }
885 
886   private void propagateErrors(ASTNode astNode, IProblem[] problems) {
887     ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(problems);
888     astNode.accept(syntaxErrorPropagator);
889   }
890   
891   private void rootNodeToCompilationUnit(AST ast, CompilationUnit compilationUnit, ASTNode node, RecordedParsingInformation recordedParsingInformation) {
892     final int problemsCount = recordedParsingInformation.problemsCount;
893     switch(node.getNodeType()) {
894       case ASTNode.BLOCK :
895         {
896           Block block = (Block) node;
897           if (problemsCount != 0) {
898             // propagate and record problems
899             final IProblem[] problems = recordedParsingInformation.problems;
900             for (int i = 0, max = block.statements().size(); i < max; i++) {
901               propagateErrors((ASTNode) block.statements().get(i), problems);
902             }
903             compilationUnit.setProblems(problems);
904           }
905           TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
906           Initializer initializer = ast.newInitializer();
907           initializer.setBody(block);
908           typeDeclaration.bodyDeclarations().add(initializer);
909           compilationUnit.types().add(typeDeclaration);
910         }
911         break;
912       case ASTNode.TYPE_DECLARATION :
913         {
914           TypeDeclaration typeDeclaration = (TypeDeclaration) node;
915           if (problemsCount != 0) {
916             // propagate and record problems
917             final IProblem[] problems = recordedParsingInformation.problems;
918             for (int i = 0, max = typeDeclaration.bodyDeclarations().size(); i < max; i++) {
919               propagateErrors((ASTNode) typeDeclaration.bodyDeclarations().get(i), problems);
920             }
921             compilationUnit.setProblems(problems);
922           }
923           compilationUnit.types().add(typeDeclaration);
924         }
925         break;
926       default :
927         if (node instanceof Expression) {
928           Expression expression = (Expression) node;
929           if (problemsCount != 0) {
930             // propagate and record problems
931             final IProblem[] problems = recordedParsingInformation.problems;
932             propagateErrors(expression, problems);
933             compilationUnit.setProblems(problems);
934           }
935           ExpressionStatement expressionStatement = ast.newExpressionStatement(expression);
936           Block block = ast.newBlock();
937           block.statements().add(expressionStatement);
938           Initializer initializer = ast.newInitializer();
939           initializer.setBody(block);
940           TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
941           typeDeclaration.bodyDeclarations().add(initializer);
942           compilationUnit.types().add(typeDeclaration);
943         }
944     }
945   }
946 }