0001: /*******************************************************************************
0002: * Copyright (c) 2004, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.jdt.core.dom;
0011:
0012: import java.util.HashMap;
0013: import java.util.Map;
0014:
0015: import org.eclipse.core.runtime.IProgressMonitor;
0016: import org.eclipse.jdt.core.IClassFile;
0017: import org.eclipse.jdt.core.ICompilationUnit;
0018: import org.eclipse.jdt.core.IJavaElement;
0019: import org.eclipse.jdt.core.ITypeRoot;
0020: import org.eclipse.jdt.core.IJavaProject;
0021: import org.eclipse.jdt.core.JavaCore;
0022: import org.eclipse.jdt.core.JavaModelException;
0023: import org.eclipse.jdt.core.WorkingCopyOwner;
0024: import org.eclipse.jdt.core.compiler.CategorizedProblem;
0025: import org.eclipse.jdt.core.compiler.CharOperation;
0026: import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
0027: import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
0028: import org.eclipse.jdt.internal.compiler.env.IBinaryType;
0029: import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
0030: import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData;
0031: import org.eclipse.jdt.internal.compiler.parser.Scanner;
0032: import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
0033: import org.eclipse.jdt.internal.core.*;
0034: import org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil;
0035: import org.eclipse.jdt.internal.core.util.RecordedParsingInformation;
0036: import org.eclipse.jdt.internal.core.util.Util;
0037:
0038: /**
0039: * A Java language parser for creating abstract syntax trees (ASTs).
0040: * <p>
0041: * Example: Create basic AST from source string
0042: * <pre>
0043: * char[] source = ...;
0044: * ASTParser parser = ASTParser.newParser(AST.JLS3); // handles JDK 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6
0045: * parser.setSource(source);
0046: * CompilationUnit result = (CompilationUnit) parser.createAST(null);
0047: * </pre>
0048: * Once a configured parser instance has been used to create an AST,
0049: * the settings are automatically reset to their defaults,
0050: * ready for the parser instance to be reused.
0051: * </p>
0052: * <p>
0053: * There are a number of configurable features:
0054: * <ul>
0055: * <li>Source string from {@link #setSource(char[]) char[]},
0056: * {@link #setSource(ICompilationUnit) ICompilationUnit},
0057: * or {@link #setSource(IClassFile) IClassFile}, and limited
0058: * to a specified {@linkplain #setSourceRange(int,int) subrange}.</li>
0059: * <li>Whether {@linkplain #setResolveBindings(boolean) bindings} will be created.</li>
0060: * <li>Which {@linkplain #setWorkingCopyOwner(WorkingCopyOwner)
0061: * working set owner} to use when resolving bindings).</li>
0062: * <li>A hypothetical {@linkplain #setUnitName(String) compilation unit file name}
0063: * and {@linkplain #setProject(IJavaProject) Java project}
0064: * for locating a raw source string in the Java model (when
0065: * resolving bindings)</li>
0066: * <li>Which {@linkplain #setCompilerOptions(Map) compiler options}
0067: * to use. This is especially important to use if the parsing/scanning of the source code requires a
0068: * different version than the default of the workspace. For example, the workspace defaults are 1.4 and
0069: * you want to create an AST for a source code that is using 1.5 constructs.</li>
0070: * <li>Whether to parse just {@linkplain #setKind(int) an expression, statements,
0071: * or body declarations} rather than an entire compilation unit.</li>
0072: * <li>Whether to return a {@linkplain #setFocalPosition(int) abridged AST}
0073: * focused on the declaration containing a given source position.</li>
0074: * </ul>
0075: * </p>
0076: *
0077: * @since 3.0
0078: */
0079: public class ASTParser {
0080:
0081: /**
0082: * Kind constant used to request that the source be parsed
0083: * as a single expression.
0084: */
0085: public static final int K_EXPRESSION = 0x01;
0086:
0087: /**
0088: * Kind constant used to request that the source be parsed
0089: * as a sequence of statements.
0090: */
0091: public static final int K_STATEMENTS = 0x02;
0092:
0093: /**
0094: * Kind constant used to request that the source be parsed
0095: * as a sequence of class body declarations.
0096: */
0097: public static final int K_CLASS_BODY_DECLARATIONS = 0x04;
0098:
0099: /**
0100: * Kind constant used to request that the source be parsed
0101: * as a compilation unit.
0102: */
0103: public static final int K_COMPILATION_UNIT = 0x08;
0104:
0105: /**
0106: * Creates a new object for creating a Java abstract syntax tree
0107: * (AST) following the specified set of API rules.
0108: *
0109: * @param level the API level; one of the LEVEL constants
0110: * declared on <code>AST</code>
0111: * @return new ASTParser instance
0112: */
0113: public static ASTParser newParser(int level) {
0114: return new ASTParser(level);
0115: }
0116:
0117: /**
0118: * Level of AST API desired.
0119: */
0120: private final int apiLevel;
0121:
0122: /**
0123: * Kind of parse requested. Defaults to an entire compilation unit.
0124: */
0125: private int astKind;
0126:
0127: /**
0128: * Compiler options. Defaults to JavaCore.getOptions().
0129: */
0130: private Map compilerOptions;
0131:
0132: /**
0133: * Request for bindings. Defaults to <code>false</code>.
0134: */
0135: private boolean resolveBindings;
0136:
0137: /**
0138: * Request for a partial AST. Defaults to <code>false</code>.
0139: */
0140: private boolean partial = false;
0141:
0142: /**
0143: * Request for a statements recovery. Defaults to <code>false</code>.
0144: */
0145: private boolean statementsRecovery;
0146:
0147: /**
0148: * Request for a bindings recovery. Defaults to <code>false</code>.
0149: */
0150: private boolean bindingsRecovery;
0151:
0152: /**
0153: * The focal point for a partial AST request.
0154: * Only used when <code>partial</code> is <code>true</code>.
0155: */
0156: private int focalPointPosition;
0157:
0158: /**
0159: * Source string.
0160: */
0161: private char[] rawSource = null;
0162:
0163: /**
0164: * Java model class file or compilation unit supplying the source.
0165: */
0166: private ITypeRoot typeRoot = null;
0167:
0168: /**
0169: * Character-based offset into the source string where parsing is to
0170: * begin. Defaults to 0.
0171: */
0172: private int sourceOffset = 0;
0173:
0174: /**
0175: * Character-based length limit, or -1 if unlimited.
0176: * All characters in the source string between <code>offset</code>
0177: * and <code>offset+length-1</code> inclusive are parsed. Defaults to -1,
0178: * which means the rest of the source string.
0179: */
0180: private int sourceLength = -1;
0181:
0182: /**
0183: * Working copy owner. Defaults to primary owner.
0184: */
0185: private WorkingCopyOwner workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
0186:
0187: /**
0188: * Java project used to resolve names, or <code>null</code> if none.
0189: * Defaults to none.
0190: */
0191: private IJavaProject project = null;
0192:
0193: /**
0194: * Name of the compilation unit for resolving bindings, or
0195: * <code>null</code> if none. Defaults to none.
0196: */
0197: private String unitName = null;
0198:
0199: /**
0200: * Creates a new AST parser for the given API level.
0201: * <p>
0202: * N.B. This constructor is package-private.
0203: * </p>
0204: *
0205: * @param level the API level; one of the LEVEL constants
0206: * declared on <code>AST</code>
0207: */
0208: ASTParser(int level) {
0209: if ((level != AST.JLS2_INTERNAL) && (level != AST.JLS3)) {
0210: throw new IllegalArgumentException();
0211: }
0212: this .apiLevel = level;
0213: initializeDefaults();
0214: }
0215:
0216: /**
0217: * Sets all the setting to their default values.
0218: */
0219: private void initializeDefaults() {
0220: this .astKind = K_COMPILATION_UNIT;
0221: this .rawSource = null;
0222: this .typeRoot = null;
0223: this .resolveBindings = false;
0224: this .sourceLength = -1;
0225: this .sourceOffset = 0;
0226: this .workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
0227: this .unitName = null;
0228: this .project = null;
0229: this .partial = false;
0230: Map options = JavaCore.getOptions();
0231: options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
0232: this .compilerOptions = options;
0233: }
0234:
0235: /**
0236: * Requests that the compiler should perform bindings recovery.
0237: * When bindings recovery is enabled the compiler returns incomplete bindings.
0238: * <p>
0239: * Default to <code>false</code>.
0240: * </p>
0241: * <p>This should be set to true only if bindings are resolved. It has no effect if there is no binding
0242: * resolution.</p>
0243: *
0244: * @param enabled <code>true</code> if incomplete bindings are expected,
0245: * and <code>false</code> if only complete bindings are expected.
0246: *
0247: * @see IBinding#isRecovered()
0248: * @since 3.3
0249: */
0250: public void setBindingsRecovery(boolean enabled) {
0251: this .bindingsRecovery = enabled;
0252: }
0253:
0254: /**
0255: * Sets the compiler options to be used when parsing.
0256: * <p>
0257: * Note that {@link #setSource(IClassFile)},
0258: * {@link #setSource(ICompilationUnit)},
0259: * and {@link #setProject(IJavaProject)} reset the compiler options
0260: * based on the Java project. In other cases, compiler options default
0261: * to {@link JavaCore#getOptions()}. In either case, and especially
0262: * in the latter, the caller should carefully weight the consequences of
0263: * allowing compiler options to be defaulted as opposed to being
0264: * explicitly specified for the <code>ASTParser</code> instance.
0265: * For instance, there is a compiler option called "Source Compatibility Mode"
0266: * which determines which JDK level the source code is expected to meet.
0267: * If you specify "1.4", then "assert" is treated as a keyword and disallowed
0268: * as an identifier; if you specify "1.3", then "assert" is allowed as an
0269: * identifier. So this particular setting has a major bearing on what is
0270: * considered syntactically legal. By explicitly specifying the setting,
0271: * the client control exactly how the parser works. On the other hand,
0272: * allowing default settings means the parsing behaves like other JDT tools.
0273: * </p>
0274: *
0275: * @param options the table of options (key type: <code>String</code>;
0276: * value type: <code>String</code>), or <code>null</code>
0277: * to set it back to the default
0278: */
0279: public void setCompilerOptions(Map options) {
0280: if (options == null) {
0281: options = JavaCore.getOptions();
0282: } else {
0283: // copy client's options so as to not do any side effect on them
0284: options = new HashMap(options);
0285: }
0286: options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
0287: this .compilerOptions = options;
0288: }
0289:
0290: /**
0291: * Requests that the compiler should provide binding information for
0292: * the AST nodes it creates.
0293: * <p>
0294: * Default to <code>false</code> (no bindings).
0295: * </p>
0296: * <p>
0297: * If <code>setResolveBindings(true)</code>, the various names
0298: * and types appearing in the AST can be resolved to "bindings"
0299: * by calling the <code>resolveBinding</code> methods. These bindings
0300: * draw connections between the different parts of a program, and
0301: * generally afford a more powerful vantage point for clients who wish to
0302: * analyze a program's structure more deeply. These bindings come at a
0303: * considerable cost in both time and space, however, and should not be
0304: * requested frivolously. The additional space is not reclaimed until the
0305: * AST, all its nodes, and all its bindings become garbage. So it is very
0306: * important to not retain any of these objects longer than absolutely
0307: * necessary. Bindings are resolved at the time the AST is created. Subsequent
0308: * modifications to the AST do not affect the bindings returned by
0309: * <code>resolveBinding</code> methods in any way; these methods return the
0310: * same binding as before the AST was modified (including modifications
0311: * that rearrange subtrees by reparenting nodes).
0312: * If <code>setResolveBindings(false)</code> (the default), the analysis
0313: * does not go beyond parsing and building the tree, and all
0314: * <code>resolveBinding</code> methods return <code>null</code> from the
0315: * outset.
0316: * </p>
0317: * <p>
0318: * When bindings are requested, instead of considering compilation units on disk only
0319: * one can supply a <code>WorkingCopyOwner</code>. Working copies owned
0320: * by this owner take precedence over the underlying compilation units when looking
0321: * up names and drawing the connections.
0322: * </p>
0323: * <p>
0324: * Binding information is obtained from the Java model.
0325: * This means that the compilation unit must be located relative to the
0326: * Java model. This happens automatically when the source code comes from
0327: * either {@link #setSource(ICompilationUnit) setSource(ICompilationUnit)}
0328: * or {@link #setSource(IClassFile) setSource(IClassFile)}.
0329: * When source is supplied by {@link #setSource(char[]) setSource(char[])},
0330: * the location must be extablished explicitly by calling
0331: * {@link #setProject(IJavaProject)} and {@link #setUnitName(String)}.
0332: * Note that the compiler options that affect doc comment checking may also
0333: * affect whether any bindings are resolved for nodes within doc comments.
0334: * </p>
0335: *
0336: * @param bindings <code>true</code> if bindings are wanted,
0337: * and <code>false</code> if bindings are not of interest
0338: */
0339: public void setResolveBindings(boolean bindings) {
0340: this .resolveBindings = bindings;
0341: }
0342:
0343: /**
0344: * Requests an abridged abstract syntax tree.
0345: * By default, complete ASTs are returned.
0346: * <p>
0347: * When <code>true</code> the resulting AST does not have nodes for
0348: * the entire compilation unit. Rather, the AST is only fleshed out
0349: * for the node that include the given source position. This kind of limited
0350: * AST is sufficient for certain purposes but totally unsuitable for others.
0351: * In places where it can be used, the limited AST offers the advantage of
0352: * being smaller and faster to construct.
0353: * </p>
0354: * <p>
0355: * The AST will include nodes for all of the compilation unit's
0356: * package, import, and top-level type declarations. It will also always contain
0357: * nodes for all the body declarations for those top-level types, as well
0358: * as body declarations for any member types. However, some of the body
0359: * declarations may be abridged. In particular, the statements ordinarily
0360: * found in the body of a method declaration node will not be included
0361: * (the block will be empty) unless the source position falls somewhere
0362: * within the source range of that method declaration node. The same is true
0363: * for initializer declarations; the statements ordinarily found in the body
0364: * of initializer node will not be included unless the source position falls
0365: * somewhere within the source range of that initializer declaration node.
0366: * Field declarations are never abridged. Note that the AST for the body of
0367: * that one unabridged method (or initializer) is 100% complete; it has all
0368: * its statements, including any local or anonymous type declarations
0369: * embedded within them. When the the given position is not located within
0370: * the source range of any body declaration of a top-level type, the AST
0371: * returned will be a skeleton that includes nodes for all and only the major
0372: * declarations; this kind of AST is still quite useful because it contains
0373: * all the constructs that introduce names visible to the world outside the
0374: * compilation unit.
0375: * </p>
0376: *
0377: * @param position a position into the corresponding body declaration
0378: */
0379: public void setFocalPosition(int position) {
0380: this .partial = true;
0381: this .focalPointPosition = position;
0382: }
0383:
0384: /**
0385: * Sets the kind of constructs to be parsed from the source.
0386: * Defaults to an entire compilation unit.
0387: * <p>
0388: * When the parse is successful the result returned includes the ASTs for the
0389: * requested source:
0390: * <ul>
0391: * <li>{@link #K_COMPILATION_UNIT K_COMPILATION_UNIT}: The result node
0392: * is a {@link CompilationUnit}.</li>
0393: * <li>{@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
0394: * is a {@link TypeDeclaration} whose
0395: * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
0396: * are the new trees. Other aspects of the type declaration are unspecified.</li>
0397: * <li>{@link #K_STATEMENTS K_STATEMENTS}: The result node is a
0398: * {@link Block Block} whose {@link Block#statements() statements}
0399: * are the new trees. Other aspects of the block are unspecified.</li>
0400: * <li>{@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
0401: * {@link Expression Expression}. Other aspects of the expression are unspecified.</li>
0402: * </ul>
0403: * The resulting AST node is rooted under (possibly contrived)
0404: * {@link CompilationUnit CompilationUnit} node, to allow the
0405: * client to retrieve the following pieces of information
0406: * available there:
0407: * <ul>
0408: * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
0409: * numbers start at 1 and only cover the subrange scanned
0410: * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
0411: * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
0412: * and {@linkplain CompilationUnit#getProblems() detailed problem reports}.
0413: * Character positions are relative to the start of
0414: * <code>source</code>; line positions are for the subrange scanned.</li>
0415: * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
0416: * for the subrange scanned.</li>
0417: * </ul>
0418: * The contrived nodes do not have source positions. Other aspects of the
0419: * {@link CompilationUnit CompilationUnit} node are unspecified, including
0420: * the exact arrangment of intervening nodes.
0421: * </p>
0422: * <p>
0423: * Lexical or syntax errors detected while parsing can result in
0424: * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
0425: * In more severe failure cases where the parser is unable to
0426: * recognize the input, this method returns
0427: * a {@link CompilationUnit CompilationUnit} node with at least the
0428: * compiler messages.
0429: * </p>
0430: * <p>Each node in the subtree (other than the contrived nodes)
0431: * carries source range(s) information relating back
0432: * to positions in the given source (the given source itself
0433: * is not remembered with the AST).
0434: * The source range usually begins at the first character of the first token
0435: * corresponding to the node; leading whitespace and comments are <b>not</b>
0436: * included. The source range usually extends through the last character of
0437: * the last token corresponding to the node; trailing whitespace and
0438: * comments are <b>not</b> included. There are a handful of exceptions
0439: * (including the various body declarations); the
0440: * specification for these node type spells out the details.
0441: * Source ranges nest properly: the source range for a child is always
0442: * within the source range of its parent, and the source ranges of sibling
0443: * nodes never overlap.
0444: * </p>
0445: * <p>
0446: * Binding information is only computed when <code>kind</code> is
0447: * <code>K_COMPILATION_UNIT</code>.
0448: * </p>
0449: *
0450: * @param kind the kind of construct to parse: one of
0451: * {@link #K_COMPILATION_UNIT},
0452: * {@link #K_CLASS_BODY_DECLARATIONS},
0453: * {@link #K_EXPRESSION},
0454: * {@link #K_STATEMENTS}
0455: */
0456: public void setKind(int kind) {
0457: if ((kind != K_COMPILATION_UNIT)
0458: && (kind != K_CLASS_BODY_DECLARATIONS)
0459: && (kind != K_EXPRESSION) && (kind != K_STATEMENTS)) {
0460: throw new IllegalArgumentException();
0461: }
0462: this .astKind = kind;
0463: }
0464:
0465: /**
0466: * Sets the source code to be parsed.
0467: *
0468: * @param source the source string to be parsed,
0469: * or <code>null</code> if none
0470: */
0471: public void setSource(char[] source) {
0472: this .rawSource = source;
0473: // clear the type root
0474: this .typeRoot = null;
0475: }
0476:
0477: /**
0478: * Sets the source code to be parsed.
0479: * This method automatically sets the project (and compiler
0480: * options) based on the given compilation unit, in a manner
0481: * equivalent to <code>setProject(source.getJavaProject())</code>
0482: *
0483: * @param source the Java model compilation unit whose source code
0484: * is to be parsed, or <code>null</code> if none
0485: */
0486: public void setSource(ICompilationUnit source) {
0487: setSource((ITypeRoot) source);
0488: }
0489:
0490: /**
0491: * Sets the source code to be parsed.
0492: * <p>This method automatically sets the project (and compiler
0493: * options) based on the given compilation unit, in a manner
0494: * equivalent to <code>setProject(source.getJavaProject())</code>.</p>
0495: * <p>If the given class file has no source attachment, the creation of the
0496: * ast will fail with an IllegalStateException.</p>
0497: *
0498: * @param source the Java model class file whose corresponding source code
0499: * is to be parsed, or <code>null</code> if none
0500: */
0501: public void setSource(IClassFile source) {
0502: setSource((ITypeRoot) source);
0503: }
0504:
0505: /**
0506: * Sets the source code to be parsed.
0507: * <p>This method automatically sets the project (and compiler
0508: * options) based on the given compilation unit of class file, in a manner
0509: * equivalent to <code>setProject(source.getJavaProject())</code>.</p>
0510: * <p>If the source is a class file without source attachment, the creation of the
0511: * ast will fail with an IllegalStateException.</p>
0512: *
0513: * @param source the Java model compilation unit or class file whose corresponding source code
0514: * is to be parsed, or <code>null</code> if none
0515: * @since 3.3
0516: */
0517: public void setSource(ITypeRoot source) {
0518: this .typeRoot = source;
0519: // clear the raw source
0520: this .rawSource = null;
0521: if (source != null) {
0522: this .project = source.getJavaProject();
0523: Map options = this .project.getOptions(true);
0524: options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
0525: this .compilerOptions = options;
0526: }
0527: }
0528:
0529: /**
0530: * Sets the subrange of the source code to be parsed.
0531: * By default, the entire source string will be parsed
0532: * (<code>offset</code> 0 and <code>length</code> -1).
0533: *
0534: * @param offset the index of the first character to parse
0535: * @param length the number of characters to parse, or -1 if
0536: * the remainder of the source string is
0537: */
0538: public void setSourceRange(int offset, int length) {
0539: if (offset < 0 || length < -1) {
0540: throw new IllegalArgumentException();
0541: }
0542: this .sourceOffset = offset;
0543: this .sourceLength = length;
0544: }
0545:
0546: /**
0547: * Requests that the compiler should perform statements recovery.
0548: * When statements recovery is enabled the compiler tries to create statement nodes
0549: * from code containing syntax errors
0550: * <p>
0551: * Default to <code>false</code>.
0552: * </p>
0553: *
0554: * @param enabled <code>true</code> if statements containing syntax errors are wanted,
0555: * and <code>false</code> if these statements aren't wanted.
0556: *
0557: * @since 3.2
0558: */
0559: public void setStatementsRecovery(boolean enabled) {
0560: this .statementsRecovery = enabled;
0561: }
0562:
0563: /**
0564: * Sets the working copy owner using when resolving bindings, where
0565: * <code>null</code> means the primary owner. Defaults to the primary owner.
0566: *
0567: * @param owner the owner of working copies that take precedence over underlying
0568: * compilation units, or <code>null</code> if the primary owner should be used
0569: */
0570: public void setWorkingCopyOwner(WorkingCopyOwner owner) {
0571: if (owner == null) {
0572: this .workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
0573: } else {
0574: this .workingCopyOwner = owner;
0575: }
0576: }
0577:
0578: /**
0579: * Sets the name of the compilation unit that would hypothetically contains
0580: * the source string. This is used in conjunction with {@link #setSource(char[])}
0581: * and {@link #setProject(IJavaProject) } to locate the compilation unit relative to a Java project.
0582: * Defaults to none (<code>null</code>).
0583: * <p>
0584: * The name of the compilation unit must be supplied for resolving bindings.
0585: * This name should be suffixed by a dot ('.') followed by one of the
0586: * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}
0587: * and match the name of the main (public) class or interface declared in the source.</p>
0588: *
0589: * <p>This name must represent the full path of the unit inside the given project. For example, if the source
0590: * declares a public class named "Foo" in a project "P", the name of the compilation unit must be
0591: * "/P/Foo.java". If the source declares a public class name "Bar" in a package "p1.p2" in a project "P",
0592: * the name of the compilation unit must be "/P/p1/p2/Bar.java".</p>
0593: *
0594: * @param unitName the name of the compilation unit that would contain the source
0595: * string, or <code>null</code> if none
0596: */
0597: public void setUnitName(String unitName) {
0598: this .unitName = unitName;
0599: }
0600:
0601: /**
0602: * Sets the Java project used when resolving bindings.
0603: * This method automatically sets the compiler
0604: * options based on the given project:
0605: * <pre>
0606: * setCompilerOptions(project.getOptions(true));
0607: * </pre>
0608: * See {@link #setCompilerOptions(Map)} for a discussion of
0609: * the pros and cons of using these options vs specifying
0610: * compiler options explicitly.
0611: * This setting is used in conjunction with <code>setSource(char[])</code>.
0612: * For the purposes of resolving bindings, types declared in the
0613: * source string will hide types by the same name available
0614: * through the classpath of the given project.
0615: * Defaults to none (<code>null</code>).
0616: *
0617: * @param project the Java project used to resolve names, or
0618: * <code>null</code> if none
0619: */
0620: public void setProject(IJavaProject project) {
0621: this .project = project;
0622: if (project != null) {
0623: Map options = project.getOptions(true);
0624: options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
0625: this .compilerOptions = options;
0626: }
0627: }
0628:
0629: /**
0630: * Creates an abstract syntax tree.
0631: * <p>
0632: * A successful call to this method returns all settings to their
0633: * default values so the object is ready to be reused.
0634: * </p>
0635: *
0636: * @param monitor the progress monitor used to report progress and request cancelation,
0637: * or <code>null</code> if none
0638: * @return an AST node whose type depends on the kind of parse
0639: * requested, with a fallback to a <code>CompilationUnit</code>
0640: * in the case of severe parsing errors
0641: * @exception IllegalStateException if the settings provided
0642: * are insufficient, contradictory, or otherwise unsupported
0643: */
0644: public ASTNode createAST(IProgressMonitor monitor) {
0645: ASTNode result = null;
0646: if (monitor != null)
0647: monitor.beginTask("", 1); //$NON-NLS-1$
0648: try {
0649: if (this .rawSource == null && this .typeRoot == null) {
0650: throw new IllegalStateException("source not specified"); //$NON-NLS-1$
0651: }
0652: result = internalCreateAST(monitor);
0653: } finally {
0654: // re-init defaults to allow reuse (and avoid leaking)
0655: initializeDefaults();
0656: if (monitor != null)
0657: monitor.done();
0658: }
0659: return result;
0660: }
0661:
0662: /**
0663: * Creates ASTs for a batch of compilation units.
0664: * When bindings are being resolved, processing a
0665: * batch of compilation units is more efficient because much
0666: * of the work involved in resolving bindings can be shared.
0667: * <p>
0668: * When bindings are being resolved, all compilation units must
0669: * come from the same Java project, which must be set beforehand
0670: * with <code>setProject</code>.
0671: * The compilation units are processed one at a time in no
0672: * specified order. For each of the compilation units in turn,
0673: * <ul>
0674: * <li><code>ASTParser.createAST</code> is called to parse it
0675: * and create a corresponding AST. The calls to
0676: * <code>ASTParser.createAST</code> all employ the same settings.</li>
0677: * <li><code>ASTRequestor.acceptAST</code> is called passing
0678: * the compilation unit and the corresponding AST to
0679: * <code>requestor</code>.
0680: * </li>
0681: * </ul>
0682: * Note only ASTs from the given compilation units are reported
0683: * to the requestor. If additional compilation units are required to
0684: * resolve the original ones, the corresponding ASTs are <b>not</b>
0685: * reported to the requestor.
0686: * </p>
0687: * <p>
0688: * Note also the following parser parameters are used, regardless of what
0689: * may have been specified:
0690: * <ul>
0691: * <li>The {@linkplain #setKind(int) parser kind} is <code>K_COMPILATION_UNIT</code></li>
0692: * <li>The {@linkplain #setSourceRange(int,int) source range} is <code>(0, -1)</code></li>
0693: * <li>The {@linkplain #setFocalPosition(int) focal position} is not set</li>
0694: * </ul>
0695: * </p>
0696: * <p>
0697: * The <code>bindingKeys</code> parameter specifies bindings keys
0698: * ({@link IBinding#getKey()}) that are to be looked up. These keys may
0699: * be for elements either inside or outside the set of compilation
0700: * units being processed. When bindings are being resolved,
0701: * the keys and corresponding bindings (or <code>null</code> if none) are
0702: * passed to <code>ASTRequestor.acceptBinding</code>. Note that binding keys
0703: * for elements outside the set of compilation units being processed are looked up
0704: * after all <code>ASTRequestor.acceptAST</code> callbacks have been made.
0705: * Binding keys for elements inside the set of compilation units being processed
0706: * are looked up and reported right after the corresponding
0707: * <code>ASTRequestor.acceptAST</code> callback has been made.
0708: * No <code>ASTRequestor.acceptBinding</code> callbacks are made unless
0709: * bindings are being resolved.
0710: * </p>
0711: * <p>
0712: * A successful call to this method returns all settings to their
0713: * default values so the object is ready to be reused.
0714: * </p>
0715: *
0716: * @param compilationUnits the compilation units to create ASTs for
0717: * @param bindingKeys the binding keys to create bindings for
0718: * @param requestor the AST requestor that collects abtract syntax trees and bindings
0719: * @param monitor the progress monitor used to report progress and request cancelation,
0720: * or <code>null</code> if none
0721: * @exception IllegalStateException if the settings provided
0722: * are insufficient, contradictory, or otherwise unsupported
0723: * @since 3.1
0724: */
0725: public void createASTs(ICompilationUnit[] compilationUnits,
0726: String[] bindingKeys, ASTRequestor requestor,
0727: IProgressMonitor monitor) {
0728: try {
0729: int flags = 0;
0730: if (this .statementsRecovery)
0731: flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
0732: if (this .resolveBindings) {
0733: if (this .project == null)
0734: throw new IllegalStateException(
0735: "project not specified"); //$NON-NLS-1$
0736: if (this .bindingsRecovery)
0737: flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
0738: CompilationUnitResolver.resolve(compilationUnits,
0739: bindingKeys, requestor, this .apiLevel,
0740: this .compilerOptions, this .project,
0741: this .workingCopyOwner, flags, monitor);
0742: } else {
0743: CompilationUnitResolver.parse(compilationUnits,
0744: requestor, this .apiLevel, this .compilerOptions,
0745: flags, monitor);
0746: }
0747: } finally {
0748: // re-init defaults to allow reuse (and avoid leaking)
0749: initializeDefaults();
0750: }
0751: }
0752:
0753: /**
0754: * Creates bindings for a batch of Java elements. These elements are either
0755: * enclosed in {@link ICompilationUnit}s or in {@link IClassFile}s.
0756: * <p>
0757: * All enclosing compilation units and class files must
0758: * come from the same Java project, which must be set beforehand
0759: * with <code>setProject</code>.
0760: * </p>
0761: * <p>
0762: * All elements must exist. If one doesn't exist, an <code>IllegalStateException</code>
0763: * is thrown.
0764: * </p>
0765: * <p>
0766: * The returned array has the same size as the given elements array. At a given position
0767: * it contains the binding of the corresponding Java element, or <code>null</code>
0768: * if no binding could be created.
0769: * </p>
0770: * <p>
0771: * Note also the following parser parameters are used, regardless of what
0772: * may have been specified:
0773: * <ul>
0774: * <li>The {@linkplain #setResolveBindings(boolean) binding resolution flag} is <code>true</code></li>
0775: * <li>The {@linkplain #setKind(int) parser kind} is <code>K_COMPILATION_UNIT</code></li>
0776: * <li>The {@linkplain #setSourceRange(int,int) source range} is <code>(0, -1)</code></li>
0777: * <li>The {@linkplain #setFocalPosition(int) focal position} is not set</li>
0778: * </ul>
0779: * </p>
0780: * <p>
0781: * A successful call to this method returns all settings to their
0782: * default values so the object is ready to be reused.
0783: * </p>
0784: *
0785: * @param elements the Java elements to create bindings for
0786: * @return the bindings for the given Java elements, possibly containing <code>null</code>s
0787: * if some bindings could not be created
0788: * @exception IllegalStateException if the settings provided
0789: * are insufficient, contradictory, or otherwise unsupported
0790: * @since 3.1
0791: */
0792: public IBinding[] createBindings(IJavaElement[] elements,
0793: IProgressMonitor monitor) {
0794: try {
0795: if (this .project == null)
0796: throw new IllegalStateException("project not specified"); //$NON-NLS-1$
0797: int flags = 0;
0798: if (this .statementsRecovery)
0799: flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
0800: if (this .bindingsRecovery)
0801: flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
0802: return CompilationUnitResolver.resolve(elements,
0803: this .apiLevel, this .compilerOptions, this .project,
0804: this .workingCopyOwner, flags, monitor);
0805: } finally {
0806: // re-init defaults to allow reuse (and avoid leaking)
0807: initializeDefaults();
0808: }
0809: }
0810:
0811: private ASTNode internalCreateAST(IProgressMonitor monitor) {
0812: boolean needToResolveBindings = this .resolveBindings;
0813: switch (this .astKind) {
0814: case K_CLASS_BODY_DECLARATIONS:
0815: case K_EXPRESSION:
0816: case K_STATEMENTS:
0817: if (this .rawSource != null) {
0818: if (this .sourceOffset + this .sourceLength > this .rawSource.length) {
0819: throw new IllegalStateException();
0820: }
0821: return internalCreateASTForKind();
0822: }
0823: break;
0824: case K_COMPILATION_UNIT:
0825: CompilationUnitDeclaration compilationUnitDeclaration = null;
0826: try {
0827: NodeSearcher searcher = null;
0828: org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = null;
0829: WorkingCopyOwner wcOwner = this .workingCopyOwner;
0830: if (this .typeRoot instanceof ICompilationUnit) {
0831: /*
0832: * this.compilationUnitSource is an instance of org.eclipse.jdt.internal.core.CompilationUnit that implements
0833: * both org.eclipse.jdt.core.ICompilationUnit and org.eclipse.jdt.internal.compiler.env.ICompilationUnit
0834: */
0835: sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) this .typeRoot;
0836: /*
0837: * use a BasicCompilation that caches the source instead of using the compilationUnitSource directly
0838: * (if it is a working copy, the source can change between the parse and the AST convertion)
0839: * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75632)
0840: */
0841: sourceUnit = new BasicCompilationUnit(sourceUnit
0842: .getContents(),
0843: sourceUnit.getPackageName(), new String(
0844: sourceUnit.getFileName()),
0845: this .project);
0846: wcOwner = ((ICompilationUnit) this .typeRoot)
0847: .getOwner();
0848: } else if (this .typeRoot instanceof IClassFile) {
0849: try {
0850: String sourceString = this .typeRoot.getSource();
0851: if (sourceString == null) {
0852: throw new IllegalStateException();
0853: }
0854: PackageFragment packageFragment = (PackageFragment) this .typeRoot
0855: .getParent();
0856: BinaryType type = (BinaryType) this .typeRoot
0857: .findPrimaryType();
0858: IBinaryType binaryType = (IBinaryType) type
0859: .getElementInfo();
0860: // file name is used to recreate the Java element, so it has to be the toplevel .class file name
0861: char[] fileName = binaryType.getFileName();
0862: int firstDollar = CharOperation.indexOf('$',
0863: fileName);
0864: if (firstDollar != -1) {
0865: char[] suffix = SuffixConstants.SUFFIX_class;
0866: int suffixLength = suffix.length;
0867: char[] newFileName = new char[firstDollar
0868: + suffixLength];
0869: System.arraycopy(fileName, 0, newFileName,
0870: 0, firstDollar);
0871: System.arraycopy(suffix, 0, newFileName,
0872: firstDollar, suffixLength);
0873: fileName = newFileName;
0874: }
0875: sourceUnit = new BasicCompilationUnit(
0876: sourceString.toCharArray(),
0877: Util
0878: .toCharArrays(packageFragment.names),
0879: new String(fileName), this .project);
0880: } catch (JavaModelException e) {
0881: // an error occured accessing the java element
0882: throw new IllegalStateException();
0883: }
0884: } else if (this .rawSource != null) {
0885: needToResolveBindings = this .resolveBindings
0886: && this .unitName != null
0887: && this .project != null
0888: && this .compilerOptions != null;
0889: sourceUnit = new BasicCompilationUnit(
0890: this .rawSource,
0891: null,
0892: this .unitName == null ? "" : this .unitName, this .project); //$NON-NLS-1$
0893: } else {
0894: throw new IllegalStateException();
0895: }
0896: if (this .partial) {
0897: searcher = new NodeSearcher(this .focalPointPosition);
0898: }
0899: int flags = 0;
0900: if (this .statementsRecovery)
0901: flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
0902: if (needToResolveBindings) {
0903: if (this .bindingsRecovery)
0904: flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
0905: try {
0906: // parse and resolve
0907: compilationUnitDeclaration = CompilationUnitResolver
0908: .resolve(sourceUnit, this .project,
0909: searcher, this .compilerOptions,
0910: this .workingCopyOwner, flags,
0911: monitor);
0912: } catch (JavaModelException e) {
0913: flags &= ~ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
0914: compilationUnitDeclaration = CompilationUnitResolver
0915: .parse(sourceUnit, searcher,
0916: this .compilerOptions, flags);
0917: needToResolveBindings = false;
0918: }
0919: } else {
0920: compilationUnitDeclaration = CompilationUnitResolver
0921: .parse(sourceUnit, searcher,
0922: this .compilerOptions, flags);
0923: needToResolveBindings = false;
0924: }
0925: CompilationUnit result = CompilationUnitResolver
0926: .convert(
0927: compilationUnitDeclaration,
0928: sourceUnit.getContents(),
0929: this .apiLevel,
0930: this .compilerOptions,
0931: needToResolveBindings,
0932: wcOwner,
0933: needToResolveBindings ? new DefaultBindingResolver.BindingTables()
0934: : null, flags, monitor);
0935: result.setTypeRoot(this .typeRoot);
0936: return result;
0937: } finally {
0938: if (compilationUnitDeclaration != null
0939: && this .resolveBindings) {
0940: compilationUnitDeclaration.cleanUp();
0941: }
0942: }
0943: }
0944: throw new IllegalStateException();
0945: }
0946:
0947: /**
0948: * Parses the given source between the bounds specified by the given offset (inclusive)
0949: * and the given length and creates and returns a corresponding abstract syntax tree.
0950: * <p>
0951: * When the parse is successful the result returned includes the ASTs for the
0952: * requested source:
0953: * <ul>
0954: * <li>{@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
0955: * is a {@link TypeDeclaration TypeDeclaration} whose
0956: * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
0957: * are the new trees. Other aspects of the type declaration are unspecified.</li>
0958: * <li>{@link #K_STATEMENTS K_STATEMENTS}: The result node is a
0959: * {@link Block Block} whose {@link Block#statements() statements}
0960: * are the new trees. Other aspects of the block are unspecified.</li>
0961: * <li>{@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
0962: * {@link Expression Expression}. Other aspects of the expression are unspecified.</li>
0963: * </ul>
0964: * The resulting AST node is rooted under an contrived
0965: * {@link CompilationUnit CompilationUnit} node, to allow the
0966: * client to retrieve the following pieces of information
0967: * available there:
0968: * <ul>
0969: * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
0970: * numbers start at 1 and only cover the subrange scanned
0971: * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
0972: * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
0973: * and {@linkplain CompilationUnit#getProblems() detailed problem reports}.
0974: * Character positions are relative to the start of
0975: * <code>source</code>; line positions are for the subrange scanned.</li>
0976: * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
0977: * for the subrange scanned.</li>
0978: * </ul>
0979: * The contrived nodes do not have source positions. Other aspects of the
0980: * {@link CompilationUnit CompilationUnit} node are unspecified, including
0981: * the exact arrangment of intervening nodes.
0982: * </p>
0983: * <p>
0984: * Lexical or syntax errors detected while parsing can result in
0985: * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
0986: * In more severe failure cases where the parser is unable to
0987: * recognize the input, this method returns
0988: * a {@link CompilationUnit CompilationUnit} node with at least the
0989: * compiler messages.
0990: * </p>
0991: * <p>Each node in the subtree (other than the contrived nodes)
0992: * carries source range(s) information relating back
0993: * to positions in the given source (the given source itself
0994: * is not remembered with the AST).
0995: * The source range usually begins at the first character of the first token
0996: * corresponding to the node; leading whitespace and comments are <b>not</b>
0997: * included. The source range usually extends through the last character of
0998: * the last token corresponding to the node; trailing whitespace and
0999: * comments are <b>not</b> included. There are a handful of exceptions
1000: * (including the various body declarations); the
1001: * specification for these node type spells out the details.
1002: * Source ranges nest properly: the source range for a child is always
1003: * within the source range of its parent, and the source ranges of sibling
1004: * nodes never overlap.
1005: * </p>
1006: * <p>
1007: * This method does not compute binding information; all <code>resolveBinding</code>
1008: * methods applied to nodes of the resulting AST return <code>null</code>.
1009: * </p>
1010: *
1011: * @return an AST node whose type depends on the kind of parse
1012: * requested, with a fallback to a <code>CompilationUnit</code>
1013: * in the case of severe parsing errors
1014: * @see ASTNode#getStartPosition()
1015: * @see ASTNode#getLength()
1016: */
1017: private ASTNode internalCreateASTForKind() {
1018: final ASTConverter converter = new ASTConverter(
1019: this .compilerOptions, false, null);
1020: converter.compilationUnitSource = this .rawSource;
1021: converter.compilationUnitSourceLength = this .rawSource.length;
1022: converter.scanner.setSource(this .rawSource);
1023:
1024: AST ast = AST.newAST(this .apiLevel);
1025: ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
1026: ast.setBindingResolver(new BindingResolver());
1027: if (this .statementsRecovery) {
1028: ast.setFlag(ICompilationUnit.ENABLE_STATEMENTS_RECOVERY);
1029: }
1030: converter.setAST(ast);
1031: CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil();
1032: CompilationUnit compilationUnit = ast.newCompilationUnit();
1033: if (this .sourceLength == -1) {
1034: this .sourceLength = this .rawSource.length;
1035: }
1036: switch (this .astKind) {
1037: case K_STATEMENTS:
1038: ConstructorDeclaration constructorDeclaration = codeSnippetParsingUtil
1039: .parseStatements(this .rawSource, this .sourceOffset,
1040: this .sourceLength, this .compilerOptions,
1041: true, this .statementsRecovery);
1042: RecoveryScannerData data = constructorDeclaration.compilationResult.recoveryScannerData;
1043: if (data != null) {
1044: Scanner scanner = converter.scanner;
1045: converter.scanner = new RecoveryScanner(scanner, data
1046: .removeUnused());
1047: converter.docParser.scanner = converter.scanner;
1048: converter.scanner.setSource(scanner.source);
1049: }
1050: RecordedParsingInformation recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
1051: int[][] comments = recordedParsingInformation.commentPositions;
1052: if (comments != null) {
1053: converter.buildCommentsTable(compilationUnit, comments);
1054: }
1055: compilationUnit
1056: .setLineEndTable(recordedParsingInformation.lineEnds);
1057: Block block = ast.newBlock();
1058: block.setSourceRange(this .sourceOffset, this .sourceOffset
1059: + 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(
1066: statements, i, block.statements());
1067: } else {
1068: Statement statement = converter
1069: .convert(statements[i]);
1070: if (statement != null) {
1071: block.statements().add(statement);
1072: }
1073: }
1074: }
1075: }
1076: rootNodeToCompilationUnit(ast, compilationUnit, block,
1077: recordedParsingInformation, data);
1078: ast.setDefaultNodeFlag(0);
1079: ast.setOriginalModificationCount(ast.modificationCount());
1080: return block;
1081: case K_EXPRESSION:
1082: org.eclipse.jdt.internal.compiler.ast.Expression expression = codeSnippetParsingUtil
1083: .parseExpression(this .rawSource, this .sourceOffset,
1084: this .sourceLength, this .compilerOptions,
1085: true);
1086: recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
1087: comments = recordedParsingInformation.commentPositions;
1088: if (comments != null) {
1089: converter.buildCommentsTable(compilationUnit, comments);
1090: }
1091: compilationUnit
1092: .setLineEndTable(recordedParsingInformation.lineEnds);
1093: if (expression != null) {
1094: Expression expression2 = converter.convert(expression);
1095: rootNodeToCompilationUnit(
1096: expression2.getAST(),
1097: compilationUnit,
1098: expression2,
1099: codeSnippetParsingUtil.recordedParsingInformation,
1100: null);
1101: ast.setDefaultNodeFlag(0);
1102: ast.setOriginalModificationCount(ast
1103: .modificationCount());
1104: return expression2;
1105: } else {
1106: CategorizedProblem[] problems = recordedParsingInformation.problems;
1107: if (problems != null) {
1108: compilationUnit.setProblems(problems);
1109: }
1110: ast.setDefaultNodeFlag(0);
1111: ast.setOriginalModificationCount(ast
1112: .modificationCount());
1113: return compilationUnit;
1114: }
1115: case K_CLASS_BODY_DECLARATIONS:
1116: final org.eclipse.jdt.internal.compiler.ast.ASTNode[] nodes = codeSnippetParsingUtil
1117: .parseClassBodyDeclarations(this .rawSource,
1118: this .sourceOffset, this .sourceLength,
1119: this .compilerOptions, true);
1120: recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
1121: comments = recordedParsingInformation.commentPositions;
1122: if (comments != null) {
1123: converter.buildCommentsTable(compilationUnit, comments);
1124: }
1125: compilationUnit
1126: .setLineEndTable(recordedParsingInformation.lineEnds);
1127: if (nodes != null) {
1128: TypeDeclaration typeDeclaration = converter
1129: .convert(nodes);
1130: typeDeclaration.setSourceRange(this .sourceOffset,
1131: this .sourceOffset + this .sourceLength);
1132: rootNodeToCompilationUnit(
1133: typeDeclaration.getAST(),
1134: compilationUnit,
1135: typeDeclaration,
1136: codeSnippetParsingUtil.recordedParsingInformation,
1137: null);
1138: ast.setDefaultNodeFlag(0);
1139: ast.setOriginalModificationCount(ast
1140: .modificationCount());
1141: return typeDeclaration;
1142: } else {
1143: CategorizedProblem[] problems = recordedParsingInformation.problems;
1144: if (problems != null) {
1145: compilationUnit.setProblems(problems);
1146: }
1147: ast.setDefaultNodeFlag(0);
1148: ast.setOriginalModificationCount(ast
1149: .modificationCount());
1150: return compilationUnit;
1151: }
1152: }
1153: throw new IllegalStateException();
1154: }
1155:
1156: private void propagateErrors(ASTNode astNode,
1157: CategorizedProblem[] problems, RecoveryScannerData data) {
1158: astNode.accept(new ASTSyntaxErrorPropagator(problems));
1159: if (data != null) {
1160: astNode.accept(new ASTRecoveryPropagator(problems, data));
1161: }
1162: }
1163:
1164: private void rootNodeToCompilationUnit(AST ast,
1165: CompilationUnit compilationUnit, ASTNode node,
1166: RecordedParsingInformation recordedParsingInformation,
1167: RecoveryScannerData data) {
1168: final int problemsCount = recordedParsingInformation.problemsCount;
1169: switch (node.getNodeType()) {
1170: case ASTNode.BLOCK: {
1171: Block block = (Block) node;
1172: if (problemsCount != 0) {
1173: // propagate and record problems
1174: final CategorizedProblem[] problems = recordedParsingInformation.problems;
1175: propagateErrors(block, problems, data);
1176: compilationUnit.setProblems(problems);
1177: }
1178: TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
1179: Initializer initializer = ast.newInitializer();
1180: initializer.setBody(block);
1181: typeDeclaration.bodyDeclarations().add(initializer);
1182: compilationUnit.types().add(typeDeclaration);
1183: }
1184: break;
1185: case ASTNode.TYPE_DECLARATION: {
1186: TypeDeclaration typeDeclaration = (TypeDeclaration) node;
1187: if (problemsCount != 0) {
1188: // propagate and record problems
1189: final CategorizedProblem[] problems = recordedParsingInformation.problems;
1190: propagateErrors(typeDeclaration, problems, data);
1191: compilationUnit.setProblems(problems);
1192: }
1193: compilationUnit.types().add(typeDeclaration);
1194: }
1195: break;
1196: default:
1197: if (node instanceof Expression) {
1198: Expression expression = (Expression) node;
1199: if (problemsCount != 0) {
1200: // propagate and record problems
1201: final CategorizedProblem[] problems = recordedParsingInformation.problems;
1202: propagateErrors(expression, problems, data);
1203: compilationUnit.setProblems(problems);
1204: }
1205: ExpressionStatement expressionStatement = ast
1206: .newExpressionStatement(expression);
1207: Block block = ast.newBlock();
1208: block.statements().add(expressionStatement);
1209: Initializer initializer = ast.newInitializer();
1210: initializer.setBody(block);
1211: TypeDeclaration typeDeclaration = ast
1212: .newTypeDeclaration();
1213: typeDeclaration.bodyDeclarations().add(initializer);
1214: compilationUnit.types().add(typeDeclaration);
1215: }
1216: }
1217: }
1218: }
|