/*******************************************************************************
 * Copyright (c) 2000, 2010 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.jdt.core.dom;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.parser.Scanner;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.TextEdit;

/**
 * Java compilation unit AST node type. This is the type of the root of an AST.
 * <p>
 * The source range for this type of node is ordinarily the entire source file,
 * including leading and trailing whitespace and comments.
 * </p>
 * For JLS2:
 * <pre>
 * CompilationUnit:
 *    [ PackageDeclaration ]
 *        { ImportDeclaration }
 *        { TypeDeclaration | <b>;</b> }
 * </pre>
 * For JLS3, the kinds of type declarations
 * grew to include enum and annotation type declarations:
 * <pre>
 * CompilationUnit:
 *    [ PackageDeclaration ]
 *        { ImportDeclaration }
 *        { TypeDeclaration | EnumDeclaration | AnnotationTypeDeclaration | <b>;</b> }
 * </pre>
 *
 * @since 2.0
 * @noinstantiate This class is not intended to be instantiated by clients.
 */
public class CompilationUnit extends ASTNode {

	/**
	 * Canonical empty list of messages.
	 */
	private static final Message[] EMPTY_MESSAGES = new Message[0];

	/**
	 * Canonical empty list of problems.
	 */
	private static final IProblem[] EMPTY_PROBLEMS = new IProblem[0];

	/**
	 * The "imports" structural property of this node type (element type: {@link ImportDeclaration}).
	 *
	 * @since 3.0
	 */
	public static final ChildListPropertyDescriptor IMPORTS_PROPERTY =
		new ChildListPropertyDescriptor(CompilationUnit.class, "imports", ImportDeclaration.class, NO_CYCLE_RISK); //$NON-NLS-1$

	/**
	 * The "package" structural property of this node type (child type: {@link PackageDeclaration}).
	 *
	 * @since 3.0
	 */
	public static final ChildPropertyDescriptor PACKAGE_PROPERTY =
		new ChildPropertyDescriptor(CompilationUnit.class, "package", PackageDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$

	/**
	 * A list of property descriptors (element type:
	 * {@link StructuralPropertyDescriptor}),
	 * or null if uninitialized.
	 * @since 3.0
	 */
	private static final List PROPERTY_DESCRIPTORS;

	/**
	 * The "types" structural property of this node type (element type: {@link AbstractTypeDeclaration}).
	 *
	 * @since 3.0
	 */
	public static final ChildListPropertyDescriptor TYPES_PROPERTY =
		new ChildListPropertyDescriptor(CompilationUnit.class, "types", AbstractTypeDeclaration.class, CYCLE_RISK); //$NON-NLS-1$

	static {
		List properyList = new ArrayList(4);
		createPropertyList(CompilationUnit.class, properyList);
		addProperty(PACKAGE_PROPERTY, properyList);
		addProperty(IMPORTS_PROPERTY, properyList);
		addProperty(TYPES_PROPERTY, properyList);
		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
	}

	/**
	 * Returns a list of structural property descriptors for this node type.
	 * Clients must not modify the result.
	 *
	 * @param apiLevel the API level; one of the
	 * <code>AST.JLS*</code> constants

	 * @return a list of property descriptors (element type:
	 * {@link StructuralPropertyDescriptor})
	 * @since 3.0
	 */
	public static List propertyDescriptors(int apiLevel) {
		return PROPERTY_DESCRIPTORS;
	}

	/**
	 * The comment mapper, or <code>null</code> if none;
	 * initially <code>null</code>.
	 * @since 3.0
	 */
	private DefaultCommentMapper commentMapper = null;

	/**
	 * The Java type root (an <code>org.eclipse.jdt.core.ICompilationUnit</code> or an <code>org.eclipse.jdt.core.IClassFile</code>)
	 * this compilation unit was created from, or <code>null</code> if it was not created from a Java type root.
	 */
	private ITypeRoot typeRoot = null;

	/**
	 * The list of import declarations in textual order order;
	 * initially none (elementType: <code>ImportDeclaration</code>).
	 */
	private ASTNode.NodeList imports =
		new ASTNode.NodeList(IMPORTS_PROPERTY);

	/**
	 * Line end table. If <code>lineEndTable[i] == p</code> then the
	 * line number <code>i+1</code> ends at character position
	 * <code>p</code>. Except for the last line, the positions are that
	 * of the last character of the line delimiter.
	 * For example, the source string <code>A\nB\nC</code> has
	 * line end table {1, 3} (if \n is one character).
	 */
	private int[] lineEndTable = Util.EMPTY_INT_ARRAY;

	/**
	 * Messages reported by the compiler during parsing or name resolution.
	 */
	private Message[] messages;

	/**
	 * The comment list (element type: {@link Comment},
	 * or <code>null</code> if none; initially <code>null</code>.
	 * @since 3.0
	 */
	private List optionalCommentList = null;

	/**
	 * The comment table, or <code>null</code> if none; initially
	 * <code>null</code>. This array is the storage underlying
	 * the <code>optionalCommentList</code> ArrayList.
	 * @since 3.0
	 */
	Comment[] optionalCommentTable = null;

	/**
	 * The package declaration, or <code>null</code> if none; initially
	 * <code>null</code>.
	 */
	private PackageDeclaration optionalPackageDeclaration = null;

	/**
	 * Problems reported by the compiler during parsing or name resolution.
	 */
	private IProblem[] problems = EMPTY_PROBLEMS;

	/**
	 * Internal data used to perform statements recovery.
	 */
	private Object statementsRecoveryData;

	/**
	 * The list of type declarations in textual order order;
	 * initially none (elementType: <code>AbstractTypeDeclaration</code>)
	 */
	private ASTNode.NodeList types =
		new ASTNode.NodeList(TYPES_PROPERTY);

	/**
	 * Creates a new AST node for a compilation owned by the given AST.
	 * The compilation unit initially has no package declaration, no
	 * import declarations, and no type declarations.
	 * <p>
	 * N.B. This constructor is package-private; all subclasses must be
	 * declared in the same package; clients are unable to declare
	 * additional subclasses.
	 * </p>
	 *
	 * @param ast the AST that is to own this node
	 */
	CompilationUnit(AST ast) {
		super(ast);
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	void accept0(ASTVisitor visitor) {
		boolean visitChildren = visitor.visit(this);
		if (visitChildren) {
			// visit children in normal left to right reading order
			acceptChild(visitor, getPackage());
			acceptChildren(visitor, this.imports);
			acceptChildren(visitor, this.types);
		}
		visitor.endVisit(this);
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	ASTNode clone0(AST target) {
		CompilationUnit result = new CompilationUnit(target);
		// n.b do not copy line number table or messages
		result.setSourceRange(getStartPosition(), getLength());
		result.setPackage(
			(PackageDeclaration) ASTNode.copySubtree(target, getPackage()));
		result.imports().addAll(ASTNode.copySubtrees(target, imports()));
		result.types().addAll(ASTNode.copySubtrees(target, types()));
		return result;
	}


	/**
	 * Returns the column number corresponding to the given source character
	 * position in the original source string. Column number are zero-based.
	 * Return <code>-1</code> if it is beyond the valid range or <code>-2</code>
	 * if the column number information is unknown.
	 *
	 * @param position a 0-based character position, possibly
	 *   negative or out of range
	 * @return the 0-based column number, or <code>-1</code> if the character
	 *    position does not correspond to a source line in the original
	 *    source file or <code>-2</code> if column number information is unknown for this
	 *    compilation unit
	 * @see ASTParser
	 * @since 3.2
	 */
	public int getColumnNumber(final int position) {
		if (this.lineEndTable == null) return -2;
		final int line = getLineNumber(position);
		if (line == -1) {
			return -1;
		}
		if (line == 1) {
			if (position >= getStartPosition() + getLength()) return -1;
			return position;
		}
		// length is different from 0
		int length = this.lineEndTable.length;
		// -1 to for one-based to zero-based conversion.
		// -1, again, to get previous line.
		final int previousLineOffset = this.lineEndTable[line - 2];
		 // previousLineOffset + 1 is the first character of the current line
		final int offsetForLine = previousLineOffset + 1;
		final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 :	this.lineEndTable[line - 1];
		if (offsetForLine > currentLineEnd) {
			return -1;
		} else {
			return position - offsetForLine;
		}
	}

	/**
	 * Finds the corresponding AST node in the given compilation unit from
	 * which the given binding originated. Returns <code>null</code> if the
	 * binding does not correspond to any node in this compilation unit.
	 * This method always returns <code>null</code> if bindings were not requested
	 * when this AST was built.
	 * <p>
	 * The following table indicates the expected node type for the various
	 * different kinds of bindings:
	 * <ul>
	 * <li>package - a <code>PackageDeclaration</code></li>
	 * <li>class or interface - a <code>TypeDeclaration</code> or a
	 *    <code>AnonymousClassDeclaration</code> (for anonymous classes)</li>
	 * <li>primitive type - none</li>
	 * <li>array type - none</li>
	 * <li>field - a <code>VariableDeclarationFragment</code> in a
	 *    <code>FieldDeclaration</code> </li>
	 * <li>local variable - a <code>SingleVariableDeclaration</code>, or
	 *    a <code>VariableDeclarationFragment</code> in a
	 *    <code>VariableDeclarationStatement</code> or
	 *    <code>VariableDeclarationExpression</code></li>
	 * <li>method - a <code>MethodDeclaration</code> </li>
	 * <li>constructor - a <code>MethodDeclaration</code> </li>
     * <li>annotation type - an <code>AnnotationTypeDeclaration</code></li>
     * <li>annotation type member - an <code>AnnotationTypeMemberDeclaration</code></li>
     * <li>enum type - an <code>EnumDeclaration</code></li>
     * <li>enum constant - an <code>EnumConstantDeclaration</code></li>
     * <li>type variable - a <code>TypeParameter</code></li>
     * <li>capture binding - none</li>
     * <li>annotation binding - an <code>Annotation</code></li>
     * <li>member value pair binding - an <code>MemberValuePair</code>,
     *      or <code>null</code> if it represents a default value or a single member value</li>
	 * </ul>
     * For parameterized or raw type bindings, the declaring node is
     * that of the corresponding generic type. And for parameterized or raw
     * method bindings, the declaring node is that of the corresponding
     * generic method.
	 * </p>
	 * <p>
	 * Each call to {@link ASTParser#createAST(org.eclipse.core.runtime.IProgressMonitor)} with a request for bindings
	 * gives rise to separate universe of binding objects. This method always returns
	 * <code>null</code> when the binding object comes from a different AST.
	 * Use <code>findDeclaringNode(binding.getKey())</code> when the binding comes
	 * from a different AST.
	 * </p>
	 *
	 * @param binding the binding
	 * @return the corresponding node where the given binding is declared,
	 * or <code>null</code> if the binding does not correspond to a node in this
	 * compilation unit or if bindings were not requested when this AST was built
	 * @see #findDeclaringNode(String)
	 */
	public ASTNode findDeclaringNode(IBinding binding) {
		return this.ast.getBindingResolver().findDeclaringNode(binding);
	}

	/**
	 * Finds the corresponding AST node in the given compilation unit from
	 * which the binding with the given key originated. Returns
	 * <code>null</code> if the corresponding node cannot be determined.
	 * This method always returns <code>null</code> if bindings were not requested
	 * when this AST was built.
	 * <p>
	 * The following table indicates the expected node type for the various
	 * different kinds of binding keys:
	 * <ul>
	 * <li></li>
	 * <li>package - a <code>PackageDeclaration</code></li>
	 * <li>class or interface - a <code>TypeDeclaration</code> or a
	 *    <code>AnonymousClassDeclaration</code> (for anonymous classes)</li>
	 * <li>primitive type - none</li>
	 * <li>array type - none</li>
	 * <li>field - a <code>VariableDeclarationFragment</code> in a
	 *    <code>FieldDeclaration</code> </li>
	 * <li>local variable - a <code>SingleVariableDeclaration</code>, or
	 *    a <code>VariableDeclarationFragment</code> in a
	 *    <code>VariableDeclarationStatement</code> or
	 *    <code>VariableDeclarationExpression</code></li>
	 * <li>method - a <code>MethodDeclaration</code> </li>
	 * <li>constructor - a <code>MethodDeclaration</code> </li>
     * <li>annotation type - an <code>AnnotationTypeDeclaration</code></li>
     * <li>annotation type member - an <code>AnnotationTypeMemberDeclaration</code></li>
     * <li>enum type - an <code>EnumDeclaration</code></li>
     * <li>enum constant - an <code>EnumConstantDeclaration</code></li>
	 * <li>type variable - a <code>TypeParameter</code></li>
     * <li>capture binding - none</li>
	 * </ul>
     * For parameterized or raw type bindings, the declaring node is
     * that of the corresponding generic type. And for parameterized or raw
     * method bindings, the declaring node is that of the corresponding
     * generic method.
	 * </p>
	 *
	 * @param key the binding key, or <code>null</code>
	 * @return the corresponding node where a binding with the given
	 * key is declared, or <code>null</code> if the key is <code>null</code>
	 * or if the key does not correspond to a node in this compilation unit
	 * or if bindings were not requested when this AST was built
	 * @see IBinding#getKey()
	 * @since 2.1
	 */
	public ASTNode findDeclaringNode(String key) {
		return this.ast.getBindingResolver().findDeclaringNode(key);
	}

	/**
	 * Returns a list of the comments encountered while parsing
	 * this compilation unit.
	 * <p>
	 * Since the Java language allows comments to appear most anywhere
	 * in the source text, it is problematic to locate comments in relation
	 * to the structure of an AST. The one exception is doc comments
	 * which, by convention, immediately precede type, field, and
	 * method declarations; these comments are located in the AST
	 * by {@link  BodyDeclaration#getJavadoc BodyDeclaration.getJavadoc}.
	 * Other comments do not show up in the AST. The table of comments
	 * is provided for clients that need to find the source ranges of
	 * all comments in the original source string. It includes entries
	 * for comments of all kinds (line, block, and doc), arranged in order
	 * of increasing source position.
	 * </p>
	 * <p>
	 * Note on comment parenting: The {@link ASTNode#getParent() getParent()}
	 * of a doc comment associated with a body declaration is the body
	 * declaration node; for these comment nodes
	 * {@link ASTNode#getRoot() getRoot()} will return the compilation unit
	 * (assuming an unmodified AST) reflecting the fact that these nodes
	 * are property located in the AST for the compilation unit.
	 * However, for other comment nodes, {@link ASTNode#getParent() getParent()}
	 * will return <code>null</code>, and {@link ASTNode#getRoot() getRoot()}
	 * will return the comment node itself, indicating that these comment nodes
	 * are not directly connected to the AST for the compilation unit. The
	 * {@link Comment#getAlternateRoot Comment.getAlternateRoot}
	 * method provides a way to navigate from a comment to its compilation
	 * unit.
	 * </p>
	 * <p>
	 * A note on visitors: The only comment nodes that will be visited when
	 * visiting a compilation unit are the doc comments parented by body
	 * declarations. To visit all comments in normal reading order, iterate
	 * over the comment table and call {@link ASTNode#accept(ASTVisitor) accept}
	 * on each element.
	 * </p>
	 * <p>
	 * Clients cannot modify the resulting list.
	 * </p>
	 *
	 * @return an unmodifiable list of comments in increasing order of source
	 * start position (element type: {@link Comment}, or <code>null</code> if comment information
	 * for this compilation unit is not available
	 * @see ASTParser
	 * @since 3.0
	 */
	public List getCommentList() {
		return this.optionalCommentList;
	}

	/**
	 * Returns the internal comment mapper.
	 *
	 * @return the comment mapper, or <code>null</code> if none.
	 * @since 3.0
	 */
	DefaultCommentMapper getCommentMapper() {
		return this.commentMapper;
	}

	/**
	 * Returns the extended source length of the given node. Unlike
	 * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
	 * the extended source range may include comments and whitespace
	 * immediately before or after the normal source range for the node.
	 *
	 * @param node the node
	 * @return a (possibly 0) length, or <code>0</code>
	 *    if no source position information is recorded for this node
	 * @see #getExtendedStartPosition(ASTNode)
	 * @since 3.0
	 */
	public int getExtendedLength(ASTNode node) {
		if (node == null) {
			throw new IllegalArgumentException();
		}
		if (this.commentMapper == null || node.getAST() != getAST()) {
			// fall back: use best info available
			return node.getLength();
		} else {
			return this.commentMapper.getExtendedLength(node);
		}
	}

	/**
	 * Returns the extended start position of the given node. Unlike
	 * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
	 * the extended source range may include comments and whitespace
	 * immediately before or after the normal source range for the node.
	 *
	 * @param node the node
	 * @return the 0-based character index, or <code>-1</code>
	 *    if no source position information is recorded for this node
	 * @see #getExtendedLength(ASTNode)
	 * @since 3.0
	 */
	public int getExtendedStartPosition(ASTNode node) {
		if (node == null) {
			throw new IllegalArgumentException();
		}
		if (this.commentMapper == null || node.getAST() != getAST()) {
			// fall back: use best info available
			return node.getStartPosition();
		} else {
			return this.commentMapper.getExtendedStartPosition(node);
		}
	}

	/**
	 * The Java element (an <code>org.eclipse.jdt.core.ICompilationUnit</code> or an <code>org.eclipse.jdt.core.IClassFile</code>)
	 * this compilation unit was created from, or <code>null</code> if it was not created from a Java element.
	 *
	 * @return the Java element this compilation unit was created from, or <code>null</code> if none
	 * @since 3.1
	 * @see #getTypeRoot()
	 */
	public IJavaElement getJavaElement() {
		return this.typeRoot;
	}

	/**
	 * Returns the list of messages reported by the compiler during the parsing
	 * or the type checking of this compilation unit. This list might be a subset of
	 * errors detected and reported by a Java compiler.
	 * <p>
	 * This list of messages is suitable for simple clients that do little
	 * more than log the messages or display them to the user. Clients that
	 * need further details should call <code>getProblems</code> to get
	 * compiler problem objects.
	 * </p>
	 *
	 * @return the list of messages, possibly empty
	 * @see #getProblems()
	 * @see ASTParser
	 */
	public Message[] getMessages() {
		if (this.messages == null) {
			int problemLength = this.problems.length;
			if (problemLength == 0) {
				this.messages = EMPTY_MESSAGES;
			} else {
				this.messages = new Message[problemLength];
				for (int i = 0; i < problemLength; i++) {
					IProblem problem = this.problems[i];
					int start = problem.getSourceStart();
					int end = problem.getSourceEnd();
					this.messages[i] = new Message(problem.getMessage(), start, end - start + 1);
				}
			}
		}
		return this.messages;
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	final int getNodeType0() {
		return COMPILATION_UNIT;
	}

	/**
	 * Returns the node for the package declaration of this compilation
	 * unit, or <code>null</code> if this compilation unit is in the
	 * default package.
	 *
	 * @return the package declaration node, or <code>null</code> if none
	 */
	public PackageDeclaration getPackage() {
		return this.optionalPackageDeclaration;
	}

	/**
	 * Given a line number and column number, returns the corresponding
	 * position in the original source string.
	 * Returns -2 if no line number information is available for this
	 * compilation unit.
	 * Returns the total size of the source string if <code>line</code>
	 * is greater than the actual number lines in the unit.
	 * Returns -1 if <code>column</code> is less than 0,
	 * or the position of the last character of the line if <code>column</code>
	 * is beyond the legal range, or the given line number is less than one.
	 *
	 * @param line the one-based line number
	 * @param column the zero-based column number
	 * @return the 0-based character position in the source string;
	 * <code>-2</code> if line/column number information is not known
	 * for this compilation unit or <code>-1</code> the inputs are not valid
	 * @since 3.2
	 */
	 public int getPosition(int line, int column) {
		if (this.lineEndTable == null) return -2;
		if (line < 1 || column < 0) return -1;
		int length;
		if ((length = this.lineEndTable.length) == 0) {
			if (line != 1) return -1;
			return column >= getStartPosition() + getLength() ? -1 : column;
		}
		if (line == 1) {
			final int endOfLine = this.lineEndTable[0];
			return column > endOfLine ? -1 : column;
		} else if( line > length + 1 ) {
			// greater than the number of lines in the source string.
			return -1;
		}
		// -1 to for one-based to zero-based conversion.
		// -1, again, to get previous line.
		final int previousLineOffset = this.lineEndTable[line - 2];
		 // previousLineOffset + 1 is the first character of the current line
		final int offsetForLine = previousLineOffset + 1;
		final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 : this.lineEndTable[line-1];
		if ((offsetForLine + column) > currentLineEnd) {
			return -1;
		} else {
			return offsetForLine + column;
		}
	}

	/**
	 * Returns the list of detailed problem reports noted by the compiler
	 * during the parsing or the type checking of this compilation unit. This
	 * list might be a subset of errors detected and reported by a Java
	 * compiler.
	 * <p>
	 * Simple clients that do little more than log the messages or display
	 * them to the user should probably call <code>getMessages</code> instead.
	 * </p>
	 *
	 * @return the list of detailed problem objects, possibly empty
	 * @see #getMessages()
	 * @see ASTParser
	 * @since 2.1
	 */
	public IProblem[] getProblems() {
		return this.problems;
	}

	/**
	 * Internal method
	 *
	 * This method return internal data used to perform statements recovery.
	 *
	 * @return internal data used to perform statements recovery.
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 * @since 3.5
	 */
	public Object getStatementsRecoveryData() {
		return this.statementsRecoveryData;
	}

	/**
	 * The Java type root (a {@link org.eclipse.jdt.core.ICompilationUnit compilation unit} or a {@link org.eclipse.jdt.core.IClassFile class file})
	 * this compilation unit was created from, or <code>null</code> if it was not created from a Java type root.
	 *
	 * @return the Java type root this compilation unit was created from, or <code>null</code> if none
	 * @since 3.3
	 */
	public ITypeRoot getTypeRoot() {
		return this.typeRoot;
	}

	/**
	 * Returns the live list of nodes for the import declarations of this
	 * compilation unit, in order of appearance.
	 *
	 * @return the live list of import declaration nodes
	 *    (elementType: {@link ImportDeclaration})
	 */
	public List imports() {
		return this.imports;
	}

	/**
	 * Return the index in the whole comments list {@link #getCommentList() }
	 * of the first leading comments associated with the given node.
	 *
	 * @param node the node
	 * @return 0-based index of first leading comment or -1 if node has no associated
	 * 	comment before its start position.
	 * @since 3.2
	 */
	public int firstLeadingCommentIndex(ASTNode node) {
		if (node == null) {
			throw new IllegalArgumentException();
		}
		if (this.commentMapper == null || node.getAST() != getAST()) {
			return -1;
		}
		return this.commentMapper.firstLeadingCommentIndex(node);
	}

	/**
	 * Return the index in the whole comments list {@link #getCommentList() }
	 * of the last trailing comments associated with the given node.
	 *
	 * @param node the node
	 * @return 0-based index of last trailing comment or -1 if node has no
	 * 	associated comment after its end position.
	 * @since 3.2
	 */
	public int lastTrailingCommentIndex(ASTNode node) {
		if (node == null) {
			throw new IllegalArgumentException();
		}
		if (this.commentMapper == null || node.getAST() != getAST()) {
			return -1;
		}
		return this.commentMapper.lastTrailingCommentIndex(node);
	}

	/**
	 * Initializes the internal comment mapper with the given
	 * scanner.
	 *
	 * @param scanner the scanner
	 * @since 3.0
	 */
	void initCommentMapper(Scanner scanner) {
		this.commentMapper = new DefaultCommentMapper(this.optionalCommentTable);
		this.commentMapper.initialize(this, scanner);
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
		if (property == IMPORTS_PROPERTY) {
			return imports();
		}
		if (property == TYPES_PROPERTY) {
			return types();
		}
		// allow default implementation to flag the error
		return super.internalGetChildListProperty(property);
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
		if (property == PACKAGE_PROPERTY) {
			if (get) {
				return getPackage();
			} else {
				setPackage((PackageDeclaration) child);
				return null;
			}
		}
		// allow default implementation to flag the error
		return super.internalGetSetChildProperty(property, get, child);
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 * @since 3.0
	 */
	final List internalStructuralPropertiesForType(int apiLevel) {
		return propertyDescriptors(apiLevel);
	}

	/**
	 * Returns the line number corresponding to the given source character
	 * position in the original source string. The initial line of the
	 * compilation unit is numbered 1, and each line extends through the
	 * last character of the end-of-line delimiter. The very last line extends
	 * through the end of the source string and has no line delimiter.
	 * For example, the source string <code>class A\n{\n}</code> has 3 lines
	 * corresponding to inclusive character ranges [0,7], [8,9], and [10,10].
	 * Returns 1 for a character position that does not correspond to any
	 * source line, or if no line number information is available for this
	 * compilation unit.
	 *
	 * @param position a 0-based character position, possibly
	 *   negative or out of range
	 * @return the 1-based line number, or <code>1</code> if the character
	 *    position does not correspond to a source line in the original
	 *    source file or if line number information is not known for this
	 *    compilation unit
	 * @deprecated Use getLineNumber(int) instead. Be careful to handle the negative values.
	 * @see ASTParser
	 * @see #getLineNumber(int)
	 */
	public int lineNumber(int position) {
		int lineNumber = getLineNumber(position);
		return lineNumber < 1 ? 1 : lineNumber;
	}

	/**
	 * Returns the line number corresponding to the given source character
	 * position in the original source string. The initial line of the
	 * compilation unit is numbered 1, and each line extends through the
	 * last character of the end-of-line delimiter. The very last line extends
	 * through the end of the source string and has no line delimiter.
	 * For example, the source string <code>class A\n{\n}</code> has 3 lines
	 * corresponding to inclusive character ranges [0,7], [8,9], and [10,10].
	 * Returns -1 for a character position that does not correspond to any
	 * source line, or -2 if no line number information is available for this
	 * compilation unit.
	 *
	 * @param position a 0-based character position, possibly
	 *   negative or out of range
	 * @return the 1-based line number, or <code>-1</code> if the character
	 *    position does not correspond to a source line in the original
	 *    source file or <code>-2</code> if line number information is not known for this
	 *    compilation unit
	 * @see ASTParser
	 * @since 3.2
	 */
	public int getLineNumber(int position) {
		if (this.lineEndTable == null) return -2;
		int length;
		if ((length = this.lineEndTable.length) == 0) {
			if (position >= getStartPosition() + getLength()) {
				return -1;
			}
			return 1;
		}
		int low = 0;
		if (position < 0) {
			// position illegal
			return -1;
		}
		if (position <= this.lineEndTable[low]) {
			// before the first line delimiter
			return 1;
		}
		// assert position > lineEndTable[low+1]  && low == 0
		int hi = length - 1;
		if (position > this.lineEndTable[hi]) {
			// position beyond the last line separator
			if (position >= getStartPosition() + getLength()) {
				// this is beyond the end of the source length
				return -1;
			} else {
				return length + 1;
			}
		}
		// assert lineEndTable[low]  < position <= lineEndTable[hi]
		// && low == 0 && hi == length - 1 && low < hi

		// binary search line end table
		while (true) {
			// invariant lineEndTable[low] < position <= lineEndTable[hi]
			// && 0 <= low < hi <= length - 1
			// reducing measure hi - low
			if (low + 1 == hi) {
				// assert lineEndTable[low] < position <= lineEndTable[low+1]
				// position is on line low+1 (line number is low+2)
				return low + 2;
			}
			// assert hi - low >= 2, so average is truly in between
			int mid = low + (hi - low) / 2;
			// assert 0 <= low < mid < hi <= length - 1
			if (position <= this.lineEndTable[mid]) {
				// assert lineEndTable[low] < position <= lineEndTable[mid]
				// && 0 <= low < mid < hi <= length - 1
				hi = mid;
			} else {
				// position > lineEndTable[mid]
				// assert lineEndTable[mid] < position <= lineEndTable[hi]
				// && 0 <= low < mid < hi <= length - 1
				low = mid;
			}
			// in both cases, invariant reachieved with reduced measure
		}
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	int memSize() {
		int size = BASE_NODE_SIZE + 8 * 4;
		if (this.lineEndTable != null) {
			size += HEADERS + 4 * this.lineEndTable.length;
		}
		if (this.optionalCommentTable != null) {
			size += HEADERS + 4 * this.optionalCommentTable.length;
		}
		// ignore the space taken up by optionalCommentList
		return size;
	}

	/**
	 * Enables the recording of changes to this compilation
	 * unit and its descendents. The compilation unit must have
	 * been created by <code>ASTParser</code> and still be in
	 * its original state. Once recording is on,
	 * arbitrary changes to the subtree rooted at this compilation
	 * unit are recorded internally. Once the modification has
	 * been completed, call <code>rewrite</code> to get an object
	 * representing the corresponding edits to the original
	 * source code string.
	 *
	 * @exception IllegalArgumentException if this compilation unit is
	 * marked as unmodifiable, or if this compilation unit has already
	 * been tampered with, or recording has already been enabled
	 * @since 3.0
	 */
	public void recordModifications() {
		getAST().recordModifications(this);
	}

	/**
	 * Converts all modifications recorded for this compilation
	 * unit into an object representing the corresponding text
	 * edits to the given document containing the original source
	 * code for this compilation unit.
	 * <p>
	 * The compilation unit must have been created by
	 * <code>ASTParser</code> from the source code string in the
	 * given document, and recording must have been turned
	 * on with a prior call to <code>recordModifications</code>
	 * while the AST was still in its original state.
	 * </p>
	 * <p>
	 * Calling this methods does not discard the modifications
	 * on record. Subsequence modifications made to the AST
	 * are added to the ones already on record. If this method
	 * is called again later, the resulting text edit object will
	 * accurately reflect the net cumulative effect of all those
	 * changes.
	 * </p>
	 *
	 * @param document original document containing source code
	 * for this compilation unit
	 * @param options the table of formatter options
	 * (key type: <code>String</code>; value type: <code>String</code>);
	 * or <code>null</code> to use the standard global options
	 * {@link org.eclipse.jdt.core.JavaCore#getOptions() JavaCore.getOptions()}.
	 * @return text edit object describing the changes to the
	 * document corresponding to the recorded AST modifications
	 * @exception IllegalArgumentException if the document passed is
	 * <code>null</code> or does not correspond to this AST
	 * @exception IllegalStateException if <code>recordModifications</code>
	 * was not called to enable recording
	 * @see #recordModifications()
	 * @since 3.0
	 */
	public TextEdit rewrite(IDocument document, Map options) {
		return getAST().rewrite(document, options);
	}

	/**
	 * Sets the list of the comments encountered while parsing
	 * this compilation unit.
	 *
	 * @param commentTable a list of comments in increasing order
	 * of source start position, or <code>null</code> if comment
	 * information for this compilation unit is not available
	 * @exception IllegalArgumentException if the comment table is
	 * not in increasing order of source position
	 * @see #getCommentList()
	 * @see ASTParser
	 * @since 3.0
	 */
	void setCommentTable(Comment[] commentTable) {
		// double check table to ensure that all comments have
		// source positions and are in strictly increasing order
		if (commentTable == null) {
			this.optionalCommentList = null;
			this.optionalCommentTable = null;
		} else {
			int nextAvailablePosition = 0;
			for (int i = 0; i < commentTable.length; i++) {
				Comment comment = commentTable[i];
				if (comment == null) {
					throw new IllegalArgumentException();
				}
				int start = comment.getStartPosition();
				int length = comment.getLength();
				if (start < 0 || length < 0 || start < nextAvailablePosition) {
					throw new IllegalArgumentException();
				}
				nextAvailablePosition = comment.getStartPosition() + comment.getLength();
			}
			this.optionalCommentTable = commentTable;
			List commentList = Arrays.asList(commentTable);
			// protect the list from further modification
			this.optionalCommentList = Collections.unmodifiableList(commentList);
		}
	}

	/**
	 * Sets the Java type root (a {@link org.eclipse.jdt.core.ICompilationUnit compilation unit} or a {@link org.eclipse.jdt.core.IClassFile class file})
	 * this compilation unit was created from, or <code>null</code> if it was not created from a Java type root.
	 *
	 * @param typeRoot the Java type root this compilation unit was created from
	 */
	void setTypeRoot(ITypeRoot typeRoot) {
		this.typeRoot = typeRoot;
	}

	/**
	 * Sets the line end table for this compilation unit.
	 * If <code>lineEndTable[i] == p</code> then line number <code>i+1</code>
	 * ends at character position <code>p</code>. Except for the last line, the
	 * positions are that of (the last character of) the line delimiter.
	 * For example, the source string <code>A\nB\nC</code> has
	 * line end table {1, 3, 4}.
	 *
	 * @param lineEndTable the line end table
	 */
	void setLineEndTable(int[] lineEndTable) {
		if (lineEndTable == null) {
			throw new NullPointerException();
		}
		// alternate root is *not* considered a structural property
		// but we protect them nevertheless
		checkModifiable();
		this.lineEndTable = lineEndTable;
	}

	/**
	 * Sets or clears the package declaration of this compilation unit
	 * node to the given package declaration node.
	 *
	 * @param pkgDecl the new package declaration node, or
	 *   <code>null</code> if this compilation unit does not have a package
	 *   declaration (that is in the default package)
	 * @exception IllegalArgumentException if:
	 * <ul>
	 * <li>the node belongs to a different AST</li>
	 * <li>the node already has a parent</li>
	 * </ul>
	 */
	public void setPackage(PackageDeclaration pkgDecl) {
		ASTNode oldChild = this.optionalPackageDeclaration;
		preReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
		this.optionalPackageDeclaration = pkgDecl;
		postReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
	}


	/**
	 * Sets the array of problems reported by the compiler during the parsing or
	 * name resolution of this compilation unit.
	 *
	 * @param problems the list of problems
	 */
	void setProblems(IProblem[] problems) {
		if (problems == null) {
			throw new IllegalArgumentException();
		}
		this.problems = problems;
	}

	/**
	 * Internal method
	 *
	 * Sets internal data used to perform statements recovery.
	 * @param data
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 * @since 3.5
	 */
	void setStatementsRecoveryData(Object data) {
		this.statementsRecoveryData = data;
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
		// dispatch to correct overloaded match method
		return matcher.match(this, other);
	}

	/* (omit javadoc for this method)
	 * Method declared on ASTNode.
	 */
	int treeSize() {
		int size = memSize();
		if (this.optionalPackageDeclaration != null) {
			size += getPackage().treeSize();
		}
		size += this.imports.listSize();
		size += this.types.listSize();
		// include disconnected comments
		if (this.optionalCommentList != null) {
			for (int i = 0; i < this.optionalCommentList.size(); i++) {
				Comment comment = (Comment) this.optionalCommentList.get(i);
				if (comment != null && comment.getParent() == null) {
					size += comment.treeSize();
				}
			}
		}
		return size;
	}

	/**
	 * Returns the live list of nodes for the top-level type declarations of this
	 * compilation unit, in order of appearance.
     * <p>
     * Note that in JLS3, the types may include both enum declarations
     * and annotation type declarations introduced in J2SE 5.
     * For JLS2, the elements are always <code>TypeDeclaration</code>.
     * </p>
	 *
	 * @return the live list of top-level type declaration
	 *    nodes (element type: {@link AbstractTypeDeclaration})
	 */
	public List types() {
		return this.types;
	}
}

