org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTParser.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.89 - (view) (download)

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