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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.85 - (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.75 * Request for a bindings recovery. Defaults to <code>false</code>.
153 :     */
154 :     private boolean bindingsRecovery;
155 :    
156 :     /**
157 : jdesrivieres 1.2 * 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 : oliviert 1.73 * Source string.
164 : jdesrivieres 1.2 */
165 :     private char[] rawSource = null;
166 : oliviert 1.73
167 : jdesrivieres 1.2 /**
168 : ffusier 1.69 * Java model class file or compilation unit supplying the source.
169 : jdesrivieres 1.2 */
170 : ffusier 1.69 private ITypeRoot typeRoot = null;
171 : oliviert 1.73
172 : jdesrivieres 1.2 /**
173 :     * Character-based offset into the source string where parsing is to
174 :     * begin. Defaults to 0.
175 :     */
176 :     private int sourceOffset = 0;
177 : oliviert 1.73
178 : jdesrivieres 1.2 /**
179 :     * Character-based length limit, or -1 if unlimited.
180 :     * All characters in the source string between <code>offset</code>
181 : oliviert 1.73 * and <code>offset+length-1</code> inclusive are parsed. Defaults to -1,
182 : jdesrivieres 1.2 * 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 : oliviert 1.73
191 : jdesrivieres 1.2 /**
192 :     * Java project used to resolve names, or <code>null</code> if none.
193 :     * Defaults to none.
194 :     */
195 :     private IJavaProject project = null;
196 : oliviert 1.73
197 : jdesrivieres 1.2 /**
198 : oliviert 1.73 * Name of the compilation unit for resolving bindings, or
199 : jdesrivieres 1.2 * <code>null</code> if none. Defaults to none.
200 :     */
201 : oliviert 1.73 private String unitName = null;
202 : jdesrivieres 1.2
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 : oliviert 1.73 *
209 : jdesrivieres 1.2 * @param level the API level; one of the LEVEL constants
210 :     * declared on <code>AST</code>
211 :     */
212 :     ASTParser(int level) {
213 : oliviert 1.40 if ((level != AST.JLS2_INTERNAL)
214 : jdesrivieres 1.14 && (level != AST.JLS3)) {
215 : jdesrivieres 1.3 throw new IllegalArgumentException();
216 :     }
217 : othomann 1.5 this.apiLevel = level;
218 : jdesrivieres 1.2 initializeDefaults();
219 :     }
220 :    
221 :     /**
222 :     * Sets all the setting to their default values.
223 :     */
224 :     private void initializeDefaults() {
225 : jeromel 1.56 this.astKind = K_COMPILATION_UNIT;
226 :     this.rawSource = null;
227 : ffusier 1.69 this.typeRoot = null;
228 : jeromel 1.56 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 : jdesrivieres 1.2 }
239 : oliviert 1.73
240 : oliviert 1.75 /**
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 : jdesrivieres 1.2 /**
259 :     * Sets the compiler options to be used when parsing.
260 : oliviert 1.44 * <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 : oliviert 1.73 *
279 : jdesrivieres 1.2 * @param options the table of options (key type: <code>String</code>;
280 :     * value type: <code>String</code>), or <code>null</code>
281 : oliviert 1.44 * to set it back to the default
282 : jdesrivieres 1.2 */
283 :     public void setCompilerOptions(Map options) {
284 : jeromel 1.57 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 : jdesrivieres 1.2 }
293 : oliviert 1.73
294 : jdesrivieres 1.2 /**
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 : oliviert 1.73 * by calling the <code>resolveBinding</code> methods. These bindings
304 :     * draw connections between the different parts of a program, and
305 : jdesrivieres 1.2 * generally afford a more powerful vantage point for clients who wish to
306 : oliviert 1.73 * analyze a program's structure more deeply. These bindings come at a
307 : jdesrivieres 1.2 * considerable cost in both time and space, however, and should not be
308 : oliviert 1.73 * requested frivolously. The additional space is not reclaimed until the
309 : jdesrivieres 1.2 * 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 : oliviert 1.73 * 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 : jdesrivieres 1.2 * outset.
320 :     * </p>
321 :     * <p>
322 :     * When bindings are requested, instead of considering compilation units on disk only
323 : oliviert 1.73 * one can supply a <code>WorkingCopyOwner</code>. Working copies owned
324 : jdesrivieres 1.2 * 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 : jdesrivieres 1.12 * 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 : oliviert 1.73 * the location must be extablished explicitly by calling
335 : jdesrivieres 1.12 * {@link #setProject(IJavaProject)} and {@link #setUnitName(String)}.
336 : jdesrivieres 1.2 * 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 : oliviert 1.73 *
340 :     * @param bindings <code>true</code> if bindings are wanted,
341 : jdesrivieres 1.2 * and <code>false</code> if bindings are not of interest
342 :     */
343 :     public void setResolveBindings(boolean bindings) {
344 :     this.resolveBindings = bindings;
345 :     }
346 : oliviert 1.73
347 : jdesrivieres 1.2 /**
348 : oliviert 1.73 * Requests an abridged abstract syntax tree.
349 : jdesrivieres 1.2 * By default, complete ASTs are returned.
350 : mdaniel 1.65 * <p>
351 : jdesrivieres 1.2 * 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 : jdesrivieres 1.7 * being smaller and faster to construct.
357 : jdesrivieres 1.2 * </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 : oliviert 1.73 * its statements, including any local or anonymous type declarations
373 : jdesrivieres 1.2 * 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 : oliviert 1.73 *
381 : jdesrivieres 1.2 * @param position a position into the corresponding body declaration
382 :     */
383 : jdesrivieres 1.3 public void setFocalPosition(int position) {
384 : jdesrivieres 1.2 this.partial = true;
385 :     this.focalPointPosition = position;
386 :     }
387 : oliviert 1.73
388 : jdesrivieres 1.2 /**
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 : oliviert 1.41 * <li>{@link #K_COMPILATION_UNIT K_COMPILATION_UNIT}: The result node
396 : jdesrivieres 1.2 * is a {@link CompilationUnit}.</li>
397 : oliviert 1.41 * <li>{@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
398 : jdesrivieres 1.2 * 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 : oliviert 1.41 * <li>{@link #K_STATEMENTS K_STATEMENTS}: The result node is a
402 : jdesrivieres 1.2 * {@link Block Block} whose {@link Block#statements() statements}
403 :     * are the new trees. Other aspects of the block are unspecified.</li>
404 : oliviert 1.41 * <li>{@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
405 : jdesrivieres 1.2 * {@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 : oliviert 1.73 * client to retrieve the following pieces of information
410 : jdesrivieres 1.2 * available there:
411 :     * <ul>
412 : jeromel 1.47 * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
413 : jdesrivieres 1.2 * 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 : oliviert 1.73 * Character positions are relative to the start of
418 : jdesrivieres 1.2 * <code>source</code>; line positions are for the subrange scanned.</li>
419 : jdesrivieres 1.4 * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
420 : jdesrivieres 1.2 * 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 : oliviert 1.73 * recognize the input, this method returns
431 : jdesrivieres 1.2 * a {@link CompilationUnit CompilationUnit} node with at least the
432 :     * compiler messages.
433 :     * </p>
434 : oliviert 1.73 * <p>Each node in the subtree (other than the contrived nodes)
435 : jdesrivieres 1.2 * carries source range(s) information relating back
436 :     * to positions in the given source (the given source itself
437 : oliviert 1.73 * is not remembered with the AST).
438 :     * The source range usually begins at the first character of the first token
439 : jdesrivieres 1.2 * 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 : oliviert 1.73 * Binding information is only computed when <code>kind</code> is
451 : jdesrivieres 1.2 * <code>K_COMPILATION_UNIT</code>.
452 :     * </p>
453 : oliviert 1.73 *
454 :     * @param kind the kind of construct to parse: one of
455 : jdesrivieres 1.2 * {@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 : oliviert 1.73
470 : jdesrivieres 1.2 /**
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 : ffusier 1.69 // clear the type root
479 :     this.typeRoot = null;
480 : jdesrivieres 1.2 }
481 :    
482 :     /**
483 :     * Sets the source code to be parsed.
484 : jdesrivieres 1.6 * 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 : jdesrivieres 1.2 *
488 :     * @param source the Java model compilation unit whose source code
489 :     * is to be parsed, or <code>null</code> if none
490 : jdesrivieres 1.6 */
491 : jdesrivieres 1.2 public void setSource(ICompilationUnit source) {
492 : ffusier 1.72 setSource((ITypeRoot)source);
493 : jdesrivieres 1.2 }
494 : oliviert 1.73
495 : jdesrivieres 1.2 /**
496 :     * Sets the source code to be parsed.
497 : oliviert 1.58 * <p>This method automatically sets the project (and compiler
498 : jdesrivieres 1.6 * options) based on the given compilation unit, in a manner
499 : oliviert 1.58 * equivalent to <code>setProject(source.getJavaProject())</code>.</p>
500 : oliviert 1.73 * <p>If the given class file has no source attachment, the creation of the
501 : oliviert 1.58 * ast will fail with an IllegalStateException.</p>
502 : jdesrivieres 1.2 *
503 : oliviert 1.60 * @param source the Java model class file whose corresponding source code
504 : jdesrivieres 1.2 * is to be parsed, or <code>null</code> if none
505 :     */
506 : oliviert 1.60 public void setSource(IClassFile source) {
507 : ffusier 1.72 setSource((ITypeRoot)source);
508 : ffusier 1.69 }
509 :    
510 : ffusier 1.70 /**
511 : ffusier 1.69 * Sets the source code to be parsed.
512 : ffusier 1.70 * <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 : oliviert 1.73 * <p>If the source is a class file without source attachment, the creation of the
516 : ffusier 1.70 * 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 : ffusier 1.69 */
522 : ffusier 1.71 public void setSource(ITypeRoot source) {
523 : ffusier 1.69 this.typeRoot = source;
524 :     // clear the raw source
525 : jdesrivieres 1.2 this.rawSource = null;
526 : oliviert 1.60 if (source != null) {
527 :     this.project = source.getJavaProject();
528 : jeromel 1.56 Map options = this.project.getOptions(true);
529 :     options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
530 :     this.compilerOptions = options;
531 : othomann 1.5 }
532 : jdesrivieres 1.2 }
533 : oliviert 1.73
534 : jdesrivieres 1.2 /**
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 : oliviert 1.83 * the remainder of the source string is to be parsed
542 : jdesrivieres 1.2 */
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 : oliviert 1.73
551 : daudel 1.50 /**
552 :     * Requests that the compiler should perform statements recovery.
553 : daudel 1.51 * When statements recovery is enabled the compiler tries to create statement nodes
554 : daudel 1.50 * from code containing syntax errors
555 :     * <p>
556 :     * Default to <code>false</code>.
557 :     * </p>
558 : oliviert 1.73 *
559 :     * @param enabled <code>true</code> if statements containing syntax errors are wanted,
560 : daudel 1.50 * and <code>false</code> if these statements aren't wanted.
561 : oliviert 1.73 *
562 : daudel 1.50 * @since 3.2
563 :     */
564 :     public void setStatementsRecovery(boolean enabled) {
565 :     this.statementsRecovery = enabled;
566 :     }
567 : oliviert 1.73
568 : jdesrivieres 1.2 /**
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 : oliviert 1.73 * @param owner the owner of working copies that take precedence over underlying
573 : jdesrivieres 1.2 * 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 : oliviert 1.62 * 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 : jdesrivieres 1.2 * Defaults to none (<code>null</code>).
588 :     * <p>
589 :     * The name of the compilation unit must be supplied for resolving bindings.
590 : oliviert 1.73 * This name should be suffixed by a dot ('.') followed by one of the
591 :     * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}
592 : oliviert 1.62 * and match the name of the main (public) class or interface declared in the source.</p>
593 : oliviert 1.73 *
594 : oliviert 1.62 * <p>This name must represent the full path of the unit inside the given project. For example, if the source
595 : ffusier 1.82 * declares a public class named "Foo" in a project "P" where the source folder is the project itself, the name
596 :     * of the compilation unit must be "/P/Foo.java".
597 : 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",
598 :     * the name of the compilation unit must be "/P/src/p1/p2/Bar.java".</p>
599 : jdesrivieres 1.2 *
600 :     * @param unitName the name of the compilation unit that would contain the source
601 :     * string, or <code>null</code> if none
602 :     */
603 :     public void setUnitName(String unitName) {
604 :     this.unitName = unitName;
605 :     }
606 : oliviert 1.73
607 : jdesrivieres 1.2 /**
608 : oliviert 1.44 * Sets the Java project used when resolving bindings.
609 :     * This method automatically sets the compiler
610 :     * options based on the given project:
611 :     * <pre>
612 :     * setCompilerOptions(project.getOptions(true));
613 :     * </pre>
614 :     * See {@link #setCompilerOptions(Map)} for a discussion of
615 : oliviert 1.73 * the pros and cons of using these options vs specifying
616 : oliviert 1.44 * compiler options explicitly.
617 :     * This setting is used in conjunction with <code>setSource(char[])</code>.
618 :     * For the purposes of resolving bindings, types declared in the
619 : jdesrivieres 1.2 * source string will hide types by the same name available
620 : oliviert 1.44 * through the classpath of the given project.
621 :     * Defaults to none (<code>null</code>).
622 : oliviert 1.73 *
623 :     * @param project the Java project used to resolve names, or
624 : jdesrivieres 1.2 * <code>null</code> if none
625 : oliviert 1.44 */
626 : jdesrivieres 1.2 public void setProject(IJavaProject project) {
627 :     this.project = project;
628 : othomann 1.5 if (project != null) {
629 : jeromel 1.56 Map options = project.getOptions(true);
630 :     options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
631 :     this.compilerOptions = options;
632 : othomann 1.5 }
633 : jdesrivieres 1.2 }
634 : oliviert 1.73
635 : jdesrivieres 1.2 /**
636 :     * Creates an abstract syntax tree.
637 :     * <p>
638 : jdesrivieres 1.3 * A successful call to this method returns all settings to their
639 : jdesrivieres 1.2 * default values so the object is ready to be reused.
640 :     * </p>
641 : oliviert 1.73 *
642 : jdesrivieres 1.2 * @param monitor the progress monitor used to report progress and request cancelation,
643 :     * or <code>null</code> if none
644 :     * @return an AST node whose type depends on the kind of parse
645 :     * requested, with a fallback to a <code>CompilationUnit</code>
646 :     * in the case of severe parsing errors
647 : jdesrivieres 1.3 * @exception IllegalStateException if the settings provided
648 :     * are insufficient, contradictory, or otherwise unsupported
649 : jdesrivieres 1.2 */
650 :     public ASTNode createAST(IProgressMonitor monitor) {
651 : othomann 1.5 ASTNode result = null;
652 : oliviert 1.54 if (monitor != null) monitor.beginTask("", 1); //$NON-NLS-1$
653 : othomann 1.5 try {
654 : ffusier 1.69 if (this.rawSource == null && this.typeRoot == null) {
655 : othomann 1.5 throw new IllegalStateException("source not specified"); //$NON-NLS-1$
656 :     }
657 :     result = internalCreateAST(monitor);
658 :     } finally {
659 :     // re-init defaults to allow reuse (and avoid leaking)
660 :     initializeDefaults();
661 : oliviert 1.54 if (monitor != null) monitor.done();
662 : othomann 1.5 }
663 : jdesrivieres 1.2 return result;
664 :     }
665 : oliviert 1.73
666 : jlanneluc 1.23 /**
667 : jeem 1.33 * Creates ASTs for a batch of compilation units.
668 : jeem 1.31 * When bindings are being resolved, processing a
669 : jdesrivieres 1.25 * batch of compilation units is more efficient because much
670 :     * of the work involved in resolving bindings can be shared.
671 :     * <p>
672 : jeem 1.31 * When bindings are being resolved, all compilation units must
673 :     * come from the same Java project, which must be set beforehand
674 :     * with <code>setProject</code>.
675 :     * The compilation units are processed one at a time in no
676 :     * specified order. For each of the compilation units in turn,
677 :     * <ul>
678 :     * <li><code>ASTParser.createAST</code> is called to parse it
679 :     * and create a corresponding AST. The calls to
680 :     * <code>ASTParser.createAST</code> all employ the same settings.</li>
681 :     * <li><code>ASTRequestor.acceptAST</code> is called passing
682 : oliviert 1.73 * the compilation unit and the corresponding AST to
683 : jeem 1.31 * <code>requestor</code>.
684 :     * </li>
685 : oliviert 1.73 * </ul>
686 : jeem 1.31 * Note only ASTs from the given compilation units are reported
687 :     * to the requestor. If additional compilation units are required to
688 :     * resolve the original ones, the corresponding ASTs are <b>not</b>
689 :     * reported to the requestor.
690 :     * </p>
691 : jeem 1.33 * <p>
692 :     * Note also the following parser parameters are used, regardless of what
693 :     * may have been specified:
694 :     * <ul>
695 :     * <li>The {@linkplain #setKind(int) parser kind} is <code>K_COMPILATION_UNIT</code></li>
696 :     * <li>The {@linkplain #setSourceRange(int,int) source range} is <code>(0, -1)</code></li>
697 :     * <li>The {@linkplain #setFocalPosition(int) focal position} is not set</li>
698 :     * </ul>
699 :     * </p>
700 : jeem 1.31 * <p>
701 :     * The <code>bindingKeys</code> parameter specifies bindings keys
702 : jeem 1.33 * ({@link IBinding#getKey()}) that are to be looked up. These keys may
703 :     * be for elements either inside or outside the set of compilation
704 :     * units being processed. When bindings are being resolved,
705 :     * the keys and corresponding bindings (or <code>null</code> if none) are
706 :     * passed to <code>ASTRequestor.acceptBinding</code>. Note that binding keys
707 : oliviert 1.73 * for elements outside the set of compilation units being processed are looked up
708 :     * after all <code>ASTRequestor.acceptAST</code> callbacks have been made.
709 : jeromel 1.37 * Binding keys for elements inside the set of compilation units being processed
710 : oliviert 1.73 * are looked up and reported right after the corresponding
711 : jeromel 1.37 * <code>ASTRequestor.acceptAST</code> callback has been made.
712 : oliviert 1.73 * No <code>ASTRequestor.acceptBinding</code> callbacks are made unless
713 : jeromel 1.37 * bindings are being resolved.
714 : jdesrivieres 1.25 * </p>
715 : jlanneluc 1.23 * <p>
716 :     * A successful call to this method returns all settings to their
717 :     * default values so the object is ready to be reused.
718 : jeem 1.31 * </p>
719 : oliviert 1.73 *
720 : jeromel 1.30 * @param compilationUnits the compilation units to create ASTs for
721 :     * @param bindingKeys the binding keys to create bindings for
722 : oliviert 1.84 * @param requestor the AST requestor that collects abstract syntax trees and bindings
723 :     * @param monitor the progress monitor used to report progress and request cancellation,
724 : jlanneluc 1.23 * or <code>null</code> if none
725 :     * @exception IllegalStateException if the settings provided
726 :     * are insufficient, contradictory, or otherwise unsupported
727 :     * @since 3.1
728 :     */
729 : jeromel 1.30 public void createASTs(ICompilationUnit[] compilationUnits, String[] bindingKeys, ASTRequestor requestor, IProgressMonitor monitor) {
730 : jlanneluc 1.23 try {
731 : oliviert 1.75 int flags = 0;
732 :     if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
733 : jlanneluc 1.23 if (this.resolveBindings) {
734 :     if (this.project == null)
735 :     throw new IllegalStateException("project not specified"); //$NON-NLS-1$
736 : oliviert 1.75 if (this.bindingsRecovery) flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
737 :     CompilationUnitResolver.resolve(compilationUnits, bindingKeys, requestor, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner, flags, monitor);
738 : jlanneluc 1.23 } else {
739 : oliviert 1.75 CompilationUnitResolver.parse(compilationUnits, requestor, this.apiLevel, this.compilerOptions, flags, monitor);
740 : jlanneluc 1.23 }
741 : jeromel 1.36 } finally {
742 : oliviert 1.75 // re-init defaults to allow reuse (and avoid leaking)
743 :     initializeDefaults();
744 : jeromel 1.36 }
745 :     }
746 : oliviert 1.73
747 : jeromel 1.36 /**
748 : oliviert 1.83 * Creates bindings for a batch of Java elements. These elements are either
749 :     * enclosed in {@link ICompilationUnit}s or in {@link IClassFile}s.
750 :     * <p>
751 :     * All enclosing compilation units and class files must
752 :     * come from the same Java project, which must be set beforehand
753 :     * with <code>setProject</code>.
754 :     * </p>
755 :     * <p>
756 :     * All elements must exist. If one doesn't exist, an <code>IllegalStateException</code>
757 :     * is thrown.
758 :     * </p>
759 :     * <p>
760 :     * The returned array has the same size as the given elements array. At a given position
761 :     * it contains the binding of the corresponding Java element, or <code>null</code>
762 :     * if no binding could be created.
763 :     * </p>
764 : jeromel 1.36 * <p>
765 :     * Note also the following parser parameters are used, regardless of what
766 :     * may have been specified:
767 :     * <ul>
768 : mdaniel 1.65 * <li>The {@linkplain #setResolveBindings(boolean) binding resolution flag} is <code>true</code></li>
769 : jeromel 1.36 * <li>The {@linkplain #setKind(int) parser kind} is <code>K_COMPILATION_UNIT</code></li>
770 :     * <li>The {@linkplain #setSourceRange(int,int) source range} is <code>(0, -1)</code></li>
771 :     * <li>The {@linkplain #setFocalPosition(int) focal position} is not set</li>
772 :     * </ul>
773 :     * </p>
774 : oliviert 1.83 * <p>
775 :     * A successful call to this method returns all settings to their
776 :     * default values so the object is ready to be reused.
777 :     * </p>
778 :     *
779 :     * @param elements the Java elements to create bindings for
780 :     * @return the bindings for the given Java elements, possibly containing <code>null</code>s
781 :     * if some bindings could not be created
782 : jeromel 1.36 * @exception IllegalStateException if the settings provided
783 :     * are insufficient, contradictory, or otherwise unsupported
784 :     * @since 3.1
785 : oliviert 1.83 */
786 : jeromel 1.36 public IBinding[] createBindings(IJavaElement[] elements, IProgressMonitor monitor) {
787 :     try {
788 :     if (this.project == null)
789 :     throw new IllegalStateException("project not specified"); //$NON-NLS-1$
790 : oliviert 1.75 int flags = 0;
791 :     if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
792 :     if (this.bindingsRecovery) flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
793 :     return CompilationUnitResolver.resolve(elements, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner, flags, monitor);
794 : jlanneluc 1.23 } finally {
795 : oliviert 1.75 // re-init defaults to allow reuse (and avoid leaking)
796 :     initializeDefaults();
797 : jlanneluc 1.23 }
798 :     }
799 : oliviert 1.73
800 : othomann 1.5 private ASTNode internalCreateAST(IProgressMonitor monitor) {
801 :     boolean needToResolveBindings = this.resolveBindings;
802 :     switch(this.astKind) {
803 :     case K_CLASS_BODY_DECLARATIONS :
804 :     case K_EXPRESSION :
805 :     case K_STATEMENTS :
806 : oliviert 1.83 if (this.rawSource == null) {
807 :     if (this.typeRoot != null) {
808 :     // get the source from the type root
809 :     if (this.typeRoot instanceof ICompilationUnit) {
810 :     org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) this.typeRoot;
811 :     this.rawSource = sourceUnit.getContents();
812 :     } else if (this.typeRoot instanceof IClassFile) {
813 :     try {
814 :     String sourceString = this.typeRoot.getSource();
815 :     if (sourceString != null) {
816 :     this.rawSource = sourceString.toCharArray();
817 :     }
818 :     } catch(JavaModelException e) {
819 :     // an error occured accessing the java element
820 :     StringWriter stringWriter = new StringWriter();
821 :     PrintWriter writer = null;
822 :     try {
823 :     writer = new PrintWriter(stringWriter);
824 :     e.printStackTrace(writer);
825 :     } finally {
826 :     if (writer != null) writer.close();
827 :     }
828 :     throw new IllegalStateException(String.valueOf(stringWriter.getBuffer()));
829 :     }
830 :     }
831 :     }
832 :     }
833 : othomann 1.5 if (this.rawSource != null) {
834 :     if (this.sourceOffset + this.sourceLength > this.rawSource.length) {
835 : oliviert 1.83 throw new IllegalStateException();
836 : othomann 1.5 }
837 :     return internalCreateASTForKind();
838 :     }
839 :     break;
840 :     case K_COMPILATION_UNIT :
841 :     CompilationUnitDeclaration compilationUnitDeclaration = null;
842 :     try {
843 :     NodeSearcher searcher = null;
844 : jlanneluc 1.23 org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = null;
845 : ffusier 1.69 WorkingCopyOwner wcOwner = this.workingCopyOwner;
846 :     if (this.typeRoot instanceof ICompilationUnit) {
847 :     /*
848 :     * this.compilationUnitSource is an instance of org.eclipse.jdt.internal.core.CompilationUnit that implements
849 :     * both org.eclipse.jdt.core.ICompilationUnit and org.eclipse.jdt.internal.compiler.env.ICompilationUnit
850 : oliviert 1.73 */
851 : ffusier 1.69 sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) this.typeRoot;
852 :     /*
853 :     * use a BasicCompilation that caches the source instead of using the compilationUnitSource directly
854 :     * (if it is a working copy, the source can change between the parse and the AST convertion)
855 :     * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75632)
856 :     */
857 :     sourceUnit = new BasicCompilationUnit(sourceUnit.getContents(), sourceUnit.getPackageName(), new String(sourceUnit.getFileName()), this.project);
858 :     wcOwner = ((ICompilationUnit) this.typeRoot).getOwner();
859 :     } else if (this.typeRoot instanceof IClassFile) {
860 : othomann 1.5 try {
861 : ffusier 1.69 String sourceString = this.typeRoot.getSource();
862 : jlanneluc 1.23 if (sourceString == null) {
863 :     throw new IllegalStateException();
864 :     }
865 : ffusier 1.69 PackageFragment packageFragment = (PackageFragment) this.typeRoot.getParent();
866 :     BinaryType type = (BinaryType) this.typeRoot.findPrimaryType();
867 : jlanneluc 1.21 IBinaryType binaryType = (IBinaryType) type.getElementInfo();
868 : jeromel 1.45 // file name is used to recreate the Java element, so it has to be the toplevel .class file name
869 :     char[] fileName = binaryType.getFileName();
870 :     int firstDollar = CharOperation.indexOf('$', fileName);
871 :     if (firstDollar != -1) {
872 :     char[] suffix = SuffixConstants.SUFFIX_class;
873 :     int suffixLength = suffix.length;
874 :     char[] newFileName = new char[firstDollar + suffixLength];
875 :     System.arraycopy(fileName, 0, newFileName, 0, firstDollar);
876 :     System.arraycopy(suffix, 0, newFileName, firstDollar, suffixLength);
877 :     fileName = newFileName;
878 :     }
879 :     sourceUnit = new BasicCompilationUnit(sourceString.toCharArray(), Util.toCharArrays(packageFragment.names), new String(fileName), this.project);
880 : othomann 1.5 } catch(JavaModelException e) {
881 : oliviert 1.34 // an error occured accessing the java element
882 : oliviert 1.78 StringWriter stringWriter = new StringWriter();
883 :     PrintWriter writer = null;
884 :     try {
885 :     writer = new PrintWriter(stringWriter);
886 :     e.printStackTrace(writer);
887 :     } finally {
888 :     if (writer != null) writer.close();
889 :     }
890 :     throw new IllegalStateException(String.valueOf(stringWriter.getBuffer()));
891 : othomann 1.5 }
892 :     } else if (this.rawSource != null) {
893 : oliviert 1.48 needToResolveBindings = this.resolveBindings && this.unitName != null && this.project != null && this.compilerOptions != null;
894 : jlanneluc 1.23 sourceUnit = new BasicCompilationUnit(this.rawSource, null, this.unitName == null ? "" : this.unitName, this.project); //$NON-NLS-1$
895 :     } else {
896 : othomann 1.5 throw new IllegalStateException();
897 :     }
898 :     if (this.partial) {
899 :     searcher = new NodeSearcher(this.focalPointPosition);
900 :     }
901 : oliviert 1.75 int flags = 0;
902 :     if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
903 : oliviert 1.48 if (needToResolveBindings) {
904 : oliviert 1.75 if (this.bindingsRecovery) flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
905 : othomann 1.5 try {
906 :     // parse and resolve
907 : oliviert 1.73 compilationUnitDeclaration =
908 : othomann 1.5 CompilationUnitResolver.resolve(
909 : jlanneluc 1.23 sourceUnit,
910 : othomann 1.5 this.project,
911 :     searcher,
912 : othomann 1.8 this.compilerOptions,
913 : othomann 1.5 this.workingCopyOwner,
914 : oliviert 1.75 flags,
915 : othomann 1.5 monitor);
916 :     } catch (JavaModelException e) {
917 : oliviert 1.75 flags &= ~ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
918 : othomann 1.5 compilationUnitDeclaration = CompilationUnitResolver.parse(
919 : jlanneluc 1.23 sourceUnit,
920 : othomann 1.5 searcher,
921 : daudel 1.50 this.compilerOptions,
922 : oliviert 1.75 flags);
923 : othomann 1.5 needToResolveBindings = false;
924 :     }
925 :     } else {
926 :     compilationUnitDeclaration = CompilationUnitResolver.parse(
927 : jlanneluc 1.23 sourceUnit,
928 : othomann 1.5 searcher,
929 : daudel 1.50 this.compilerOptions,
930 : oliviert 1.75 flags);
931 : othomann 1.5 needToResolveBindings = false;
932 :     }
933 : jeromel 1.39 CompilationUnit result = CompilationUnitResolver.convert(
934 : oliviert 1.73 compilationUnitDeclaration,
935 : ptff 1.27 sourceUnit.getContents(),
936 : oliviert 1.73 this.apiLevel,
937 : jlanneluc 1.23 this.compilerOptions,
938 :     needToResolveBindings,
939 : ffusier 1.69 wcOwner,
940 : oliviert 1.73 needToResolveBindings ? new DefaultBindingResolver.BindingTables() : null,
941 : oliviert 1.75 flags,
942 : jlanneluc 1.23 monitor);
943 : ffusier 1.69 result.setTypeRoot(this.typeRoot);
944 : jeromel 1.39 return result;
945 : othomann 1.5 } finally {
946 :     if (compilationUnitDeclaration != null && this.resolveBindings) {
947 :     compilationUnitDeclaration.cleanUp();
948 :     }
949 : oliviert 1.73 }
950 : jdesrivieres 1.2 }
951 : othomann 1.5 throw new IllegalStateException();
952 :     }
953 : oliviert 1.73
954 : jdesrivieres 1.2 /**
955 :     * Parses the given source between the bounds specified by the given offset (inclusive)
956 :     * and the given length and creates and returns a corresponding abstract syntax tree.
957 :     * <p>
958 :     * When the parse is successful the result returned includes the ASTs for the
959 :     * requested source:
960 :     * <ul>
961 :     * <li>{@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
962 :     * is a {@link TypeDeclaration TypeDeclaration} whose
963 :     * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
964 :     * are the new trees. Other aspects of the type declaration are unspecified.</li>
965 :     * <li>{@link #K_STATEMENTS K_STATEMENTS}: The result node is a
966 :     * {@link Block Block} whose {@link Block#statements() statements}
967 :     * are the new trees. Other aspects of the block are unspecified.</li>
968 :     * <li>{@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
969 :     * {@link Expression Expression}. Other aspects of the expression are unspecified.</li>
970 :     * </ul>
971 :     * The resulting AST node is rooted under an contrived
972 :     * {@link CompilationUnit CompilationUnit} node, to allow the
973 : oliviert 1.73 * client to retrieve the following pieces of information
974 : jdesrivieres 1.2 * available there:
975 :     * <ul>
976 : jeromel 1.47 * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
977 : jdesrivieres 1.2 * numbers start at 1 and only cover the subrange scanned
978 :     * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
979 :     * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
980 :     * and {@linkplain CompilationUnit#getProblems() detailed problem reports}.
981 : oliviert 1.73 * Character positions are relative to the start of
982 : jdesrivieres 1.2 * <code>source</code>; line positions are for the subrange scanned.</li>
983 : jdesrivieres 1.4 * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
984 : jdesrivieres 1.2 * for the subrange scanned.</li>
985 :     * </ul>
986 :     * The contrived nodes do not have source positions. Other aspects of the
987 :     * {@link CompilationUnit CompilationUnit} node are unspecified, including
988 :     * the exact arrangment of intervening nodes.
989 :     * </p>
990 :     * <p>
991 :     * Lexical or syntax errors detected while parsing can result in
992 :     * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
993 :     * In more severe failure cases where the parser is unable to
994 : oliviert 1.73 * recognize the input, this method returns
995 : jdesrivieres 1.2 * a {@link CompilationUnit CompilationUnit} node with at least the
996 :     * compiler messages.
997 :     * </p>
998 : oliviert 1.73 * <p>Each node in the subtree (other than the contrived nodes)
999 : jdesrivieres 1.2 * carries source range(s) information relating back
1000 :     * to positions in the given source (the given source itself
1001 : oliviert 1.73 * is not remembered with the AST).
1002 :     * The source range usually begins at the first character of the first token
1003 : jdesrivieres 1.2 * corresponding to the node; leading whitespace and comments are <b>not</b>
1004 :     * included. The source range usually extends through the last character of
1005 :     * the last token corresponding to the node; trailing whitespace and
1006 :     * comments are <b>not</b> included. There are a handful of exceptions
1007 :     * (including the various body declarations); the
1008 :     * specification for these node type spells out the details.
1009 :     * Source ranges nest properly: the source range for a child is always
1010 :     * within the source range of its parent, and the source ranges of sibling
1011 :     * nodes never overlap.
1012 :     * </p>
1013 :     * <p>
1014 :     * This method does not compute binding information; all <code>resolveBinding</code>
1015 :     * methods applied to nodes of the resulting AST return <code>null</code>.
1016 :     * </p>
1017 : oliviert 1.73 *
1018 : jdesrivieres 1.2 * @return an AST node whose type depends on the kind of parse
1019 :     * requested, with a fallback to a <code>CompilationUnit</code>
1020 :     * in the case of severe parsing errors
1021 :     * @see ASTNode#getStartPosition()
1022 :     * @see ASTNode#getLength()
1023 :     */
1024 : othomann 1.5 private ASTNode internalCreateASTForKind() {
1025 : oliviert 1.42 final ASTConverter converter = new ASTConverter(this.compilerOptions, false, null);
1026 : othomann 1.5 converter.compilationUnitSource = this.rawSource;
1027 : oliviert 1.42 converter.compilationUnitSourceLength = this.rawSource.length;
1028 : othomann 1.5 converter.scanner.setSource(this.rawSource);
1029 : oliviert 1.73
1030 : othomann 1.5 AST ast = AST.newAST(this.apiLevel);
1031 : daudel 1.9 ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
1032 : jdesrivieres 1.2 ast.setBindingResolver(new BindingResolver());
1033 : oliviert 1.75 if (this.statementsRecovery) {
1034 :     ast.setFlag(ICompilationUnit.ENABLE_STATEMENTS_RECOVERY);
1035 :     }
1036 : jdesrivieres 1.2 converter.setAST(ast);
1037 :     CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil();
1038 :     CompilationUnit compilationUnit = ast.newCompilationUnit();
1039 : othomann 1.17 if (this.sourceLength == -1) {
1040 :     this.sourceLength = this.rawSource.length;
1041 :     }
1042 : othomann 1.5 switch(this.astKind) {
1043 : jdesrivieres 1.2 case K_STATEMENTS :
1044 : oliviert 1.67 ConstructorDeclaration constructorDeclaration = codeSnippetParsingUtil.parseStatements(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true, this.statementsRecovery);
1045 : daudel 1.49 RecoveryScannerData data = constructorDeclaration.compilationResult.recoveryScannerData;
1046 :     if(data != null) {
1047 :     Scanner scanner = converter.scanner;
1048 :     converter.scanner = new RecoveryScanner(scanner, data.removeUnused());
1049 :     converter.docParser.scanner = converter.scanner;
1050 :     converter.scanner.setSource(scanner.source);
1051 :     }
1052 : jdesrivieres 1.2 RecordedParsingInformation recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
1053 :     int[][] comments = recordedParsingInformation.commentPositions;
1054 :     if (comments != null) {
1055 :     converter.buildCommentsTable(compilationUnit, comments);
1056 :     }
1057 :     compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
1058 : oliviert 1.73 Block block = ast.newBlock();
1059 :     block.setSourceRange(this.sourceOffset, this.sourceOffset + this.sourceLength);
1060 :     org.eclipse.jdt.internal.compiler.ast.Statement[] statements = constructorDeclaration.statements;
1061 :     if (statements != null) {
1062 :     int statementsLength = statements.length;
1063 :     for (int i = 0; i < statementsLength; i++) {
1064 :     if (statements[i] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
1065 :     converter.checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
1066 :     } else {
1067 :     Statement statement = converter.convert(statements[i]);
1068 :     if (statement != null) {
1069 :     block.statements().add(statement);
1070 : oliviert 1.46 }
1071 : jdesrivieres 1.2 }
1072 :     }
1073 :     }
1074 : oliviert 1.73 rootNodeToCompilationUnit(ast, compilationUnit, block, recordedParsingInformation, data);
1075 :     ast.setDefaultNodeFlag(0);
1076 :     ast.setOriginalModificationCount(ast.modificationCount());
1077 :     return block;
1078 : jdesrivieres 1.2 case K_EXPRESSION :
1079 : othomann 1.5 org.eclipse.jdt.internal.compiler.ast.Expression expression = codeSnippetParsingUtil.parseExpression(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true);
1080 : jdesrivieres 1.2 recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
1081 :     comments = recordedParsingInformation.commentPositions;
1082 :     if (comments != null) {
1083 :     converter.buildCommentsTable(compilationUnit, comments);
1084 :     }
1085 :     compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
1086 :     if (expression != null) {
1087 :     Expression expression2 = converter.convert(expression);
1088 : daudel 1.52 rootNodeToCompilationUnit(expression2.getAST(), compilationUnit, expression2, codeSnippetParsingUtil.recordedParsingInformation, null);
1089 : daudel 1.9 ast.setDefaultNodeFlag(0);
1090 :     ast.setOriginalModificationCount(ast.modificationCount());
1091 : jdesrivieres 1.2 return expression2;
1092 :     } else {
1093 : pmulet 1.55 CategorizedProblem[] problems = recordedParsingInformation.problems;
1094 : jdesrivieres 1.2 if (problems != null) {
1095 :     compilationUnit.setProblems(problems);
1096 :     }
1097 : daudel 1.9 ast.setDefaultNodeFlag(0);
1098 :     ast.setOriginalModificationCount(ast.modificationCount());
1099 : jdesrivieres 1.2 return compilationUnit;
1100 :     }
1101 :     case K_CLASS_BODY_DECLARATIONS :
1102 : othomann 1.5 final org.eclipse.jdt.internal.compiler.ast.ASTNode[] nodes = codeSnippetParsingUtil.parseClassBodyDeclarations(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 (nodes != null) {
1110 :     TypeDeclaration typeDeclaration = converter.convert(nodes);
1111 : daudel 1.68 typeDeclaration.setSourceRange(this.sourceOffset, this.sourceOffset + this.sourceLength);
1112 : daudel 1.52 rootNodeToCompilationUnit(typeDeclaration.getAST(), compilationUnit, typeDeclaration, codeSnippetParsingUtil.recordedParsingInformation, null);
1113 : daudel 1.9 ast.setDefaultNodeFlag(0);
1114 :     ast.setOriginalModificationCount(ast.modificationCount());
1115 : jdesrivieres 1.2 return typeDeclaration;
1116 :     } else {
1117 : pmulet 1.55 CategorizedProblem[] problems = recordedParsingInformation.problems;
1118 : jdesrivieres 1.2 if (problems != null) {
1119 :     compilationUnit.setProblems(problems);
1120 :     }
1121 : daudel 1.9 ast.setDefaultNodeFlag(0);
1122 :     ast.setOriginalModificationCount(ast.modificationCount());
1123 : jdesrivieres 1.2 return compilationUnit;
1124 :     }
1125 :     }
1126 : othomann 1.5 throw new IllegalStateException();
1127 : jdesrivieres 1.2 }
1128 :    
1129 : pmulet 1.55 private void propagateErrors(ASTNode astNode, CategorizedProblem[] problems, RecoveryScannerData data) {
1130 : oliviert 1.67 astNode.accept(new ASTSyntaxErrorPropagator(problems));
1131 :     if (data != null) {
1132 :     astNode.accept(new ASTRecoveryPropagator(problems, data));
1133 :     }
1134 : jdesrivieres 1.2 }
1135 : oliviert 1.73
1136 : daudel 1.52 private void rootNodeToCompilationUnit(AST ast, CompilationUnit compilationUnit, ASTNode node, RecordedParsingInformation recordedParsingInformation, RecoveryScannerData data) {
1137 : jdesrivieres 1.2 final int problemsCount = recordedParsingInformation.problemsCount;
1138 :     switch(node.getNodeType()) {
1139 :     case ASTNode.BLOCK :
1140 :     {
1141 :     Block block = (Block) node;
1142 :     if (problemsCount != 0) {
1143 :     // propagate and record problems
1144 : pmulet 1.55 final CategorizedProblem[] problems = recordedParsingInformation.problems;
1145 : daudel 1.68 propagateErrors(block, problems, data);
1146 : jdesrivieres 1.2 compilationUnit.setProblems(problems);
1147 :     }
1148 :     TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
1149 :     Initializer initializer = ast.newInitializer();
1150 :     initializer.setBody(block);
1151 :     typeDeclaration.bodyDeclarations().add(initializer);
1152 :     compilationUnit.types().add(typeDeclaration);
1153 :     }
1154 :     break;
1155 :     case ASTNode.TYPE_DECLARATION :
1156 :     {
1157 :     TypeDeclaration typeDeclaration = (TypeDeclaration) node;
1158 :     if (problemsCount != 0) {
1159 :     // propagate and record problems
1160 : pmulet 1.55 final CategorizedProblem[] problems = recordedParsingInformation.problems;
1161 : daudel 1.68 propagateErrors(typeDeclaration, problems, data);
1162 : jdesrivieres 1.2 compilationUnit.setProblems(problems);
1163 :     }
1164 :     compilationUnit.types().add(typeDeclaration);
1165 :     }
1166 :     break;
1167 :     default :
1168 :     if (node instanceof Expression) {
1169 :     Expression expression = (Expression) node;
1170 :     if (problemsCount != 0) {
1171 :     // propagate and record problems
1172 : pmulet 1.55 final CategorizedProblem[] problems = recordedParsingInformation.problems;
1173 : daudel 1.52 propagateErrors(expression, problems, data);
1174 : jdesrivieres 1.2 compilationUnit.setProblems(problems);
1175 :     }
1176 :     ExpressionStatement expressionStatement = ast.newExpressionStatement(expression);
1177 :     Block block = ast.newBlock();
1178 :     block.statements().add(expressionStatement);
1179 :     Initializer initializer = ast.newInitializer();
1180 :     initializer.setBody(block);
1181 :     TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
1182 :     typeDeclaration.bodyDeclarations().add(initializer);
1183 :     compilationUnit.types().add(typeDeclaration);
1184 :     }
1185 :     }
1186 :     }
1187 : oliviert 1.38 }