e3d0873c67cd1bcd0f834d49c45119e4f9c42794
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / ASTParser.java
1 /*******************************************************************************
2  * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
12
13 import java.io.PrintWriter;
14 import java.io.StringWriter;
15 import java.util.HashMap;
16 import java.util.Map;
17
18 import org.eclipse.core.runtime.IProgressMonitor;
19 import net.sourceforge.phpdt.core.IClassFile;
20 import net.sourceforge.phpdt.core.ICompilationUnit;
21 import net.sourceforge.phpdt.core.IJavaElement;
22 import net.sourceforge.phpdt.core.ITypeRoot;
23 import net.sourceforge.phpdt.core.IJavaProject;
24 import net.sourceforge.phpdt.core.JavaCore;
25 import net.sourceforge.phpdt.core.JavaModelException;
26 import net.sourceforge.phpdt.core.WorkingCopyOwner;
27 import net.sourceforge.phpdt.core.compiler.CategorizedProblem;
28 import net.sourceforge.phpdt.core.compiler.CharOperation;
29 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
30 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
31 import net.sourceforge.phpdt.internal.compiler.env.IBinaryType;
32 import net.sourceforge.phpdt.internal.compiler.parser.RecoveryScanner;
33 import net.sourceforge.phpdt.internal.compiler.parser.RecoveryScannerData;
34 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
35 import net.sourceforge.phpdt.internal.compiler.util.SuffixConstants;
36 import net.sourceforge.phpdt.internal.core.*;
37 import net.sourceforge.phpdt.internal.core.util.CodeSnippetParsingUtil;
38 import net.sourceforge.phpdt.internal.core.util.RecordedParsingInformation;
39 import net.sourceforge.phpdt.internal.core.util.Util;
40
41 /**
42  * A Java language parser for creating abstract syntax trees (ASTs).
43  * <p>
44  * Example: Create basic AST from source string
45  * <pre>
46  * char[] source = ...;
47  * ASTParser parser = ASTParser.newParser(AST.JLS3);  // handles JDK 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6
48  * parser.setSource(source);
49  * CompilationUnit result = (CompilationUnit) parser.createAST(null);
50  * </pre>
51  * Once a configured parser instance has been used to create an AST,
52  * the settings are automatically reset to their defaults,
53  * ready for the parser instance to be reused.
54  * </p>
55  * <p>
56  * There are a number of configurable features:
57  * <ul>
58  * <li>Source string from {@link #setSource(char[]) char[]},
59  * {@link #setSource(ICompilationUnit) ICompilationUnit},
60  * or {@link #setSource(IClassFile) IClassFile}, and limited
61  * to a specified {@linkplain #setSourceRange(int,int) subrange}.</li>
62  * <li>Whether {@linkplain #setResolveBindings(boolean) bindings} will be created.</li>
63  * <li>Which {@linkplain #setWorkingCopyOwner(WorkingCopyOwner)
64  * working copy owner} to use when resolving bindings.</li>
65  * <li>A hypothetical {@linkplain #setUnitName(String) compilation unit file name}
66  * and {@linkplain #setProject(IJavaProject) Java project}
67  * for locating a raw source string in the Java model (when
68  * resolving bindings)</li>
69  * <li>Which {@linkplain #setCompilerOptions(Map) compiler options}
70  * to use. This is especially important to use if the parsing/scanning of the source code requires a
71  * different version than the default of the workspace. For example, the workspace defaults are 1.4 and
72  * you want to create an AST for a source code that is using 1.5 constructs.</li>
73  * <li>Whether to parse just {@linkplain #setKind(int) an expression, statements,
74  * or body declarations} rather than an entire compilation unit.</li>
75  * <li>Whether to return a {@linkplain #setFocalPosition(int) abridged AST}
76  * focused on the declaration containing a given source position.</li>
77  * </ul>
78  * </p>
79  *
80  * @since 3.0
81  * @noinstantiate This class is not intended to be instantiated by clients.
82  */
83 public class ASTParser {
84
85         /**
86          * Kind constant used to request that the source be parsed
87      * as a single expression.
88          */
89         public static final int K_EXPRESSION = 0x01;
90
91         /**
92          * Kind constant used to request that the source be parsed
93      * as a sequence of statements.
94          */
95         public static final int K_STATEMENTS = 0x02;
96
97         /**
98          * Kind constant used to request that the source be parsed
99          * as a sequence of class body declarations.
100          */
101         public static final int K_CLASS_BODY_DECLARATIONS = 0x04;
102
103         /**
104          * Kind constant used to request that the source be parsed
105          * as a compilation unit.
106          */
107         public static final int K_COMPILATION_UNIT = 0x08;
108
109         /**
110          * Creates a new object for creating a Java abstract syntax tree
111      * (AST) following the specified set of API rules.
112      *
113          * @param level the API level; one of the LEVEL constants
114      * declared on <code>AST</code>
115          * @return new ASTParser instance
116          */
117         public static ASTParser newParser(int level) {
118                 return new ASTParser(level);
119         }
120
121         /**
122          * Level of AST API desired.
123          */
124         private final int apiLevel;
125
126         /**
127          * Kind of parse requested. Defaults to an entire compilation unit.
128          */
129         private int astKind;
130
131         /**
132          * Compiler options. Defaults to JavaCore.getOptions().
133          */
134         private Map compilerOptions;
135
136         /**
137          * Request for bindings. Defaults to <code>false</code>.
138      */
139         private boolean resolveBindings;
140
141         /**
142          * Request for a partial AST. Defaults to <code>false</code>.
143      */
144         private boolean partial = false;
145
146         /**
147          * Request for a statements recovery. Defaults to <code>false</code>.
148      */
149         private boolean statementsRecovery;
150
151         /**
152      * Request for a bindings recovery. Defaults to <code>false</code>.
153      */
154     private boolean bindingsRecovery;
155
156     /**
157          * The focal point for a partial AST request.
158      * Only used when <code>partial</code> is <code>true</code>.
159      */
160         private int focalPointPosition;
161
162     /**
163      * Source string.
164      */
165     private char[] rawSource = null;
166
167     /**
168      * Java model class file or compilation unit supplying the source.
169      */
170     private ITypeRoot typeRoot = null;
171
172     /**
173      * Character-based offset into the source string where parsing is to
174      * begin. Defaults to 0.
175      */
176         private int sourceOffset = 0;
177
178     /**
179      * Character-based length limit, or -1 if unlimited.
180      * All characters in the source string between <code>offset</code>
181      * and <code>offset+length-1</code> inclusive are parsed. Defaults to -1,
182      * which means the rest of the source string.
183      */
184         private int sourceLength = -1;
185
186     /**
187      * Working copy owner. Defaults to primary owner.
188      */
189         private WorkingCopyOwner workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
190
191     /**
192          * Java project used to resolve names, or <code>null</code> if none.
193      * Defaults to none.
194      */
195         private IJavaProject project = null;
196
197     /**
198          * Name of the compilation unit for resolving bindings, or
199          * <code>null</code> if none. Defaults to none.
200      */
201         private String unitName = null;
202
203         /**
204          * Creates a new AST parser for the given API level.
205          * <p>
206          * N.B. This constructor is package-private.
207          * </p>
208          *
209          * @param level the API level; one of the LEVEL constants
210      * declared on <code>AST</code>
211          */
212         ASTParser(int level) {
213                 if ((level != AST.JLS2_INTERNAL)
214                         && (level != AST.JLS3)) {
215                         throw new IllegalArgumentException();
216                 }
217                 this.apiLevel = level;
218                 initializeDefaults();
219         }
220
221         /**
222          * Sets all the setting to their default values.
223          */
224         private void initializeDefaults() {
225                 this.astKind = K_COMPILATION_UNIT;
226                 this.rawSource = null;
227                 this.typeRoot = null;
228                 this.resolveBindings = false;
229                 this.sourceLength = -1;
230                 this.sourceOffset = 0;
231                 this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
232                 this.unitName = null;
233                 this.project = null;
234                 this.partial = false;
235                 Map options = JavaCore.getOptions();
236                 options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
237                 this.compilerOptions = options;
238         }
239
240     /**
241      * Requests that the compiler should perform bindings recovery.
242      * When bindings recovery is enabled the compiler returns incomplete bindings.
243      * <p>
244      * Default to <code>false</code>.
245      * </p>
246      * <p>This should be set to true only if bindings are resolved. It has no effect if there is no binding
247      * resolution.</p>
248      *
249      * @param enabled <code>true</code> if incomplete bindings are expected,
250      *   and <code>false</code> if only complete bindings are expected.
251      *
252      * @see IBinding#isRecovered()
253      * @since 3.3
254      */
255     public void setBindingsRecovery(boolean enabled) {
256         this.bindingsRecovery = enabled;
257     }
258         /**
259          * Sets the compiler options to be used when parsing.
260          * <p>
261          * Note that {@link #setSource(IClassFile)},
262          * {@link #setSource(ICompilationUnit)},
263          * and {@link #setProject(IJavaProject)} reset the compiler options
264          * based on the Java project. In other cases, compiler options default
265          * to {@link JavaCore#getOptions()}. In either case, and especially
266          * in the latter, the caller should carefully weight the consequences of
267          * allowing compiler options to be defaulted as opposed to being
268          * explicitly specified for the <code>ASTParser</code> instance.
269          * For instance, there is a compiler option called "Source Compatibility Mode"
270          * which determines which JDK level the source code is expected to meet.
271          * If you specify "1.4", then "assert" is treated as a keyword and disallowed
272          * as an identifier; if you specify "1.3", then "assert" is allowed as an
273          * identifier. So this particular setting has a major bearing on what is
274          * considered syntactically legal. By explicitly specifying the setting,
275          * the client control exactly how the parser works. On the other hand,
276          * allowing default settings means the parsing behaves like other JDT tools.
277          * </p>
278          *
279          * @param options the table of options (key type: <code>String</code>;
280          * value type: <code>String</code>), or <code>null</code>
281          * to set it back to the default
282          */
283         public void setCompilerOptions(Map options) {
284                 if (options == null) {
285                         options = JavaCore.getOptions();
286                 } else {
287                         // copy client's options so as to not do any side effect on them
288                         options = new HashMap(options);
289                 }
290                 options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
291                 this.compilerOptions = options;
292         }
293
294         /**
295          * Requests that the compiler should provide binding information for
296      * the AST nodes it creates.
297      * <p>
298      * Default to <code>false</code> (no bindings).
299      * </p>
300          * <p>
301          * If <code>setResolveBindings(true)</code>, the various names
302          * and types appearing in the AST can be resolved to "bindings"
303          * by calling the <code>resolveBinding</code> methods. These bindings
304          * draw connections between the different parts of a program, and
305          * generally afford a more powerful vantage point for clients who wish to
306          * analyze a program's structure more deeply. These bindings come at a
307          * considerable cost in both time and space, however, and should not be
308          * requested frivolously. The additional space is not reclaimed until the
309          * AST, all its nodes, and all its bindings become garbage. So it is very
310          * important to not retain any of these objects longer than absolutely
311          * necessary. Bindings are resolved at the time the AST is created. Subsequent
312          * modifications to the AST do not affect the bindings returned by
313          * <code>resolveBinding</code> methods in any way; these methods return the
314          * same binding as before the AST was modified (including modifications
315          * that rearrange subtrees by reparenting nodes).
316          * If <code>setResolveBindings(false)</code> (the default), the analysis
317          * does not go beyond parsing and building the tree, and all
318          * <code>resolveBinding</code> methods return <code>null</code> from the
319          * outset.
320          * </p>
321          * <p>
322          * When bindings are requested, instead of considering compilation units on disk only
323          * one can supply a <code>WorkingCopyOwner</code>. Working copies owned
324          * by this owner take precedence over the underlying compilation units when looking
325          * up names and drawing the connections.
326          * </p>
327          * <p>
328      * Binding information is obtained from the Java model.
329      * This means that the compilation unit must be located relative to the
330      * Java model. This happens automatically when the source code comes from
331      * either {@link #setSource(ICompilationUnit) setSource(ICompilationUnit)}
332      * or {@link #setSource(IClassFile) setSource(IClassFile)}.
333      * When source is supplied by {@link #setSource(char[]) setSource(char[])},
334      * the location must be extablished explicitly by calling
335      * {@link #setProject(IJavaProject)} and  {@link #setUnitName(String)}.
336          * Note that the compiler options that affect doc comment checking may also
337          * affect whether any bindings are resolved for nodes within doc comments.
338          * </p>
339          *
340          * @param bindings <code>true</code> if bindings are wanted,
341          *   and <code>false</code> if bindings are not of interest
342          */
343         public void setResolveBindings(boolean bindings) {
344           this.resolveBindings = bindings;
345         }
346
347         /**
348      * Requests an abridged abstract syntax tree.
349      * By default, complete ASTs are returned.
350      * <p>
351      * When <code>true</code> the resulting AST does not have nodes for
352      * the entire compilation unit. Rather, the AST is only fleshed out
353      * for the node that include the given source position. This kind of limited
354      * AST is sufficient for certain purposes but totally unsuitable for others.
355      * In places where it can be used, the limited AST offers the advantage of
356      * being smaller and faster to construct.
357          * </p>
358          * <p>
359          * The AST will include nodes for all of the compilation unit's
360          * package, import, and top-level type declarations. It will also always contain
361          * nodes for all the body declarations for those top-level types, as well
362          * as body declarations for any member types. However, some of the body
363          * declarations may be abridged. In particular, the statements ordinarily
364          * found in the body of a method declaration node will not be included
365          * (the block will be empty) unless the source position falls somewhere
366          * within the source range of that method declaration node. The same is true
367          * for initializer declarations; the statements ordinarily found in the body
368          * of initializer node will not be included unless the source position falls
369          * somewhere within the source range of that initializer declaration node.
370          * Field declarations are never abridged. Note that the AST for the body of
371          * that one unabridged method (or initializer) is 100% complete; it has all
372          * its statements, including any local or anonymous type declarations
373          * embedded within them. When the the given position is not located within
374          * the source range of any body declaration of a top-level type, the AST
375          * returned will be a skeleton that includes nodes for all and only the major
376          * declarations; this kind of AST is still quite useful because it contains
377          * all the constructs that introduce names visible to the world outside the
378          * compilation unit.
379          * </p>
380          *
381          * @param position a position into the corresponding body declaration
382          */
383         public void setFocalPosition(int position) {
384                 this.partial = true;
385                 this.focalPointPosition = position;
386         }
387
388         /**
389          * Sets the kind of constructs to be parsed from the source.
390      * Defaults to an entire compilation unit.
391          * <p>
392          * When the parse is successful the result returned includes the ASTs for the
393          * requested source:
394          * <ul>
395          * <li>{@link #K_COMPILATION_UNIT K_COMPILATION_UNIT}: The result node
396          * is a {@link CompilationUnit}.</li>
397          * <li>{@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
398          * is a {@link TypeDeclaration} whose
399          * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
400          * are the new trees. Other aspects of the type declaration are unspecified.</li>
401          * <li>{@link #K_STATEMENTS K_STATEMENTS}: The result node is a
402          * {@link Block Block} whose {@link Block#statements() statements}
403          * are the new trees. Other aspects of the block are unspecified.</li>
404          * <li>{@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
405          * {@link Expression Expression}. Other aspects of the expression are unspecified.</li>
406          * </ul>
407          * The resulting AST node is rooted under (possibly contrived)
408          * {@link CompilationUnit CompilationUnit} node, to allow the
409          * client to retrieve the following pieces of information
410          * available there:
411          * <ul>
412          * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
413          * numbers start at 1 and only cover the subrange scanned
414          * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
415          * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
416          * and {@linkplain CompilationUnit#getProblems() detailed problem reports}.
417          * Character positions are relative to the start of
418          * <code>source</code>; line positions are for the subrange scanned.</li>
419          * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
420          * for the subrange scanned.</li>
421          * </ul>
422          * The contrived nodes do not have source positions. Other aspects of the
423          * {@link CompilationUnit CompilationUnit} node are unspecified, including
424          * the exact arrangment of intervening nodes.
425          * </p>
426          * <p>
427          * Lexical or syntax errors detected while parsing can result in
428          * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
429          * In more severe failure cases where the parser is unable to
430          * recognize the input, this method returns
431          * a {@link CompilationUnit CompilationUnit} node with at least the
432          * compiler messages.
433          * </p>
434          * <p>Each node in the subtree (other than the contrived nodes)
435          * carries source range(s) information relating back
436          * to positions in the given source (the given source itself
437          * is not remembered with the AST).
438          * The source range usually begins at the first character of the first token
439          * corresponding to the node; leading whitespace and comments are <b>not</b>
440          * included. The source range usually extends through the last character of
441          * the last token corresponding to the node; trailing whitespace and
442          * comments are <b>not</b> included. There are a handful of exceptions
443          * (including the various body declarations); the
444          * specification for these node type spells out the details.
445          * Source ranges nest properly: the source range for a child is always
446          * within the source range of its parent, and the source ranges of sibling
447          * nodes never overlap.
448          * </p>
449          * <p>
450          * Binding information is only computed when <code>kind</code> is
451      * <code>K_COMPILATION_UNIT</code>.
452          * </p>
453          *
454          * @param kind the kind of construct to parse: one of
455          * {@link #K_COMPILATION_UNIT},
456          * {@link #K_CLASS_BODY_DECLARATIONS},
457          * {@link #K_EXPRESSION},
458          * {@link #K_STATEMENTS}
459          */
460         public void setKind(int kind) {
461             if ((kind != K_COMPILATION_UNIT)
462                     && (kind != K_CLASS_BODY_DECLARATIONS)
463                     && (kind != K_EXPRESSION)
464                     && (kind != K_STATEMENTS)) {
465                 throw new IllegalArgumentException();
466             }
467                 this.astKind = kind;
468         }
469
470         /**
471      * Sets the source code to be parsed.
472      *
473          * @param source the source string to be parsed,
474      * or <code>null</code> if none
475      */
476         public void setSource(char[] source) {
477                 this.rawSource = source;
478                 // clear the type root
479                 this.typeRoot = null;
480         }
481
482         /**
483      * Sets the source code to be parsed.
484      * This method automatically sets the project (and compiler
485      * options) based on the given compilation unit, in a manner
486      * equivalent to <code>setProject(source.getJavaProject())</code>
487      *
488          * @param source the Java model compilation unit whose source code
489      * is to be parsed, or <code>null</code> if none
490       */
491         public void setSource(ICompilationUnit source) {
492                 setSource((ITypeRoot)source);
493         }
494
495         /**
496      * Sets the source code to be parsed.
497      * <p>This method automatically sets the project (and compiler
498      * options) based on the given compilation unit, in a manner
499      * equivalent to <code>setProject(source.getJavaProject())</code>.</p>
500      * <p>If the given class file has  no source attachment, the creation of the
501      * ast will fail with an IllegalStateException.</p>
502      *
503          * @param source the Java model class file whose corresponding source code
504      * is to be parsed, or <code>null</code> if none
505      */
506         public void setSource(IClassFile source) {
507                 setSource((ITypeRoot)source);
508         }
509
510         /**
511          * Sets the source code to be parsed.
512          * <p>This method automatically sets the project (and compiler
513          * options) based on the given compilation unit of class file, in a manner
514          * equivalent to <code>setProject(source.getJavaProject())</code>.</p>
515          * <p>If the source is a class file without source attachment, the creation of the
516          * ast will fail with an IllegalStateException.</p>
517          *
518          * @param source the Java model compilation unit or class file whose corresponding source code
519          * is to be parsed, or <code>null</code> if none
520          * @since 3.3
521          */
522         public void setSource(ITypeRoot source) {
523                 this.typeRoot = source;
524                 // clear the raw source
525                 this.rawSource = null;
526                 if (source != null) {
527                         this.project = source.getJavaProject();
528                         Map options = this.project.getOptions(true);
529                         options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
530                         this.compilerOptions = options;
531                 }
532         }
533
534         /**
535      * Sets the subrange of the source code to be parsed.
536      * By default, the entire source string will be parsed
537      * (<code>offset</code> 0 and <code>length</code> -1).
538      *
539      * @param offset the index of the first character to parse
540      * @param length the number of characters to parse, or -1 if
541      * the remainder of the source string is
542      */
543         public void setSourceRange(int offset, int length) {
544                 if (offset < 0 || length < -1) {
545                         throw new IllegalArgumentException();
546                 }
547                 this.sourceOffset = offset;
548                 this.sourceLength = length;
549         }
550
551         /**
552          * Requests that the compiler should perform statements recovery.
553          * When statements recovery is enabled the compiler tries to create statement nodes
554          * from code containing syntax errors
555      * <p>
556      * Default to <code>false</code>.
557      * </p>
558          *
559          * @param enabled <code>true</code> if statements containing syntax errors are wanted,
560          *   and <code>false</code> if these statements aren't wanted.
561          *
562          * @since 3.2
563          */
564         public void setStatementsRecovery(boolean enabled) {
565                 this.statementsRecovery = enabled;
566         }
567
568     /**
569      * Sets the working copy owner using when resolving bindings, where
570      * <code>null</code> means the primary owner. Defaults to the primary owner.
571      *
572          * @param owner the owner of working copies that take precedence over underlying
573          *   compilation units, or <code>null</code> if the primary owner should be used
574      */
575         public void setWorkingCopyOwner(WorkingCopyOwner owner) {
576             if (owner == null) {
577                         this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
578                 } else {
579                         this.workingCopyOwner = owner;
580                 }
581         }
582
583         /**
584      * Sets the name of the compilation unit that would hypothetically contains
585      * the source string. This is used in conjunction with {@link #setSource(char[])}
586      * and {@link #setProject(IJavaProject) } to locate the compilation unit relative to a Java project.
587      * Defaults to none (<code>null</code>).
588          * <p>
589          * The name of the compilation unit must be supplied for resolving bindings.
590          * This name should be suffixed by a dot ('.') followed by one of the
591          * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}
592          * and match the name of the main (public) class or interface declared in the source.</p>
593          *
594          * <p>This name must represent the full path of the unit inside the given project. For example, if the source
595          * declares a public class named "Foo" in a project "P", the name of the compilation unit must be
596          * "/P/Foo.java". If the source declares a public class name "Bar" in a package "p1.p2" in a project "P",
597          * the name of the compilation unit must be "/P/p1/p2/Bar.java".</p>
598      *
599          * @param unitName the name of the compilation unit that would contain the source
600          *    string, or <code>null</code> if none
601      */
602         public void setUnitName(String unitName) {
603                 this.unitName = unitName;
604         }
605
606         /**
607          * Sets the Java project used when resolving bindings.
608          * This method automatically sets the compiler
609          * options based on the given project:
610          * <pre>
611          * setCompilerOptions(project.getOptions(true));
612          * </pre>
613          * See {@link #setCompilerOptions(Map)} for a discussion of
614          * the pros and cons of using these options vs specifying
615          * compiler options explicitly.
616          * This setting is used in conjunction with <code>setSource(char[])</code>.
617          * For the purposes of resolving bindings, types declared in the
618          * source string will hide types by the same name available
619          * through the classpath of the given project.
620          * Defaults to none (<code>null</code>).
621          *
622          * @param project the Java project used to resolve names, or
623          *    <code>null</code> if none
624          */
625         public void setProject(IJavaProject project) {
626                 this.project = project;
627                 if (project != null) {
628                         Map options = project.getOptions(true);
629                         options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
630                         this.compilerOptions = options;
631                 }
632         }
633
634         /**
635      * Creates an abstract syntax tree.
636      * <p>
637      * A successful call to this method returns all settings to their
638      * default values so the object is ready to be reused.
639      * </p>
640      *
641          * @param monitor the progress monitor used to report progress and request cancelation,
642          *   or <code>null</code> if none
643          * @return an AST node whose type depends on the kind of parse
644          *  requested, with a fallback to a <code>CompilationUnit</code>
645          *  in the case of severe parsing errors
646          * @exception IllegalStateException if the settings provided
647          * are insufficient, contradictory, or otherwise unsupported
648      */
649         public ASTNode createAST(IProgressMonitor monitor) {
650            ASTNode result = null;
651            if (monitor != null) monitor.beginTask("", 1); //$NON-NLS-1$
652                 try {
653                         if (this.rawSource == null && this.typeRoot == null) {
654                           throw new IllegalStateException("source not specified"); //$NON-NLS-1$
655                    }
656                         result = internalCreateAST(monitor);
657                 } finally {
658                    // re-init defaults to allow reuse (and avoid leaking)
659                    initializeDefaults();
660                    if (monitor != null) monitor.done();
661                 }
662            return result;
663         }
664
665         /**
666      * Creates ASTs for a batch of compilation units.
667      * When bindings are being resolved, processing a
668      * batch of compilation units is more efficient because much
669      * of the work involved in resolving bindings can be shared.
670      * <p>
671      * When bindings are being resolved, all compilation units must
672      * come from the same Java project, which must be set beforehand
673      * with <code>setProject</code>.
674      * The compilation units are processed one at a time in no
675      * specified order. For each of the compilation units in turn,
676          * <ul>
677          * <li><code>ASTParser.createAST</code> is called to parse it
678          * and create a corresponding AST. The calls to
679          * <code>ASTParser.createAST</code> all employ the same settings.</li>
680          * <li><code>ASTRequestor.acceptAST</code> is called passing
681          * the compilation unit and the corresponding AST to
682          * <code>requestor</code>.
683          * </li>
684          * </ul>
685      * Note only ASTs from the given compilation units are reported
686      * to the requestor. If additional compilation units are required to
687      * resolve the original ones, the corresponding ASTs are <b>not</b>
688      * reported to the requestor.
689      * </p>
690          * <p>
691          * Note also the following parser parameters are used, regardless of what
692          * may have been specified:
693          * <ul>
694          * <li>The {@linkplain #setKind(int) parser kind} is <code>K_COMPILATION_UNIT</code></li>
695          * <li>The {@linkplain #setSourceRange(int,int) source range} is <code>(0, -1)</code></li>
696          * <li>The {@linkplain #setFocalPosition(int) focal position} is not set</li>
697          * </ul>
698          * </p>
699      * <p>
700      * The <code>bindingKeys</code> parameter specifies bindings keys
701      * ({@link IBinding#getKey()}) that are to be looked up. These keys may
702      * be for elements either inside or outside the set of compilation
703      * units being processed. When bindings are being resolved,
704      * the keys and corresponding bindings (or <code>null</code> if none) are
705      * passed to <code>ASTRequestor.acceptBinding</code>. Note that binding keys
706      * for elements outside the set of compilation units being processed are looked up
707      * after all <code>ASTRequestor.acceptAST</code> callbacks have been made.
708      * Binding keys for elements inside the set of compilation units being processed
709      * are looked up and reported right after the corresponding
710      * <code>ASTRequestor.acceptAST</code> callback has been made.
711      * No <code>ASTRequestor.acceptBinding</code> callbacks are made unless
712      * bindings are being resolved.
713      * </p>
714      * <p>
715      * A successful call to this method returns all settings to their
716      * default values so the object is ready to be reused.
717      * </p>
718      *
719      * @param compilationUnits the compilation units to create ASTs for
720      * @param bindingKeys the binding keys to create bindings for
721      * @param requestor the AST requestor that collects abtract syntax trees and bindings
722          * @param monitor the progress monitor used to report progress and request cancelation,
723          *   or <code>null</code> if none
724          * @exception IllegalStateException if the settings provided
725          * are insufficient, contradictory, or otherwise unsupported
726          * @since 3.1
727      */
728         public void createASTs(ICompilationUnit[] compilationUnits, String[] bindingKeys, ASTRequestor requestor, IProgressMonitor monitor) {
729                 try {
730                         int flags = 0;
731                         if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
732                         if (this.resolveBindings) {
733                                 if (this.project == null)
734                                         throw new IllegalStateException("project not specified"); //$NON-NLS-1$
735                                 if (this.bindingsRecovery) flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
736                                 CompilationUnitResolver.resolve(compilationUnits, bindingKeys, requestor, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner, flags, monitor);
737                         } else {
738                                 CompilationUnitResolver.parse(compilationUnits, requestor, this.apiLevel, this.compilerOptions, flags, monitor);
739                         }
740                 } finally {
741                         // re-init defaults to allow reuse (and avoid leaking)
742                         initializeDefaults();
743                 }
744         }
745
746         /**
747      * Creates bindings for a batch of Java elements. These elements are either
748      * enclosed in {@link ICompilationUnit}s or in {@link IClassFile}s.
749      * <p>
750      * All enclosing compilation units and class files must
751      * come from the same Java project, which must be set beforehand
752      * with <code>setProject</code>.
753      * </p>
754      * <p>
755      * All elements must exist. If one doesn't exist, an <code>IllegalStateException</code>
756      * is thrown.
757      * </p>
758      * <p>
759      * The returned array has the same size as the given elements array. At a given position
760      * it contains the binding of the corresponding Java element, or <code>null</code>
761      * if no binding could be created.
762      * </p>
763          * <p>
764          * Note also the following parser parameters are used, regardless of what
765          * may have been specified:
766          * <ul>
767          * <li>The {@linkplain #setResolveBindings(boolean) binding resolution flag} is <code>true</code></li>
768          * <li>The {@linkplain #setKind(int) parser kind} is <code>K_COMPILATION_UNIT</code></li>
769          * <li>The {@linkplain #setSourceRange(int,int) source range} is <code>(0, -1)</code></li>
770          * <li>The {@linkplain #setFocalPosition(int) focal position} is not set</li>
771          * </ul>
772          * </p>
773      * <p>
774      * A successful call to this method returns all settings to their
775      * default values so the object is ready to be reused.
776      * </p>
777      *
778      * @param elements the Java elements to create bindings for
779      * @return the bindings for the given Java elements, possibly containing <code>null</code>s
780      *              if some bindings could not be created
781          * @exception IllegalStateException if the settings provided
782          * are insufficient, contradictory, or otherwise unsupported
783          * @since 3.1
784      */
785         public IBinding[] createBindings(IJavaElement[] elements, IProgressMonitor monitor) {
786                 try {
787                         if (this.project == null)
788                                 throw new IllegalStateException("project not specified"); //$NON-NLS-1$
789                         int flags = 0;
790                         if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
791                         if (this.bindingsRecovery)  flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
792                         return CompilationUnitResolver.resolve(elements, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner, flags, monitor);
793                 } finally {
794                         // re-init defaults to allow reuse (and avoid leaking)
795                         initializeDefaults();
796                 }
797         }
798
799         private ASTNode internalCreateAST(IProgressMonitor monitor) {
800                 boolean needToResolveBindings = this.resolveBindings;
801                 switch(this.astKind) {
802                         case K_CLASS_BODY_DECLARATIONS :
803                         case K_EXPRESSION :
804                         case K_STATEMENTS :
805                                 if (this.rawSource != null) {
806                                         if (this.sourceOffset + this.sourceLength > this.rawSource.length) {
807                                             throw new IllegalStateException();
808                                         }
809                                         return internalCreateASTForKind();
810                                 }
811                                 break;
812                         case K_COMPILATION_UNIT :
813                                 CompilationUnitDeclaration compilationUnitDeclaration = null;
814                                 try {
815                                         NodeSearcher searcher = null;
816                                         net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit sourceUnit = null;
817                                         WorkingCopyOwner wcOwner = this.workingCopyOwner;
818                                         if (this.typeRoot instanceof ICompilationUnit) {
819                                                         /*
820                                                          * this.compilationUnitSource is an instance of org.eclipse.jdt.internal.core.CompilationUnit that implements
821                                                          * both org.eclipse.jdt.core.ICompilationUnit and org.eclipse.jdt.internal.compiler.env.ICompilationUnit
822                                                          */
823                                                         sourceUnit = (net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit) this.typeRoot;
824                                                         /*
825                                                          * use a BasicCompilation that caches the source instead of using the compilationUnitSource directly
826                                                          * (if it is a working copy, the source can change between the parse and the AST convertion)
827                                                          * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75632)
828                                                          */
829                                                         sourceUnit = new BasicCompilationUnit(sourceUnit.getContents(), sourceUnit.getPackageName(), new String(sourceUnit.getFileName()), this.project);
830                                                         wcOwner = ((ICompilationUnit) this.typeRoot).getOwner();
831                                         } else if (this.typeRoot instanceof IClassFile) {
832                                                 try {
833                                                         String sourceString = this.typeRoot.getSource();
834                                                         if (sourceString == null) {
835                                                                 throw new IllegalStateException();
836                                                         }
837                                                         PackageFragment packageFragment = (PackageFragment) this.typeRoot.getParent();
838                                                         BinaryType type = (BinaryType) this.typeRoot.findPrimaryType();
839                                                         IBinaryType binaryType = (IBinaryType) type.getElementInfo();
840                                                         // file name is used to recreate the Java element, so it has to be the toplevel .class file name
841                                                         char[] fileName = binaryType.getFileName();
842                                                         int firstDollar = CharOperation.indexOf('$', fileName);
843                                                         if (firstDollar != -1) {
844                                                                 char[] suffix = SuffixConstants.SUFFIX_class;
845                                                                 int suffixLength = suffix.length;
846                                                                 char[] newFileName = new char[firstDollar + suffixLength];
847                                                                 System.arraycopy(fileName, 0, newFileName, 0, firstDollar);
848                                                                 System.arraycopy(suffix, 0, newFileName, firstDollar, suffixLength);
849                                                                 fileName = newFileName;
850                                                         }
851                                                         sourceUnit = new BasicCompilationUnit(sourceString.toCharArray(), Util.toCharArrays(packageFragment.names), new String(fileName), this.project);
852                                                 } catch(JavaModelException e) {
853                                                         // an error occured accessing the java element
854                                                         StringWriter stringWriter = new StringWriter();
855                                                         PrintWriter writer = null;
856                                                         try {
857                                                                 writer = new PrintWriter(stringWriter);
858                                                                 e.printStackTrace(writer);
859                                                         } finally {
860                                                                 if (writer != null) writer.close();
861                                                         }
862                                                         throw new IllegalStateException(String.valueOf(stringWriter.getBuffer()));
863                                                 }
864                                         } else if (this.rawSource != null) {
865                                                 needToResolveBindings = this.resolveBindings && this.unitName != null && this.project != null && this.compilerOptions != null;
866                                                 sourceUnit = new BasicCompilationUnit(this.rawSource, null, this.unitName == null ? "" : this.unitName, this.project); //$NON-NLS-1$
867                                         } else {
868                                                 throw new IllegalStateException();
869                                         }
870                                         if (this.partial) {
871                                                 searcher = new NodeSearcher(this.focalPointPosition);
872                                         }
873                                         int flags = 0;
874                                         if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
875                                         if (needToResolveBindings) {
876                                                 if (this.bindingsRecovery) flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
877                                                 try {
878                                                         // parse and resolve
879                                                         compilationUnitDeclaration =
880                                                                 CompilationUnitResolver.resolve(
881                                                                         sourceUnit,
882                                                                         this.project,
883                                                                         searcher,
884                                                                         this.compilerOptions,
885                                                                         this.workingCopyOwner,
886                                                                         flags,
887                                                                         monitor);
888                                                 } catch (JavaModelException e) {
889                                                         flags &= ~ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
890                                                         compilationUnitDeclaration = CompilationUnitResolver.parse(
891                                                                         sourceUnit,
892                                                                         searcher,
893                                                                         this.compilerOptions,
894                                                                         flags);
895                                                         needToResolveBindings = false;
896                                                 }
897                                         } else {
898                                                 compilationUnitDeclaration = CompilationUnitResolver.parse(
899                                                                 sourceUnit,
900                                                                 searcher,
901                                                                 this.compilerOptions,
902                                                                 flags);
903                                                 needToResolveBindings = false;
904                                         }
905                                         CompilationUnit result = CompilationUnitResolver.convert(
906                                                 compilationUnitDeclaration,
907                                                 sourceUnit.getContents(),
908                                                 this.apiLevel,
909                                                 this.compilerOptions,
910                                                 needToResolveBindings,
911                                                 wcOwner,
912                                                 needToResolveBindings ? new DefaultBindingResolver.BindingTables() : null,
913                                                 flags,
914                                                 monitor);
915                                         result.setTypeRoot(this.typeRoot);
916                                         return result;
917                                 } finally {
918                                         if (compilationUnitDeclaration != null && this.resolveBindings) {
919                                                 compilationUnitDeclaration.cleanUp();
920                                         }
921                                 }
922                 }
923                 throw new IllegalStateException();
924         }
925
926         /**
927          * Parses the given source between the bounds specified by the given offset (inclusive)
928          * and the given length and creates and returns a corresponding abstract syntax tree.
929          * <p>
930          * When the parse is successful the result returned includes the ASTs for the
931          * requested source:
932          * <ul>
933          * <li>{@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
934          * is a {@link TypeDeclaration TypeDeclaration} whose
935          * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
936          * are the new trees. Other aspects of the type declaration are unspecified.</li>
937          * <li>{@link #K_STATEMENTS K_STATEMENTS}: The result node is a
938          * {@link Block Block} whose {@link Block#statements() statements}
939          * are the new trees. Other aspects of the block are unspecified.</li>
940          * <li>{@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
941          * {@link Expression Expression}. Other aspects of the expression are unspecified.</li>
942          * </ul>
943          * The resulting AST node is rooted under an contrived
944          * {@link CompilationUnit CompilationUnit} node, to allow the
945          * client to retrieve the following pieces of information
946          * available there:
947          * <ul>
948          * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
949          * numbers start at 1 and only cover the subrange scanned
950          * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
951          * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
952          * and {@linkplain CompilationUnit#getProblems() detailed problem reports}.
953          * Character positions are relative to the start of
954          * <code>source</code>; line positions are for the subrange scanned.</li>
955          * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
956          * for the subrange scanned.</li>
957          * </ul>
958          * The contrived nodes do not have source positions. Other aspects of the
959          * {@link CompilationUnit CompilationUnit} node are unspecified, including
960          * the exact arrangment of intervening nodes.
961          * </p>
962          * <p>
963          * Lexical or syntax errors detected while parsing can result in
964          * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
965          * In more severe failure cases where the parser is unable to
966          * recognize the input, this method returns
967          * a {@link CompilationUnit CompilationUnit} node with at least the
968          * compiler messages.
969          * </p>
970          * <p>Each node in the subtree (other than the contrived nodes)
971          * carries source range(s) information relating back
972          * to positions in the given source (the given source itself
973          * is not remembered with the AST).
974          * The source range usually begins at the first character of the first token
975          * corresponding to the node; leading whitespace and comments are <b>not</b>
976          * included. The source range usually extends through the last character of
977          * the last token corresponding to the node; trailing whitespace and
978          * comments are <b>not</b> included. There are a handful of exceptions
979          * (including the various body declarations); the
980          * specification for these node type spells out the details.
981          * Source ranges nest properly: the source range for a child is always
982          * within the source range of its parent, and the source ranges of sibling
983          * nodes never overlap.
984          * </p>
985          * <p>
986          * This method does not compute binding information; all <code>resolveBinding</code>
987          * methods applied to nodes of the resulting AST return <code>null</code>.
988          * </p>
989          *
990          * @return an AST node whose type depends on the kind of parse
991          *  requested, with a fallback to a <code>CompilationUnit</code>
992          *  in the case of severe parsing errors
993          * @see ASTNode#getStartPosition()
994          * @see ASTNode#getLength()
995          */
996         private ASTNode internalCreateASTForKind() {
997                 final ASTConverter converter = new ASTConverter(this.compilerOptions, false, null);
998                 converter.compilationUnitSource = this.rawSource;
999                 converter.compilationUnitSourceLength = this.rawSource.length;
1000                 converter.scanner.setSource(this.rawSource);
1001
1002                 AST ast = AST.newAST(this.apiLevel);
1003                 ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
1004                 ast.setBindingResolver(new BindingResolver());
1005                 if (this.statementsRecovery) {
1006                         ast.setFlag(ICompilationUnit.ENABLE_STATEMENTS_RECOVERY);
1007                 }
1008                 converter.setAST(ast);
1009                 CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil();
1010                 CompilationUnit compilationUnit = ast.newCompilationUnit();
1011                 if (this.sourceLength == -1) {
1012                         this.sourceLength = this.rawSource.length;
1013                 }
1014                 switch(this.astKind) {
1015                         case K_STATEMENTS :
1016                                 ConstructorDeclaration constructorDeclaration = codeSnippetParsingUtil.parseStatements(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true, this.statementsRecovery);
1017                                 RecoveryScannerData data = constructorDeclaration.compilationResult.recoveryScannerData;
1018                                 if(data != null) {
1019                                         Scanner scanner = converter.scanner;
1020                                         converter.scanner = new RecoveryScanner(scanner, data.removeUnused());
1021                                         converter.docParser.scanner = converter.scanner;
1022                                         converter.scanner.setSource(scanner.source);
1023                                 }
1024                                 RecordedParsingInformation recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
1025                                 int[][] comments = recordedParsingInformation.commentPositions;
1026                                 if (comments != null) {
1027                                         converter.buildCommentsTable(compilationUnit, comments);
1028                                 }
1029                                 compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
1030                                 Block block = ast.newBlock();
1031                                 block.setSourceRange(this.sourceOffset, this.sourceOffset + this.sourceLength);
1032                                 net.sourceforge.phpdt.internal.compiler.ast.Statement[] statements = constructorDeclaration.statements;
1033                                 if (statements != null) {
1034                                         int statementsLength = statements.length;
1035                                         for (int i = 0; i < statementsLength; i++) {
1036                                                 if (statements[i] instanceof net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) {
1037                                                         converter.checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
1038                                                 } else {
1039                                                         Statement statement = converter.convert(statements[i]);
1040                                                         if (statement != null) {
1041                                                                 block.statements().add(statement);
1042                                                         }
1043                                                 }
1044                                         }
1045                                 }
1046                                 rootNodeToCompilationUnit(ast, compilationUnit, block, recordedParsingInformation, data);
1047                                 ast.setDefaultNodeFlag(0);
1048                                 ast.setOriginalModificationCount(ast.modificationCount());
1049                                 return block;
1050                         case K_EXPRESSION :
1051                                 net.sourceforge.phpdt.internal.compiler.ast.Expression expression = codeSnippetParsingUtil.parseExpression(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true);
1052                                 recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
1053                                 comments = recordedParsingInformation.commentPositions;
1054                                 if (comments != null) {
1055                                         converter.buildCommentsTable(compilationUnit, comments);
1056                                 }
1057                                 compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
1058                                 if (expression != null) {
1059                                         Expression expression2 = converter.convert(expression);
1060                                         rootNodeToCompilationUnit(expression2.getAST(), compilationUnit, expression2, codeSnippetParsingUtil.recordedParsingInformation, null);
1061                                         ast.setDefaultNodeFlag(0);
1062                                         ast.setOriginalModificationCount(ast.modificationCount());
1063                                         return expression2;
1064                                 } else {
1065                                         CategorizedProblem[] problems = recordedParsingInformation.problems;
1066                                         if (problems != null) {
1067                                                 compilationUnit.setProblems(problems);
1068                                         }
1069                                         ast.setDefaultNodeFlag(0);
1070                                         ast.setOriginalModificationCount(ast.modificationCount());
1071                                         return compilationUnit;
1072                                 }
1073                         case K_CLASS_BODY_DECLARATIONS :
1074                                 final net.sourceforge.phpdt.internal.compiler.ast.ASTNode[] nodes = codeSnippetParsingUtil.parseClassBodyDeclarations(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true);
1075                                 recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
1076                                 comments = recordedParsingInformation.commentPositions;
1077                                 if (comments != null) {
1078                                         converter.buildCommentsTable(compilationUnit, comments);
1079                                 }
1080                                 compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
1081                                 if (nodes != null) {
1082                                         TypeDeclaration typeDeclaration = converter.convert(nodes);
1083                                         typeDeclaration.setSourceRange(this.sourceOffset, this.sourceOffset + this.sourceLength);
1084                                         rootNodeToCompilationUnit(typeDeclaration.getAST(), compilationUnit, typeDeclaration, codeSnippetParsingUtil.recordedParsingInformation, null);
1085                                         ast.setDefaultNodeFlag(0);
1086                                         ast.setOriginalModificationCount(ast.modificationCount());
1087                                         return typeDeclaration;
1088                                 } else {
1089                                         CategorizedProblem[] problems = recordedParsingInformation.problems;
1090                                         if (problems != null) {
1091                                                 compilationUnit.setProblems(problems);
1092                                         }
1093                                         ast.setDefaultNodeFlag(0);
1094                                         ast.setOriginalModificationCount(ast.modificationCount());
1095                                         return compilationUnit;
1096                                 }
1097                 }
1098                 throw new IllegalStateException();
1099         }
1100
1101         private void propagateErrors(ASTNode astNode, CategorizedProblem[] problems, RecoveryScannerData data) {
1102                 astNode.accept(new ASTSyntaxErrorPropagator(problems));
1103                 if (data != null) {
1104                         astNode.accept(new ASTRecoveryPropagator(problems, data));
1105                 }
1106         }
1107
1108         private void rootNodeToCompilationUnit(AST ast, CompilationUnit compilationUnit, ASTNode node, RecordedParsingInformation recordedParsingInformation, RecoveryScannerData data) {
1109                 final int problemsCount = recordedParsingInformation.problemsCount;
1110                 switch(node.getNodeType()) {
1111                         case ASTNode.BLOCK :
1112                                 {
1113                                         Block block = (Block) node;
1114                                         if (problemsCount != 0) {
1115                                                 // propagate and record problems
1116                                                 final CategorizedProblem[] problems = recordedParsingInformation.problems;
1117                                                 propagateErrors(block, problems, data);
1118                                                 compilationUnit.setProblems(problems);
1119                                         }
1120                                         TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
1121                                         Initializer initializer = ast.newInitializer();
1122                                         initializer.setBody(block);
1123                                         typeDeclaration.bodyDeclarations().add(initializer);
1124                                         compilationUnit.types().add(typeDeclaration);
1125                                 }
1126                                 break;
1127                         case ASTNode.TYPE_DECLARATION :
1128                                 {
1129                                         TypeDeclaration typeDeclaration = (TypeDeclaration) node;
1130                                         if (problemsCount != 0) {
1131                                                 // propagate and record problems
1132                                                 final CategorizedProblem[] problems = recordedParsingInformation.problems;
1133                                                 propagateErrors(typeDeclaration, problems, data);
1134                                                 compilationUnit.setProblems(problems);
1135                                         }
1136                                         compilationUnit.types().add(typeDeclaration);
1137                                 }
1138                                 break;
1139                         default :
1140                                 if (node instanceof Expression) {
1141                                         Expression expression = (Expression) node;
1142                                         if (problemsCount != 0) {
1143                                                 // propagate and record problems
1144                                                 final CategorizedProblem[] problems = recordedParsingInformation.problems;
1145                                                 propagateErrors(expression, problems, data);
1146                                                 compilationUnit.setProblems(problems);
1147                                         }
1148                                         ExpressionStatement expressionStatement = ast.newExpressionStatement(expression);
1149                                         Block block = ast.newBlock();
1150                                         block.statements().add(expressionStatement);
1151                                         Initializer initializer = ast.newInitializer();
1152                                         initializer.setBody(block);
1153                                         TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
1154                                         typeDeclaration.bodyDeclarations().add(initializer);
1155                                         compilationUnit.types().add(typeDeclaration);
1156                                 }
1157                 }
1158         }
1159 }