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