Initial upgrade to Platform/JDT 3.4.1
authorincastrix <incastrix>
Sat, 12 Sep 2009 22:04:55 +0000 (22:04 +0000)
committerincastrix <incastrix>
Sat, 12 Sep 2009 22:04:55 +0000 (22:04 +0000)
143 files changed:
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/compiler/CategorizedProblem.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AST.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTConverter.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTMatcher.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTNode.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTParser.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTRecoveryPropagator.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTRequestor.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTSyntaxErrorPropagator.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTVisitor.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AbstractTypeDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Annotation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnnotationBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnnotationTypeDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnnotationTypeMemberDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnonymousClassDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayAccess.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayCreation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayInitializer.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayType.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AssertStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Assignment.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BindingComparator.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BindingResolver.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Block.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BlockComment.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BodyDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BooleanLiteral.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BreakStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CastExpression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CatchClause.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CharacterLiteral.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ChildListPropertyDescriptor.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ChildPropertyDescriptor.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ClassInstanceCreation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Comment.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CompilationUnitResolver.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ConditionalExpression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ConstructorInvocation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ContinueStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultASTVisitor.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultBindingResolver.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultCommentMapper.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultValuePairBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DoStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DocCommentParser.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EmptyStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EnhancedForStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EnumConstantDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EnumDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Expression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ExpressionStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/FieldAccess.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/FieldDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ForStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IAnnotationBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IDocElement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IExtendedModifier.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IMemberValuePairBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IMethodBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IPackageBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ITypeBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IVariableBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IfStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ImportDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/InfixExpression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Initializer.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/InstanceofExpression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/InternalASTRewrite.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Javadoc.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/LabeledStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/LineComment.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MarkerAnnotation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MemberRef.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MemberValuePair.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MemberValuePairBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Message.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodInvocation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodRef.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodRefParameter.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Modifier.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Name.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NodeEventHandler.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NodeSearcher.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NormalAnnotation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NullLiteral.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NumberLiteral.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PackageBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PackageDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ParameterizedType.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ParenthesizedExpression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PostfixExpression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PrefixExpression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PrimitiveType.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/QualifiedName.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/QualifiedType.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/RecoveredTypeBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/RecoveredVariableBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ReturnStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SimpleName.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SimplePropertyDescriptor.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SimpleType.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SingleMemberAnnotation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SingleVariableDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Statement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/StringLiteral.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/StructuralPropertyDescriptor.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SuperConstructorInvocation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SuperFieldAccess.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SuperMethodInvocation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SwitchCase.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SwitchStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SynchronizedStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TagElement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TextElement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ThisExpression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ThrowStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TryStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Type.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeDeclarationStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeLiteral.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeParameter.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclaration.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclarationExpression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclarationFragment.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclarationStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/WhileStatement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/WildcardType.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/Annotation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/ClassLiteralAccess.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/MemberValuePair.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/classfmt/ClassFileConstants.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/AnnotationBinding.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/ElementValuePair.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/TerminalTokens.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/dom/NaiveASTFlattener.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/RecordedParsingInformation.java [new file with mode: 0644]

diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/compiler/CategorizedProblem.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/compiler/CategorizedProblem.java
new file mode 100644 (file)
index 0000000..daab6ff
--- /dev/null
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.compiler;
+
+import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblem;
+
+/**
+ * Richer description of a Java problem, as detected by the compiler or some of the underlying
+ * technology reusing the compiler. With the introduction of <code>org.eclipse.jdt.core.compiler.CompilationParticipant</code>,
+ * the simpler problem interface {@link IProblem} did not carry enough information to better
+ * separate and categorize Java problems. In order to minimize impact on existing API, Java problems
+ * are still passed around as {@link IProblem}, though actual implementations should explicitly
+ * extend {@link CategorizedProblem}. Participants can produce their own problem definitions,
+ * and given these are categorized problems, they can be better handled by clients (such as user
+ * interface).
+ * <p>
+ * A categorized problem provides access to:
+ * <ul>
+ * <li> its location (originating source file name, source position, line number), </li>
+ * <li> its message description and a predicate to check its severity (warning or error). </li>
+ * <li> its ID : a number identifying the very nature of this problem. All possible IDs for standard Java 
+ * problems are listed as constants on {@link IProblem}, </li>
+ * <li> its marker type : a string identifying the problem creator. It corresponds to the marker type
+ * chosen if this problem was to be persisted. Standard Java problems are associated to marker
+ * type "org.eclipse.jdt.core.problem"), </li>
+ * <li> its category ID : a number identifying the category this problem belongs to. All possible IDs for 
+ * standard Java problem categories are listed in this class. </li>
+ * </ul>
+ * <p>
+ * Note: the compiler produces IProblems internally, which are turned into markers by the JavaBuilder
+ * so as to persist problem descriptions. This explains why there is no API allowing to reach IProblem detected
+ * when compiling. However, the Java problem markers carry equivalent information to IProblem, in particular
+ * their ID (attribute "id") is set to one of the IDs defined on this interface.
+ * <p>
+ * Note: Standard Java problems produced by Java default tooling will be subclasses of this class. Technically, most
+ * API methods dealing with problems are referring to {@link IProblem} for backward compatibility reason.
+ * It is intended that {@link CategorizedProblem} will be subclassed for custom problem implementation when
+ * participating in compilation operations, so as to allow participant to contribute their own marker types, and thus
+ * defining their own domain specific problem/category IDs.
+ * <p>
+ * Note: standard Java problems produced by Java default tooling will set the marker
+ * <code> IMarker#SOURCE_ID</code> attribute to
+ * <code> JavaBuilder#SOURCE_ID</code>; compiler
+ * participants may specify the <code> IMarker#SOURCE_ID</code>
+ * attribute of their markers by adding it to the extra marker attributes of the problems they generate; 
+ * markers resulting from compiler participants' problems that do not have the
+ * <code> IMarker#SOURCE_ID</code> extra attribute set do not have the
+ * <code> JavaBuilder#SOURCE_ID</code> attribute set either.
+ * 
+ * @since 3.2
+ */
+public abstract class CategorizedProblem implements IProblem {
+       
+       /**
+        * List of standard category IDs used by Java problems, more categories will be added 
+        * in the future.
+        */
+       public static final int CAT_UNSPECIFIED = 0;
+       /** Category for problems related to buildpath */
+       public static final int CAT_BUILDPATH = 10;
+       /** Category for fatal problems related to syntax */
+       public static final int CAT_SYNTAX = 20;
+       /** Category for fatal problems in import statements */
+       public static final int CAT_IMPORT = 30;
+       /** Category for fatal problems related to types, could be addressed by some type change */
+       public static final int CAT_TYPE = 40;
+       /** Category for fatal problems related to type members, could be addressed by some field or method change */
+       public static final int CAT_MEMBER = 50;
+       /** Category for fatal problems which could not be addressed by external changes, but require an edit to be addressed */
+       public static final int CAT_INTERNAL = 60;      
+       /** Category for optional problems in Javadoc */
+       public static final int CAT_JAVADOC = 70;
+       /** Category for optional problems related to coding style practices */
+       public static final int CAT_CODE_STYLE = 80;
+       /** Category for optional problems related to potential programming flaws */
+       public static final int CAT_POTENTIAL_PROGRAMMING_PROBLEM = 90;
+       /** Category for optional problems related to naming conflicts */
+       public static final int CAT_NAME_SHADOWING_CONFLICT = 100;
+       /** Category for optional problems related to deprecation */
+       public static final int CAT_DEPRECATION = 110;
+       /** Category for optional problems related to unnecessary code */
+       public static final int CAT_UNNECESSARY_CODE = 120;
+       /** Category for optional problems related to type safety in generics */
+       public static final int CAT_UNCHECKED_RAW = 130;
+       /** Category for optional problems related to internationalization of String literals */
+       public static final int CAT_NLS = 140;
+       /** Category for optional problems related to access restrictions */
+       public static final int CAT_RESTRICTION = 150;  
+       
+/** 
+ * Returns an integer identifying the category of this problem. Categories, like problem IDs are
+ * defined in the context of some marker type. Custom implementations of {@link CategorizedProblem}
+ * may choose arbitrary values for problem/category IDs, as long as they are associated with a different
+ * marker type.
+ * Standard Java problem markers (i.e. marker type is "org.eclipse.jdt.core.problem") carry an
+ * attribute "categoryId" persisting the originating problem category ID as defined by this method).
+ * @return id - an integer identifying the category of this problem
+ */
+public abstract int getCategoryID();
+
+/**
+ * Returns the marker type associated to this problem, if it gets persisted into a marker by the JavaBuilder
+ * Standard Java problems are associated to marker type "org.eclipse.jdt.core.problem").
+ * Note: problem markers are expected to extend "org.eclipse.core.resources.problemmarker" marker type.
+ * @return the type of the marker which would be associated to the problem
+ */
+public abstract String getMarkerType();
+
+/**
+ * Returns the names of the extra marker attributes associated to this problem when persisted into a marker 
+ * by the JavaBuilder. Extra attributes are only optional, and are allowing client customization of generated
+ * markers. By default, no EXTRA attributes is persisted, and a categorized problem only persists the following attributes:
+ * <ul>
+ * <li>        <code>IMarker#MESSAGE</code> -&gt; {@link IProblem#getMessage()}</li>
+ * <li>        <code>IMarker#SEVERITY</code> -&gt; <code> IMarker#SEVERITY_ERROR</code> or 
+ *         <code>IMarker#SEVERITY_WARNING</code> depending on {@link IProblem#isError()} or {@link IProblem#isWarning()}</li>
+ * <li>        <code>IJavaModelMarker#ID</code> -&gt; {@link IProblem#getID()}</li>
+ * <li>        <code>IMarker#CHAR_START</code>  -&gt; {@link IProblem#getSourceStart()}</li>
+ * <li>        <code>IMarker#CHAR_END</code>  -&gt; {@link IProblem#getSourceEnd()}</li>
+ * <li>        <code>IMarker#LINE_NUMBER</code>  -&gt; {@link IProblem#getSourceLineNumber()}</li>
+ * <li>        <code>IJavaModelMarker#ARGUMENTS</code>  -&gt; some <code>String[]</code> used to compute quickfixes </li>
+ * <li>        <code>IJavaModelMarker#CATEGORY_ID</code> -&gt; {@link CategorizedProblem#getCategoryID()}</li>
+ * </ul>
+ * The names must be eligible for marker creation, as defined by <code>IMarker#setAttributes(String[], Object[])</code>, 
+ * and there must be as many names as values according to {@link #getExtraMarkerAttributeValues()}.
+ * Note that extra marker attributes will be inserted after default ones (as described in {@link CategorizedProblem#getMarkerType()},
+ * and thus could be used to override defaults.
+ * @return the names of the corresponding marker attributes
+ */
+public String[] getExtraMarkerAttributeNames() {
+       return CharOperation.NO_STRINGS;
+}
+
+/**
+ * Returns the respective values for the extra marker attributes associated to this problem when persisted into 
+ * a marker by the JavaBuilder. Each value must correspond to a matching attribute name, as defined by
+ * {@link #getExtraMarkerAttributeNames()}. 
+ * The values must be eligible for marker creation, as defined by <code> IMarker#setAttributes(String[], Object[])}.
+ * @return the values of the corresponding extra marker attributes
+ */
+public Object[] getExtraMarkerAttributeValues() {
+       return DefaultProblem.EMPTY_VALUES;
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AST.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AST.java
new file mode 100644 (file)
index 0000000..4e01873
--- /dev/null
@@ -0,0 +1,2897 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import net.sourceforge.phpdt.core.IClassFile;
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ * Umbrella owner and abstract syntax tree node factory.
+ * An <code>AST</code> instance serves as the common owner of any number of
+ * AST nodes, and as the factory for creating new AST nodes owned by that 
+ * instance.
+ * <p>
+ * Abstract syntax trees may be hand constructed by clients, using the
+ * <code>new<i>TYPE</i></code> factory methods to create new nodes, and the
+ * various <code>set<i>CHILD</i></code> methods 
+ * (see {@link org.eclipse.jdt.core.dom.ASTNode ASTNode} and its subclasses)
+ * to connect them together.
+ * </p>
+ * <p>
+ * Each AST node belongs to a unique AST instance, called the owning AST.
+ * The children of an AST node always have the same owner as their parent node.
+ * If a node from one AST is to be added to a different AST, the subtree must
+ * be cloned first to ensures that the added nodes have the correct owning AST.
+ * </p>
+ * <p>
+ * There can be any number of AST nodes owned by a single AST instance that are
+ * unparented. Each of these nodes is the root of a separate little tree of nodes.
+ * The method <code>ASTNode.getRoot()</code> navigates from any node to the root
+ * of the tree that it is contained in. Ordinarily, an AST instance has one main
+ * tree (rooted at a <code>CompilationUnit</code>), with newly-created nodes appearing
+ * as additional roots until they are parented somewhere under the main tree.
+ * One can navigate from any node to its AST instance, but not conversely.
+ * </p>
+ * <p>
+ * The class {@link ASTParser} parses a string
+ * containing a Java source code and returns an abstract syntax tree
+ * for it. The resulting nodes carry source ranges relating the node back to
+ * the original source characters.
+ * </p>
+ * <p>
+ * Compilation units created by <code>ASTParser</code> from a
+ * source document can be serialized after arbitrary modifications
+ * with minimal loss of original formatting. Here is an example:
+ * <pre>
+ * Document doc = new Document("import java.util.List;\nclass X {}\n");
+ * ASTParser parser = ASTParser.newParser(AST.JLS3);
+ * parser.setSource(doc.get().toCharArray());
+ * CompilationUnit cu = (CompilationUnit) parser.createAST(null);
+ * cu.recordModifications();
+ * AST ast = cu.getAST();
+ * ImportDeclaration id = ast.newImportDeclaration();
+ * id.setName(ast.newName(new String[] {"java", "util", "Set"});
+ * cu.imports().add(id); // add import declaration at end
+ * TextEdit edits = cu.rewrite(document, null);
+ * UndoEdit undo = edits.apply(document);
+ * </pre>
+ * See also {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite} for
+ * an alternative way to describe and serialize changes to a
+ * read-only AST.
+ * </p>
+ * <p>
+ * Clients may create instances of this class using {@link #newAST(int)}, 
+ * but this class is not intended to be subclassed.
+ * </p>
+ * 
+ * @see ASTParser
+ * @see ASTNode
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class AST {
+       /**
+        * Constant for indicating the AST API that handles JLS2.
+        * This API is capable of handling all constructs
+        * in the Java language as described in the Java Language
+     * Specification, Second Edition (JLS2).
+     * JLS2 is a superset of all earlier versions of the
+     * Java language, and the JLS2 API can be used to manipulate
+     * programs written in all versions of the Java language
+     * up to and including J2SE 1.4.
+     *
+        * @since 3.0
+        * @deprecated Clients should use the {@link #JLS3} AST API instead.
+        */
+       public static final int JLS2 = 2;
+       
+       /**
+        * Internal synonym for {@link #JLS2}. Use to alleviate
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ static final int JLS2_INTERNAL = JLS2;
+
+       /**
+        * Constant for indicating the AST API that handles JLS3.
+        * This API is capable of handling all constructs in the
+        * Java language as described in the Java Language
+        * Specification, Third Edition (JLS3).
+     * JLS3 is a superset of all earlier versions of the
+     * Java language, and the JLS3 API can be used to manipulate
+     * programs written in all versions of the Java language
+     * up to and including J2SE 5 (aka JDK 1.5). 
+     *
+        * @since 3.1
+        */
+       public static final int JLS3 = 3;
+       
+       /**
+        * The binding resolver for this AST. Initially a binding resolver that
+        * does not resolve names at all.
+        */
+       private BindingResolver resolver = new BindingResolver();
+       
+       /**
+        * The event handler for this AST. 
+        * Initially an event handler that does not nothing.
+        * @since 3.0
+        */
+       private NodeEventHandler eventHandler = new NodeEventHandler();
+       
+       /**
+        * Level of AST API supported by this AST.
+        * @since 3.0
+        */
+       int apiLevel;
+       
+       /**
+        * Internal modification count; initially 0; increases monotonically
+        * <b>by one or more</b> as the AST is successively modified.
+        */
+       private long modificationCount = 0;
+       
+       /**
+        * Internal original modification count; value is equals to <code>
+        * modificationCount</code> at the end of the parse (<code>ASTParser
+        * </code>). If this ast is not created with a parser then value is 0.
+        * @since 3.0
+        */
+       private long originalModificationCount = 0;
+
+       /**
+        * When disableEvents > 0, events are not reported and
+        * the modification count stays fixed.
+        * <p>
+        * This mechanism is used in lazy initialization of a node
+        * to prevent events from being reported for the modification
+        * of the node as well as for the creation of the missing child.
+        * </p>
+        * @since 3.0
+        */
+       private int disableEvents = 0;
+
+       /**
+        * Internal object unique to the AST instance. Readers must synchronize on
+        * this object when the modifying instance fields.
+        * @since 3.0
+        */
+       private final Object internalASTLock = new Object();
+
+       /**
+        * Java Scanner used to validate preconditions for the creation of specific nodes
+        * like CharacterLiteral, NumberLiteral, StringLiteral or SimpleName.
+        */
+       Scanner scanner;
+
+       /**
+        * Internal ast rewriter used to record ast modification when record mode is enabled.
+        */
+       InternalASTRewrite rewriter;
+
+       /**
+        * Default value of <code>flag<code> when a new node is created.
+        */
+       private int defaultNodeFlag = 0;
+
+       /**
+        * Creates a new Java abstract syntax tree
+     * (AST) following the specified set of API rules.
+     *
+        * @param level the API level; one of the LEVEL constants
+     * @since 3.0
+        */
+       private AST(int level) {
+               if ((level != AST.JLS2)
+                       && (level != AST.JLS3)) {
+                       throw new IllegalArgumentException();
+               }
+               this.apiLevel = level;
+               // initialize a scanner
+               this.scanner = new Scanner(
+                               true /*comment*/,
+                               true /*whitespace*/,
+                               false /*nls*/,
+                               ClassFileConstants.JDK1_3 /*sourceLevel*/,
+                               ClassFileConstants.JDK1_5 /*complianceLevel*/,
+                               null/*taskTag*/,
+                               null/*taskPriorities*/,
+                               true/*taskCaseSensitive*/);
+       }
+
+       /**
+        * Creates a new, empty abstract syntax tree using default options.
+        *
+        * @see JavaCore#getDefaultOptions()
+        * @deprecated Clients should port their code to use the new JLS3 AST API and call
+        *    {@link #newAST(int) AST.newAST(AST.JLS3)} instead of using this constructor.
+        */
+       public AST() {
+               this(JavaCore.getDefaultOptions());
+       }
+
+       /**
+        * Internal method.
+        * <p>
+        * This method converts the given internal compiler AST for the given source string
+        * into a compilation unit. This method is not intended to be called by clients.
+        * </p>
+        *
+        * @param level the API level; one of the LEVEL constants
+        * @param compilationUnitDeclaration an internal AST node for a compilation unit declaration
+        * @param options compiler options
+        * @param workingCopy the working copy that the AST is created from
+        * @param monitor the progress monitor used to report progress and request cancellation,
+        *     or <code>null</code> if none
+        * @param isResolved whether the given compilation unit declaration is resolved
+        * @return the compilation unit node
+        * @since 3.4
+        * @noreference This method is not intended to be referenced by clients.
+        */
+       public static CompilationUnit convertCompilationUnit(
+               int level,
+               net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration,
+               Map options,
+               boolean isResolved,
+               net.sourceforge.phpdt.internal.core.CompilationUnit workingCopy,
+               int reconcileFlags,
+               IProgressMonitor monitor) {
+
+               ASTConverter converter = new ASTConverter(options, isResolved, monitor);
+               AST ast = AST.newAST(level);
+               int savedDefaultNodeFlag = ast.getDefaultNodeFlag();
+               ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+               BindingResolver resolver = null;
+               if (isResolved) {
+                       resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope, workingCopy.owner, new DefaultBindingResolver.BindingTables(), false);
+                       ((DefaultBindingResolver) resolver).isRecoveringBindings = (reconcileFlags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0;
+                       ast.setFlag(AST.RESOLVED_BINDINGS);
+               } else {
+                       resolver = new BindingResolver();
+               }
+               ast.setFlag(reconcileFlags);
+               ast.setBindingResolver(resolver);
+               converter.setAST(ast);
+
+               CompilationUnit unit = converter.convert(compilationUnitDeclaration, workingCopy.getContents());
+               unit.setLineEndTable(compilationUnitDeclaration.compilationResult.getLineSeparatorPositions());
+               unit.setTypeRoot(workingCopy.originalFromClone());
+               ast.setDefaultNodeFlag(savedDefaultNodeFlag);
+               return unit;
+       }
+
+       /**
+        * Internal method.
+        * <p>
+        * This method converts the given internal compiler AST for the given source string
+        * into a compilation unit. This method is not intended to be called by clients.
+        * </p>
+        *
+        * @param level the API level; one of the LEVEL constants
+        * @param compilationUnitDeclaration an internal AST node for a compilation unit declaration
+        * @param source the string of the Java compilation unit
+        * @param options compiler options
+        * @param workingCopy the working copy that the AST is created from
+        * @param monitor the progress monitor used to report progress and request cancellation,
+        *     or <code>null</code> if none
+        * @param isResolved whether the given compilation unit declaration is resolved
+        * @return the compilation unit node
+        * @deprecated Use org.eclipse.jdt.core.dom.AST.convertCompilationUnit(int, CompilationUnitDeclaration, Map, boolean, CompilationUnit, int, IProgressMonitor) instead
+        * @noreference This method is not intended to be referenced by clients.
+        */
+       public static CompilationUnit convertCompilationUnit(
+                       int level,
+                       net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration,
+                       char[] source,
+                       Map options,
+                       boolean isResolved,
+                       net.sourceforge.phpdt.internal.core.CompilationUnit workingCopy,
+                       int reconcileFlags,
+                       IProgressMonitor monitor) {
+               return null;
+       }
+       
+       /**
+        * Creates a new, empty abstract syntax tree using the given options.
+        * <p>
+        * Following option keys are significant:
+        * <ul>
+        * <li><code>"org.eclipse.jdt.core.compiler.source"</code> -
+        *    indicates source compatibility mode (as per <code>JavaCore</code>);
+        *    <code>"1.3"</code> means the source code is as per JDK 1.3;
+        *    <code>"1.4"</code> means the source code is as per JDK 1.4
+        *    (<code>"assert"</code> is now a keyword);
+        *    <code>"1.5"</code> means the source code is as per JDK 1.5
+        *    (<code>"enum"</code> is now a keyword);
+        *    additional legal values may be added later. </li>
+        * </ul>
+        * Options other than the above are ignored.
+        * </p>
+        *
+        * @param options the table of options (key type: <code>String</code>;
+        *    value type: <code>String</code>)
+        * @see JavaCore#getDefaultOptions()
+        * @deprecated Clients should port their code to use the new JLS3 AST API and call
+        *    {@link #newAST(int) AST.newAST(AST.JLS3)} instead of using this constructor.
+        */
+       public AST(Map options) {
+               this(JLS2);
+               Object sourceLevelOption = options.get(JavaCore.COMPILER_SOURCE);
+               long sourceLevel = ClassFileConstants.JDK1_3;
+               if (JavaCore.VERSION_1_4.equals(sourceLevelOption)) {
+                       sourceLevel = ClassFileConstants.JDK1_4;
+               } else if (JavaCore.VERSION_1_5.equals(sourceLevelOption)) {
+                       sourceLevel = ClassFileConstants.JDK1_5;
+               }
+               Object complianceLevelOption = options.get(JavaCore.COMPILER_COMPLIANCE);
+               long complianceLevel = ClassFileConstants.JDK1_3;
+               if (JavaCore.VERSION_1_4.equals(complianceLevelOption)) {
+                       complianceLevel = ClassFileConstants.JDK1_4;
+               } else if (JavaCore.VERSION_1_5.equals(complianceLevelOption)) {
+                       complianceLevel = ClassFileConstants.JDK1_5;
+               }
+               // override scanner if 1.4 or 1.5 asked for
+               this.scanner = new Scanner(
+                       true /*comment*/,
+                       true /*whitespace*/,
+                       false /*nls*/,
+                       sourceLevel /*sourceLevel*/,
+                       complianceLevel /*complianceLevel*/,
+                       null/*taskTag*/,
+                       null/*taskPriorities*/,
+                       true/*taskCaseSensitive*/);
+       }
+
+       /**
+        * Creates a new Java abstract syntax tree
+     * (AST) following the specified set of API rules.
+     * <p>
+     * Clients should use this method specifing {@link #JLS3} as the
+     * AST level in all cases, even when dealing with JDK 1.3 or 1.4..
+     * </p>
+     *
+        * @param level the API level; one of the LEVEL constants
+        * @return new AST instance following the specified set of API rules.
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the API level is not one of the LEVEL constants</li>
+        * </ul>
+     * @since 3.0
+        */
+       public static AST newAST(int level) {
+               if ((level != AST.JLS2)
+                       && (level != AST.JLS3)) {
+                       throw new IllegalArgumentException();
+               }
+               return new AST(level);
+       }
+
+       /**
+        * Returns the modification count for this AST. The modification count
+        * is a non-negative value that increases (by 1 or perhaps by more) as
+        * this AST or its nodes are changed. The initial value is unspecified.
+        * <p>
+        * The following things count as modifying an AST:
+        * <ul>
+        * <li>creating a new node owned by this AST,</li>
+        * <li>adding a child to a node owned by this AST,</li>
+        * <li>removing a child from a node owned by this AST,</li>
+        * <li>setting a non-node attribute of a node owned by this AST.</li>
+        * </ul>
+        * </p>
+        * Operations which do not entail creating or modifying existing nodes
+        * do not increase the modification count.
+        * <p>
+        * N.B. This method may be called several times in the course
+        * of a single client operation. The only promise is that the modification
+        * count increases monotonically as the AST or its nodes change; there is
+        * no promise that a modifying operation increases the count by exactly 1.
+        * </p>
+        *
+        * @return the current value (non-negative) of the modification counter of
+        *    this AST
+        */
+       public long modificationCount() {
+               return this.modificationCount;
+       }
+
+       /**
+        * Return the API level supported by this AST.
+        *
+        * @return level the API level; one of the <code>JLS*</code>LEVEL
+     * declared on <code>AST</code>; assume this set is open-ended
+     * @since 3.0
+        */
+       public int apiLevel() {
+               return this.apiLevel;
+       }
+
+       /**
+        * Indicates that this AST is about to be modified.
+        * <p>
+        * The following things count as modifying an AST:
+        * <ul>
+        * <li>creating a new node owned by this AST</li>
+        * <li>adding a child to a node owned by this AST</li>
+        * <li>removing a child from a node owned by this AST</li>
+        * <li>setting a non-node attribute of a node owned by this AST</li>.
+        * </ul>
+        * </p>
+        * <p>
+        * N.B. This method may be called several times in the course
+        * of a single client operation.
+        * </p>
+        */
+       void modifying() {
+               // when this method is called during lazy init, events are disabled
+               // and the modification count will not be increased
+               if (this.disableEvents > 0) {
+                       return;
+               }
+               // increase the modification count
+               this.modificationCount++;
+       }
+
+       /**
+     * Disable events.
+        * This method is thread-safe for AST readers.
+        *
+        * @see #reenableEvents()
+     * @since 3.0
+     */
+       final void disableEvents() {
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by another reader
+                       this.disableEvents++;
+               }
+               // while disableEvents > 0 no events will be reported, and mod count will stay fixed
+       }
+
+       /**
+     * Reenable events.
+        * This method is thread-safe for AST readers.
+        *
+        * @see #disableEvents()
+     * @since 3.0
+     */
+       final void reenableEvents() {
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by another reader
+                       this.disableEvents--;
+               }
+       }
+
+       /**
+        * Reports that the given node is about to lose a child.
+        *
+        * @param node the node about to be modified
+        * @param child the node about to be removed
+        * @param property the child or child list property descriptor
+        * @since 3.0
+        */
+       void preRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+               // IMPORTANT: this method is called by readers during lazy init
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by a reader doing lazy init
+                       if (this.disableEvents > 0) {
+                               // doing lazy init OR already processing an event
+                               // System.out.println("[BOUNCE DEL]");
+                               return;
+                       } else {
+                               disableEvents();
+                       }
+               }
+               try {
+                       this.eventHandler.preRemoveChildEvent(node, child, property);
+                       // N.B. even if event handler blows up, the AST is not
+                       // corrupted since node has not been changed yet
+               } finally {
+                       reenableEvents();
+               }
+       }
+
+       /**
+        * Reports that the given node jsut lost a child.
+        *
+        * @param node the node that was modified
+        * @param child the child node that was removed
+        * @param property the child or child list property descriptor
+        * @since 3.0
+        */
+       void postRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+               // IMPORTANT: this method is called by readers during lazy init
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by a reader doing lazy init
+                       if (this.disableEvents > 0) {
+                               // doing lazy init OR already processing an event
+                               // System.out.println("[BOUNCE DEL]");
+                               return;
+                       } else {
+                               disableEvents();
+                       }
+               }
+               try {
+                       this.eventHandler.postRemoveChildEvent(node, child, property);
+                       // N.B. even if event handler blows up, the AST is not
+                       // corrupted since node has not been changed yet
+               } finally {
+                       reenableEvents();
+               }
+       }
+
+       /**
+        * Reports that the given node is about have a child replaced.
+        *
+        * @param node the node about to be modified
+        * @param child the child node about to be removed
+        * @param newChild the replacement child
+        * @param property the child or child list property descriptor
+        * @since 3.0
+        */
+       void preReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+               // IMPORTANT: this method is called by readers during lazy init
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by a reader doing lazy init
+                       if (this.disableEvents > 0) {
+                               // doing lazy init OR already processing an event
+                               // System.out.println("[BOUNCE REP]");
+                               return;
+                       } else {
+                               disableEvents();
+                       }
+               }
+               try {
+                       this.eventHandler.preReplaceChildEvent(node, child, newChild, property);
+                       // N.B. even if event handler blows up, the AST is not
+                       // corrupted since node has not been changed yet
+               } finally {
+                       reenableEvents();
+               }
+       }
+
+       /**
+        * Reports that the given node has just had a child replaced.
+        *
+        * @param node the node modified
+        * @param child the child removed
+        * @param newChild the replacement child
+        * @param property the child or child list property descriptor
+        * @since 3.0
+        */
+       void postReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+               // IMPORTANT: this method is called by readers during lazy init
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by a reader doing lazy init
+                       if (this.disableEvents > 0) {
+                               // doing lazy init OR already processing an event
+                               // System.out.println("[BOUNCE REP]");
+                               return;
+                       } else {
+                               disableEvents();
+                       }
+               }
+               try {
+                       this.eventHandler.postReplaceChildEvent(node, child, newChild, property);
+                       // N.B. even if event handler blows up, the AST is not
+                       // corrupted since node has not been changed yet
+               } finally {
+                       reenableEvents();
+               }
+       }
+
+       /**
+        * Reports that the given node is about to gain a child.
+        *
+        * @param node the node that to be modified
+        * @param child the node that to be added as a child
+        * @param property the child or child list property descriptor
+        * @since 3.0
+        */
+       void preAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+               // IMPORTANT: this method is called by readers during lazy init
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by a reader doing lazy init
+                       if (this.disableEvents > 0) {
+                               // doing lazy init OR already processing an event
+                               // System.out.println("[BOUNCE ADD]");
+                               return;
+                       } else {
+                               disableEvents();
+                       }
+               }
+               try {
+                       this.eventHandler.preAddChildEvent(node, child, property);
+                       // N.B. even if event handler blows up, the AST is not
+                       // corrupted since node has already been changed
+               } finally {
+                       reenableEvents();
+               }
+       }
+
+       /**
+        * Reports that the given node has just gained a child.
+        *
+        * @param node the node that was modified
+        * @param child the node that was added as a child
+        * @param property the child or child list property descriptor
+        * @since 3.0
+        */
+       void postAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+               // IMPORTANT: this method is called by readers during lazy init
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by a reader doing lazy init
+                       if (this.disableEvents > 0) {
+                               // doing lazy init OR already processing an event
+                               // System.out.println("[BOUNCE ADD]");
+                               return;
+                       } else {
+                               disableEvents();
+                       }
+               }
+               try {
+                       this.eventHandler.postAddChildEvent(node, child, property);
+                       // N.B. even if event handler blows up, the AST is not
+                       // corrupted since node has already been changed
+               } finally {
+                       reenableEvents();
+               }
+       }
+
+       /**
+        * Reports that the given node is about to change the value of a
+        * non-child property.
+        *
+        * @param node the node to be modified
+        * @param property the property descriptor
+        * @since 3.0
+        */
+       void preValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+               // IMPORTANT: this method is called by readers during lazy init
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by a reader doing lazy init
+                       if (this.disableEvents > 0) {
+                               // doing lazy init OR already processing an event
+                               // System.out.println("[BOUNCE CHANGE]");
+                               return;
+                       } else {
+                               disableEvents();
+                       }
+               }
+               try {
+                       this.eventHandler.preValueChangeEvent(node, property);
+                       // N.B. even if event handler blows up, the AST is not
+                       // corrupted since node has already been changed
+               } finally {
+                       reenableEvents();
+               }
+       }
+
+       /**
+        * Reports that the given node has just changed the value of a
+        * non-child property.
+        *
+        * @param node the node that was modified
+        * @param property the property descriptor
+        * @since 3.0
+        */
+       void postValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+               // IMPORTANT: this method is called by readers during lazy init
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by a reader doing lazy init
+                       if (this.disableEvents > 0) {
+                               // doing lazy init OR already processing an event
+                               // System.out.println("[BOUNCE CHANGE]");
+                               return;
+                       } else {
+                               disableEvents();
+                       }
+               }
+               try {
+                       this.eventHandler.postValueChangeEvent(node, property);
+                       // N.B. even if event handler blows up, the AST is not
+                       // corrupted since node has already been changed
+               } finally {
+                       reenableEvents();
+               }
+       }
+
+       /**
+        * Reports that the given node is about to be cloned.
+        *
+        * @param node the node to be cloned
+        * @since 3.0
+        */
+       void preCloneNodeEvent(ASTNode node) {
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by a reader doing lazy init
+                       if (this.disableEvents > 0) {
+                               // doing lazy init OR already processing an event
+                               // System.out.println("[BOUNCE CLONE]");
+                               return;
+                       } else {
+                               disableEvents();
+                       }
+               }
+               try {
+                       this.eventHandler.preCloneNodeEvent(node);
+                       // N.B. even if event handler blows up, the AST is not
+                       // corrupted since node has already been changed
+               } finally {
+                       reenableEvents();
+               }
+       }
+
+       /**
+        * Reports that the given node has just been cloned.
+        *
+        * @param node the node that was cloned
+        * @param clone the clone of <code>node</code>
+        * @since 3.0
+        */
+       void postCloneNodeEvent(ASTNode node, ASTNode clone) {
+               synchronized (this.internalASTLock) {
+                       // guard against concurrent access by a reader doing lazy init
+                       if (this.disableEvents > 0) {
+                               // doing lazy init OR already processing an event
+                               // System.out.println("[BOUNCE CLONE]");
+                               return;
+                       } else {
+                               disableEvents();
+                       }
+               }
+               try {
+                       this.eventHandler.postCloneNodeEvent(node, clone);
+                       // N.B. even if event handler blows up, the AST is not
+                       // corrupted since node has already been changed
+               } finally {
+                       reenableEvents();
+               }
+       }
+
+       /**
+        * Parses the source string of the given Java model compilation unit element
+        * and creates and returns a corresponding abstract syntax tree. The source
+        * string is obtained from the Java model element using
+        * <code>ICompilationUnit.getSource()</code>.
+        * <p>
+        * The returned compilation unit node is the root node of a new AST.
+        * Each node in the subtree carries source range(s) information relating back
+        * to positions in the source string (the source string is not remembered
+        * with the AST).
+        * The source range usually begins at the first character of the first token
+        * corresponding to the node; leading whitespace and comments are <b>not</b>
+        * included. The source range usually extends through the last character of
+        * the last token corresponding to the node; trailing whitespace and
+        * comments are <b>not</b> included. There are a handful of exceptions
+        * (including compilation units and the various body declarations); the
+        * specification for these node type spells out the details.
+        * Source ranges nest properly: the source range for a child is always
+        * within the source range of its parent, and the source ranges of sibling
+        * nodes never overlap.
+        * If a syntax error is detected while parsing, the relevant node(s) of the
+        * tree will be flagged as <code>MALFORMED</code>.
+        * </p>
+        * <p>
+        * If <code>resolveBindings</code> is <code>true</code>, the various names
+        * and types appearing in the compilation unit can be resolved to "bindings"
+        * by calling the <code>resolveBinding</code> methods. These bindings
+        * draw connections between the different parts of a program, and
+        * generally afford a more powerful vantage point for clients who wish to
+        * analyze a program's structure more deeply. These bindings come at a
+        * considerable cost in both time and space, however, and should not be
+        * requested frivolously. The additional space is not reclaimed until the
+        * AST, all its nodes, and all its bindings become garbage. So it is very
+        * important to not retain any of these objects longer than absolutely
+        * necessary. Bindings are resolved at the time the AST is created. Subsequent
+        * modifications to the AST do not affect the bindings returned by
+        * <code>resolveBinding</code> methods in any way; these methods return the
+        * same binding as before the AST was modified (including modifications
+        * that rearrange subtrees by reparenting nodes).
+        * If <code>resolveBindings</code> is <code>false</code>, the analysis
+        * does not go beyond parsing and building the tree, and all
+        * <code>resolveBinding</code> methods return <code>null</code> from the
+        * outset.
+        * </p>
+        *
+        * @param unit the Java model compilation unit whose source code is to be parsed
+        * @param resolveBindings <code>true</code> if bindings are wanted,
+        *   and <code>false</code> if bindings are not of interest
+        * @return the compilation unit node
+        * @exception IllegalArgumentException if the given Java element does not
+        * exist or if its source string cannot be obtained
+        * @see ASTNode#getFlags()
+        * @see ASTNode#MALFORMED
+        * @see ASTNode#getStartPosition()
+        * @see ASTNode#getLength()
+        * @since 2.0
+        * @deprecated Use {@link ASTParser} instead.
+        */
+       public static CompilationUnit parseCompilationUnit(
+               ICompilationUnit unit,
+               boolean resolveBindings) {
+
+               try {
+                       ASTParser c = ASTParser.newParser(AST.JLS2);
+                       c.setSource(unit);
+                       c.setResolveBindings(resolveBindings);
+                       ASTNode result = c.createAST(null);
+                       return (CompilationUnit) result;
+               } catch (IllegalStateException e) {
+                       // convert ASTParser's complaints into old form
+                       throw new IllegalArgumentException();
+               }
+       }
+
+       /**
+        * Parses the source string corresponding to the given Java class file
+        * element and creates and returns a corresponding abstract syntax tree.
+        * The source string is obtained from the Java model element using
+        * <code>IClassFile.getSource()</code>, and is only available for a class
+        * files with attached source.
+        * <p>
+        * The returned compilation unit node is the root node of a new AST.
+        * Each node in the subtree carries source range(s) information relating back
+        * to positions in the source string (the source string is not remembered
+        * with the AST).
+        * The source range usually begins at the first character of the first token
+        * corresponding to the node; leading whitespace and comments are <b>not</b>
+        * included. The source range usually extends through the last character of
+        * the last token corresponding to the node; trailing whitespace and
+        * comments are <b>not</b> included. There are a handful of exceptions
+        * (including compilation units and the various body declarations); the
+        * specification for these node type spells out the details.
+        * Source ranges nest properly: the source range for a child is always
+        * within the source range of its parent, and the source ranges of sibling
+        * nodes never overlap.
+        * If a syntax error is detected while parsing, the relevant node(s) of the
+        * tree will be flagged as <code>MALFORMED</code>.
+        * </p>
+        * <p>
+        * If <code>resolveBindings</code> is <code>true</code>, the various names
+        * and types appearing in the compilation unit can be resolved to "bindings"
+        * by calling the <code>resolveBinding</code> methods. These bindings
+        * draw connections between the different parts of a program, and
+        * generally afford a more powerful vantage point for clients who wish to
+        * analyze a program's structure more deeply. These bindings come at a
+        * considerable cost in both time and space, however, and should not be
+        * requested frivolously. The additional space is not reclaimed until the
+        * AST, all its nodes, and all its bindings become garbage. So it is very
+        * important to not retain any of these objects longer than absolutely
+        * necessary. Bindings are resolved at the time the AST is created. Subsequent
+        * modifications to the AST do not affect the bindings returned by
+        * <code>resolveBinding</code> methods in any way; these methods return the
+        * same binding as before the AST was modified (including modifications
+        * that rearrange subtrees by reparenting nodes).
+        * If <code>resolveBindings</code> is <code>false</code>, the analysis
+        * does not go beyond parsing and building the tree, and all
+        * <code>resolveBinding</code> methods return <code>null</code> from the
+        * outset.
+        * </p>
+        *
+        * @param classFile the Java model class file whose corresponding source code is to be parsed
+        * @param resolveBindings <code>true</code> if bindings are wanted,
+        *   and <code>false</code> if bindings are not of interest
+        * @return the compilation unit node
+        * @exception IllegalArgumentException if the given Java element does not
+        * exist or if its source string cannot be obtained
+        * @see ASTNode#getFlags()
+        * @see ASTNode#MALFORMED
+        * @see ASTNode#getStartPosition()
+        * @see ASTNode#getLength()
+        * @since 2.1
+        * @deprecated Use {@link ASTParser} instead.
+        */
+       public static CompilationUnit parseCompilationUnit(
+               IClassFile classFile,
+               boolean resolveBindings) {
+
+               if (classFile == null) {
+                       throw new IllegalArgumentException();
+               }
+               try {
+                       ASTParser c = ASTParser.newParser(AST.JLS2);
+                       c.setSource(classFile);
+                       c.setResolveBindings(resolveBindings);
+                       ASTNode result = c.createAST(null);
+                       return (CompilationUnit) result;
+               } catch (IllegalStateException e) {
+                       // convert ASTParser's complaints into old form
+                       throw new IllegalArgumentException();
+               }
+       }
+
+       /**
+        * Parses the given string as the hypothetical contents of the named
+        * compilation unit and creates and returns a corresponding abstract syntax tree.
+        * <p>
+        * The returned compilation unit node is the root node of a new AST.
+        * Each node in the subtree carries source range(s) information relating back
+        * to positions in the given source string (the given source string itself
+        * is not remembered with the AST).
+        * The source range usually begins at the first character of the first token
+        * corresponding to the node; leading whitespace and comments are <b>not</b>
+        * included. The source range usually extends through the last character of
+        * the last token corresponding to the node; trailing whitespace and
+        * comments are <b>not</b> included. There are a handful of exceptions
+        * (including compilation units and the various body declarations); the
+        * specification for these node type spells out the details.
+        * Source ranges nest properly: the source range for a child is always
+        * within the source range of its parent, and the source ranges of sibling
+        * nodes never overlap.
+        * If a syntax error is detected while parsing, the relevant node(s) of the
+        * tree will be flagged as <code>MALFORMED</code>.
+        * </p>
+        * <p>
+        * If the given project is not <code>null</code>, the various names
+        * and types appearing in the compilation unit can be resolved to "bindings"
+        * by calling the <code>resolveBinding</code> methods. These bindings
+        * draw connections between the different parts of a program, and
+        * generally afford a more powerful vantage point for clients who wish to
+        * analyze a program's structure more deeply. These bindings come at a
+        * considerable cost in both time and space, however, and should not be
+        * requested frivolously. The additional space is not reclaimed until the
+        * AST, all its nodes, and all its bindings become garbage. So it is very
+        * important to not retain any of these objects longer than absolutely
+        * necessary. Bindings are resolved at the time the AST is created. Subsequent
+        * modifications to the AST do not affect the bindings returned by
+        * <code>resolveBinding</code> methods in any way; these methods return the
+        * same binding as before the AST was modified (including modifications
+        * that rearrange subtrees by reparenting nodes).
+        * If the given project is <code>null</code>, the analysis
+        * does not go beyond parsing and building the tree, and all
+        * <code>resolveBinding</code> methods return <code>null</code> from the
+        * outset.
+        * </p>
+        * <p>
+        * The name of the compilation unit must be supplied for resolving bindings.
+        * This name should be suffixed by a dot ('.') followed by one of the
+        * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}
+        * and match the name of the main
+        * (public) class or interface declared in the source. For example, if the source
+        * declares a public class named "Foo", the name of the compilation can be
+        * "Foo.java". For the purposes of resolving bindings, types declared in the
+        * source string hide types by the same name available through the classpath
+        * of the given project.
+        * </p>
+        *
+        * @param source the string to be parsed as a Java compilation unit
+        * @param unitName the name of the compilation unit that would contain the source
+        *    string, or <code>null</code> if <code>javaProject</code> is also <code>null</code>
+        * @param project the Java project used to resolve names, or
+        *    <code>null</code> if bindings are not resolved
+        * @return the compilation unit node
+        * @see ASTNode#getFlags()
+        * @see ASTNode#MALFORMED
+        * @see ASTNode#getStartPosition()
+        * @see ASTNode#getLength()
+        * @since 2.0
+        * @deprecated Use {@link ASTParser} instead.
+        */
+       public static CompilationUnit parseCompilationUnit(
+               char[] source,
+               String unitName,
+               IJavaProject project) {
+
+               if (source == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTParser astParser = ASTParser.newParser(AST.JLS2);
+               astParser.setSource(source);
+               astParser.setUnitName(unitName);
+               astParser.setProject(project);
+               astParser.setResolveBindings(project != null);
+               ASTNode result = astParser.createAST(null);
+               return (CompilationUnit) result;
+       }
+
+       /**
+        * Parses the given string as a Java compilation unit and creates and
+        * returns a corresponding abstract syntax tree.
+        * <p>
+        * The returned compilation unit node is the root node of a new AST.
+        * Each node in the subtree carries source range(s) information relating back
+        * to positions in the given source string (the given source string itself
+        * is not remembered with the AST).
+        * The source range usually begins at the first character of the first token
+        * corresponding to the node; leading whitespace and comments are <b>not</b>
+        * included. The source range usually extends through the last character of
+        * the last token corresponding to the node; trailing whitespace and
+        * comments are <b>not</b> included. There are a handful of exceptions
+        * (including compilation units and the various body declarations); the
+        * specification for these node type spells out the details.
+        * Source ranges nest properly: the source range for a child is always
+        * within the source range of its parent, and the source ranges of sibling
+        * nodes never overlap.
+        * If a syntax error is detected while parsing, the relevant node(s) of the
+        * tree will be flagged as <code>MALFORMED</code>.
+        * </p>
+        * <p>
+        * This method does not compute binding information; all <code>resolveBinding</code>
+        * methods applied to nodes of the resulting AST return <code>null</code>.
+        * </p>
+        *
+        * @param source the string to be parsed as a Java compilation unit
+        * @return the compilation unit node
+        * @see ASTNode#getFlags()
+        * @see ASTNode#MALFORMED
+        * @see ASTNode#getStartPosition()
+        * @see ASTNode#getLength()
+        * @since 2.0
+        * @deprecated Use {@link ASTParser} instead.
+        */
+       public static CompilationUnit parseCompilationUnit(char[] source) {
+               if (source == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTParser c = ASTParser.newParser(AST.JLS2);
+               c.setSource(source);
+               ASTNode result = c.createAST(null);
+               return (CompilationUnit) result;
+       }
+
+       /**
+        * Returns the binding resolver for this AST.
+        *
+        * @return the binding resolver for this AST
+        */
+       BindingResolver getBindingResolver() {
+               return this.resolver;
+       }
+
+       /**
+        * Returns the event handler for this AST.
+        *
+        * @return the event handler for this AST
+        * @since 3.0
+        */
+       NodeEventHandler getEventHandler() {
+               return this.eventHandler;
+       }
+
+       /**
+        * Sets the event handler for this AST.
+        *
+        * @param eventHandler the event handler for this AST
+        * @since 3.0
+        */
+       void setEventHandler(NodeEventHandler eventHandler) {
+               if (this.eventHandler == null) {
+                       throw new IllegalArgumentException();
+               }
+               this.eventHandler = eventHandler;
+       }
+
+       /**
+        * Returns default node flags of new nodes of this AST.
+        *
+        * @return the default node flags of new nodes of this AST
+        * @since 3.0
+        */
+       int getDefaultNodeFlag() {
+               return this.defaultNodeFlag;
+       }
+
+       /**
+        * Sets default node flags of new nodes of this AST.
+        *
+        * @param flag node flags of new nodes of this AST
+        * @since 3.0
+        */
+       void setDefaultNodeFlag(int flag) {
+               this.defaultNodeFlag = flag;
+       }
+
+       /**
+        * Set <code>originalModificationCount</code> to the current modification count
+        *
+        * @since 3.0
+        */
+       void setOriginalModificationCount(long count) {
+               this.originalModificationCount = count;
+       }
+
+       /**
+        * Returns the type binding for a "well known" type.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * <p>
+        * The following type names are supported:
+        * <ul>
+        * <li><code>"boolean"</code></li>
+        * <li><code>"byte"</code></li>
+        * <li><code>"char"</code></li>
+        * <li><code>"double"</code></li>
+        * <li><code>"float"</code></li>
+        * <li><code>"int"</code></li>
+        * <li><code>"long"</code></li>
+        * <li><code>"short"</code></li>
+        * <li><code>"void"</code></li>
+        * <li><code>"java.lang.Boolean"</code> (since 3.1)</li>
+        * <li><code>"java.lang.Byte"</code> (since 3.1)</li>
+        * <li><code>"java.lang.Character"</code> (since 3.1)</li>
+        * <li><code>"java.lang.Class"</code></li>
+        * <li><code>"java.lang.Cloneable"</code></li>
+        * <li><code>"java.lang.Double"</code> (since 3.1)</li>
+        * <li><code>"java.lang.Error"</code></li>
+        * <li><code>"java.lang.Exception"</code></li>
+        * <li><code>"java.lang.Float"</code> (since 3.1)</li>
+        * <li><code>"java.lang.Integer"</code> (since 3.1)</li>
+        * <li><code>"java.lang.Long"</code> (since 3.1)</li>
+        * <li><code>"java.lang.Object"</code></li>
+        * <li><code>"java.lang.RuntimeException"</code></li>
+        * <li><code>"java.lang.Short"</code> (since 3.1)</li>
+        * <li><code>"java.lang.String"</code></li>
+        * <li><code>"java.lang.StringBuffer"</code></li>
+        * <li><code>"java.lang.Throwable"</code></li>
+        * <li><code>"java.lang.Void"</code> (since 3.1)</li>
+        * <li><code>"java.io.Serializable"</code></li>
+        * </ul>
+        * </p>
+        *
+        * @param name the name of a well known type
+        * @return the corresponding type binding, or <code>null</code> if the
+        *   named type is not considered well known or if no binding can be found
+        *   for it
+        */
+       public ITypeBinding resolveWellKnownType(String name) {
+               if (name == null) {
+                       return null;
+               }
+               return getBindingResolver().resolveWellKnownType(name);
+       }
+
+       /**
+        * Sets the binding resolver for this AST.
+        *
+        * @param resolver the new binding resolver for this AST
+        */
+       void setBindingResolver(BindingResolver resolver) {
+               if (resolver == null) {
+                       throw new IllegalArgumentException();
+               }
+               this.resolver = resolver;
+       }
+
+       /**
+     * Checks that this AST operation is not used when
+     * building level JLS2 ASTs.
+
+     * @exception UnsupportedOperationException
+        * @since 3.0
+     */
+       void unsupportedIn2() {
+         if (this.apiLevel == AST.JLS2) {
+               throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
+         }
+       }
+
+       /**
+     * Checks that this AST operation is only used when
+     * building level JLS2 ASTs.
+
+     * @exception UnsupportedOperationException
+        * @since 3.0
+     */
+       void supportedOnlyIn2() {
+         if (this.apiLevel != AST.JLS2) {
+               throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
+         }
+       }
+
+       /**
+        * new Class[] {AST.class}
+        * @since 3.0
+        */
+       private static final Class[] AST_CLASS = new Class[] {AST.class};
+
+       /**
+        * new Object[] {this}
+        * @since 3.0
+        */
+       private final Object[] THIS_AST= new Object[] {this};
+
+       /*
+        * Must not collide with a value for ICompilationUnit constants
+        */
+       static final int RESOLVED_BINDINGS = 0x80000000;
+
+       /**
+        * Tag bit value. This represents internal state of the tree.
+        */
+       private int bits;
+
+       /**
+        * Creates an unparented node of the given node class
+        * (non-abstract subclass of {@link ASTNode}). 
+        * 
+        * @param nodeClass AST node class
+        * @return a new unparented node owned by this AST
+        * @exception IllegalArgumentException if <code>nodeClass</code> is
+        * <code>null</code> or is not a concrete node type class
+        * @since 3.0
+        */
+       public ASTNode createInstance(Class nodeClass) {
+               if (nodeClass == null) {
+                       throw new IllegalArgumentException();
+               }
+               try {
+                       // invoke constructor with signature Foo(AST)
+                       Constructor c = nodeClass.getDeclaredConstructor(AST_CLASS);
+                       Object result = c.newInstance(this.THIS_AST);
+                       return (ASTNode) result;
+               } catch (NoSuchMethodException e) {
+                       // all AST node classes have a Foo(AST) constructor
+                       // therefore nodeClass is not legit
+                       throw new IllegalArgumentException();
+               } catch (InstantiationException e) {
+                       // all concrete AST node classes can be instantiated
+                       // therefore nodeClass is not legit
+                       throw new IllegalArgumentException();
+               } catch (IllegalAccessException e) {
+                       // all AST node classes have an accessible Foo(AST) constructor
+                       // therefore nodeClass is not legit
+                       throw new IllegalArgumentException();
+               } catch (InvocationTargetException e) {
+                       // concrete AST node classes do not die in the constructor
+                       // therefore nodeClass is not legit
+                       throw new IllegalArgumentException();
+               }
+       }
+
+       /**
+        * Creates an unparented node of the given node type.
+        * This convenience method is equivalent to:
+        * <pre>
+        * createInstance(ASTNode.nodeClassForType(nodeType))
+        * </pre>
+        *
+        * @param nodeType AST node type, one of the node type
+        * constants declared on {@link ASTNode}
+        * @return a new unparented node owned by this AST
+        * @exception IllegalArgumentException if <code>nodeType</code> is
+        * not a legal AST node type
+        * @since 3.0
+        */
+       public ASTNode createInstance(int nodeType) {
+               // nodeClassForType throws IllegalArgumentException if nodeType is bogus
+               Class nodeClass = ASTNode.nodeClassForType(nodeType);
+               return createInstance(nodeClass);
+       }
+
+       //=============================== NAMES ===========================
+       /**
+        * Creates and returns a new unparented simple name node for the given
+        * identifier. The identifier should be a legal Java identifier, but not
+        * a keyword, boolean literal ("true", "false") or null literal ("null").
+        *
+        * @param identifier the identifier
+        * @return a new unparented simple name node
+        * @exception IllegalArgumentException if the identifier is invalid
+        */
+       public SimpleName newSimpleName(String identifier) {
+               if (identifier == null) {
+                       throw new IllegalArgumentException();
+               }
+               SimpleName result = new SimpleName(this);
+               result.setIdentifier(identifier);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented qualified name node for the given
+        * qualifier and simple name child node.
+        *
+        * @param qualifier the qualifier name node
+        * @param name the simple name being qualified
+        * @return a new unparented qualified name node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */
+       public QualifiedName newQualifiedName(
+               Name qualifier,
+               SimpleName name) {
+               QualifiedName result = new QualifiedName(this);
+               result.setQualifier(qualifier);
+               result.setName(name);
+               return result;
+
+       }
+
+       /**
+        * Creates and returns a new unparented name node for the given name
+        * segments. Returns a simple name if there is only one name segment, and
+        * a qualified name if there are multiple name segments. Each of the name
+        * segments should be legal Java identifiers (this constraint may or may
+        * not be enforced), and there must be at least one name segment.
+        *
+        * @param identifiers a list of 1 or more name segments, each of which
+        *    is a legal Java identifier
+        * @return a new unparented name node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the identifier is invalid</li>
+        * <li>the list of identifiers is empty</li>
+        * </ul>
+        */
+       public Name newName(String[] identifiers) {
+               // update internalSetName(String[] if changed
+               int count = identifiers.length;
+               if (count == 0) {
+                       throw new IllegalArgumentException();
+               }
+               Name result = newSimpleName(identifiers[0]);
+               for (int i = 1; i < count; i++) {
+                       SimpleName name = newSimpleName(identifiers[i]);
+                       result = newQualifiedName(result, name);
+               }
+               return result;
+       }
+
+       /* (omit javadoc for this method)
+        * This method is a copy of setName(String[]) that doesn't do any validation.
+        */
+       Name internalNewName(String[] identifiers) {
+               int count = identifiers.length;
+               if (count == 0) {
+                       throw new IllegalArgumentException();
+               }
+               final SimpleName simpleName = new SimpleName(this);
+               simpleName.internalSetIdentifier(identifiers[0]);
+               Name result = simpleName;
+               for (int i = 1; i < count; i++) {
+                       SimpleName name = new SimpleName(this);
+                       name.internalSetIdentifier(identifiers[i]);
+                       result = newQualifiedName(result, name);
+               }
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented name node for the given name.
+        * The name string must consist of 1 or more name segments separated
+        * by single dots '.'. Returns a {@link QualifiedName} if the name has
+        * dots, and a {@link SimpleName} otherwise. Each of the name
+        * segments should be legal Java identifiers (this constraint may or may
+        * not be enforced), and there must be at least one name segment.
+        * The string must not contains white space, '&lt;', '&gt;',
+        * '[', ']', or other any other characters that are not
+        * part of the Java identifiers or separating '.'s.
+        *
+        * @param qualifiedName string consisting of 1 or more name segments,
+        * each of which is a legal Java identifier, separated  by single dots '.'
+        * @return a new unparented name node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the string is empty</li>
+        * <li>the string begins or ends in a '.'</li>
+        * <li>the string has adjacent '.'s</li>
+        * <li>the segments between the '.'s are not valid Java identifiers</li>
+        * </ul>
+        * @since 3.1
+        */
+       public Name newName(String qualifiedName) {
+               StringTokenizer t = new StringTokenizer(qualifiedName, ".", true); //$NON-NLS-1$
+               Name result = null;
+               // balance is # of name tokens - # of period tokens seen so far
+               // initially 0; finally 1; should never drop < 0 or > 1
+               int balance = 0;
+               while(t.hasMoreTokens()) {
+                       String s = t.nextToken();
+                       if (s.indexOf('.') >= 0) {
+                               // this is a delimiter
+                               if (s.length() > 1) {
+                                       // too many dots in a row
+                                       throw new IllegalArgumentException();
+                               }
+                               balance--;
+                               if (balance < 0) {
+                                       throw new IllegalArgumentException();
+                               }
+                       } else {
+                               // this is an identifier segment
+                               balance++;
+                               SimpleName name = newSimpleName(s);
+                               if (result == null) {
+                                       result = name;
+                               } else {
+                                       result = newQualifiedName(result, name);
+                               }
+                       }
+               }
+               if (balance != 1) {
+                       throw new IllegalArgumentException();
+               }
+               return result;
+       }
+
+       //=============================== TYPES ===========================
+       /**
+        * Creates and returns a new unparented simple type node with the given
+        * type name.
+        * <p>
+        * This method can be used to convert a name (<code>Name</code>) into a
+        * type (<code>Type</code>) by wrapping it.
+        * </p>
+        *
+        * @param typeName the name of the class or interface
+        * @return a new unparented simple type node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */
+       public SimpleType newSimpleType(Name typeName) {
+               SimpleType result = new SimpleType(this);
+               result.setName(typeName);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented array type node with the given
+        * component type, which may be another array type.
+        *
+        * @param componentType the component type (possibly another array type)
+        * @return a new unparented array type node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */
+       public ArrayType newArrayType(Type componentType) {
+               ArrayType result = new ArrayType(this);
+               result.setComponentType(componentType);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented array type node with the given
+        * element type and number of dimensions.
+        * <p>
+        * Note that if the element type passed in is an array type, the
+        * element type of the result will not be the same as what was passed in.
+        * </p>
+        *
+        * @param elementType the element type (never an array type)
+        * @param dimensions the number of dimensions, a positive number
+        * @return a new unparented array type node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * <li>the element type is null</li>
+        * <li>the element type is an array type</li>
+        * <li>the number of dimensions is lower than 1</li>
+        * <li>the number of dimensions is greater than 1000</li>
+        * </ul>
+        */
+       public ArrayType newArrayType(Type elementType, int dimensions) {
+               if (elementType == null || elementType.isArrayType()) {
+                       throw new IllegalArgumentException();
+               }
+               if (dimensions < 1 || dimensions > 1000) {
+                       // we would blow our stacks anyway with a 1000-D array
+                       throw new IllegalArgumentException();
+               }
+               ArrayType result = new ArrayType(this);
+               result.setComponentType(elementType);
+               for (int i = 2; i <= dimensions; i++) {
+                       result = newArrayType(result);
+               }
+               return result;
+
+       }
+
+       /**
+        * Creates and returns a new unparented primitive type node with the given
+        * type code.
+        *
+        * @param typeCode one of the primitive type code constants declared in
+        *    <code>PrimitiveType</code>
+        * @return a new unparented primitive type node
+        * @exception IllegalArgumentException if the primitive type code is invalid
+        */
+       public PrimitiveType newPrimitiveType(PrimitiveType.Code typeCode) {
+               PrimitiveType result = new PrimitiveType(this);
+               result.setPrimitiveTypeCode(typeCode);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented parameterized type node with the
+        * given type and an empty list of type arguments.
+        *
+        * @param type the type that is parameterized
+        * @return a new unparented parameterized type node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public ParameterizedType newParameterizedType(Type type) {
+               ParameterizedType result = new ParameterizedType(this);
+               result.setType(type);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented qualified type node with
+        * the given qualifier type and name.
+        *
+        * @param qualifier the qualifier type node
+        * @param name the simple name being qualified
+        * @return a new unparented qualified type node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public QualifiedType newQualifiedType(Type qualifier, SimpleName name) {
+               QualifiedType result = new QualifiedType(this);
+               result.setQualifier(qualifier);
+               result.setName(name);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented wildcard type node with no
+        * type bound.
+        *
+        * @return a new unparented wildcard type node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public WildcardType newWildcardType() {
+               WildcardType result = new WildcardType(this);
+               return result;
+       }
+
+       //=============================== DECLARATIONS ===========================
+       /**
+        * Creates an unparented compilation unit node owned by this AST.
+        * The compilation unit initially has no package declaration, no
+        * import declarations, and no type declarations.
+        *
+        * @return the new unparented compilation unit node
+        */
+       public CompilationUnit newCompilationUnit() {
+               return new CompilationUnit(this);
+       }
+
+       /**
+        * Creates an unparented package declaration node owned by this AST.
+        * The package declaration initially declares a package with an
+        * unspecified name.
+        *
+        * @return the new unparented package declaration node
+        */
+       public PackageDeclaration newPackageDeclaration() {
+               PackageDeclaration result = new PackageDeclaration(this);
+               return result;
+       }
+
+       /**
+        * Creates an unparented import declaration node owned by this AST.
+        * The import declaration initially contains a single-type import
+        * of a type with an unspecified name.
+        *
+        * @return the new unparented import declaration node
+        */
+       public ImportDeclaration newImportDeclaration() {
+               ImportDeclaration result = new ImportDeclaration(this);
+               return result;
+       }
+
+       /**
+        * Creates an unparented class declaration node owned by this AST.
+        * The name of the class is an unspecified, but legal, name;
+        * no modifiers; no doc comment; no superclass or superinterfaces;
+        * and an empty class body.
+        * <p>
+        * To create an interface, use this method and then call
+        * <code>TypeDeclaration.setInterface(true)</code>.
+        * </p>
+        *
+        * @return a new unparented type declaration node
+        */
+       public TypeDeclaration newTypeDeclaration() {
+               TypeDeclaration result = new TypeDeclaration(this);
+               result.setInterface(false);
+               return result;
+       }
+
+       /**
+        * Creates an unparented method declaration node owned by this AST.
+        * By default, the declaration is for a method of an unspecified, but
+        * legal, name; no modifiers; no doc comment; no parameters; return
+        * type void; no extra array dimensions; no thrown exceptions; and no
+        * body (as opposed to an empty body).
+        * <p>
+        * To create a constructor, use this method and then call
+        * <code>MethodDeclaration.setConstructor(true)</code> and
+        * <code>MethodDeclaration.setName(className)</code>.
+        * </p>
+        *
+        * @return a new unparented method declaration node
+        */
+       public MethodDeclaration newMethodDeclaration() {
+               MethodDeclaration result = new MethodDeclaration(this);
+               result.setConstructor(false);
+               return result;
+       }
+
+       /**
+        * Creates an unparented single variable declaration node owned by this AST.
+        * By default, the declaration is for a variable with an unspecified, but
+        * legal, name and type; no modifiers; no array dimensions after the
+        * variable; no initializer; not variable arity.
+        *
+        * @return a new unparented single variable declaration node
+        */
+       public SingleVariableDeclaration newSingleVariableDeclaration() {
+               SingleVariableDeclaration result = new SingleVariableDeclaration(this);
+               return result;
+       }
+
+       /**
+        * Creates an unparented variable declaration fragment node owned by this
+        * AST. By default, the fragment is for a variable with an unspecified, but
+        * legal, name; no extra array dimensions; and no initializer.
+        *
+        * @return a new unparented variable declaration fragment node
+        */
+       public VariableDeclarationFragment newVariableDeclarationFragment() {
+               VariableDeclarationFragment result = new VariableDeclarationFragment(this);
+               return result;
+       }
+
+       /**
+        * Creates an unparented initializer node owned by this AST, with an
+        * empty block. By default, the initializer has no modifiers and
+        * an empty block.
+        *
+        * @return a new unparented initializer node
+        */
+       public Initializer newInitializer() {
+               Initializer result = new Initializer(this);
+               return result;
+       }
+
+       /**
+        * Creates an unparented enum constant declaration node owned by this AST.
+        * The name of the constant is an unspecified, but legal, name;
+        * no doc comment; no modifiers or annotations; no arguments;
+        * and does not declare an anonymous class.
+        *
+        * @return a new unparented enum constant declaration node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public EnumConstantDeclaration newEnumConstantDeclaration() {
+               EnumConstantDeclaration result = new EnumConstantDeclaration(this);
+               return result;
+       }
+
+       /**
+        * Creates an unparented enum declaration node owned by this AST.
+        * The name of the enum is an unspecified, but legal, name;
+        * no doc comment; no modifiers or annotations;
+        * no superinterfaces; and empty lists of enum constants
+        * and body declarations.
+        *
+        * @return a new unparented enum declaration node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public EnumDeclaration newEnumDeclaration() {
+               EnumDeclaration result = new EnumDeclaration(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented type parameter type node with an
+        * unspecified type variable name and an empty list of type bounds.
+        *
+        * @return a new unparented type parameter node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public TypeParameter newTypeParameter() {
+               TypeParameter result = new TypeParameter(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented annotation type declaration
+        * node for an unspecified, but legal, name; no modifiers; no javadoc;
+        * and an empty list of member declarations.
+        *
+        * @return a new unparented annotation type declaration node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public AnnotationTypeDeclaration newAnnotationTypeDeclaration() {
+               AnnotationTypeDeclaration result = new AnnotationTypeDeclaration(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented annotation type
+        * member declaration node for an unspecified, but legal,
+        * member name and type; no modifiers; no javadoc;
+        * and no default value.
+        *
+        * @return a new unparented annotation type member declaration node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public AnnotationTypeMemberDeclaration newAnnotationTypeMemberDeclaration() {
+               AnnotationTypeMemberDeclaration result = new AnnotationTypeMemberDeclaration(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented modifier node for the given
+        * modifier.
+        *
+        * @param keyword one of the modifier keyword constants
+        * @return a new unparented modifier node
+        * @exception IllegalArgumentException if the primitive type code is invalid
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public Modifier newModifier(Modifier.ModifierKeyword keyword) {
+               Modifier result = new Modifier(this);
+               result.setKeyword(keyword);
+               return result;
+       }
+
+       /**
+        * Creates and returns a list of new unparented modifier nodes
+        * for the given modifier flags. When multiple modifiers are
+        * requested the modifiers nodes will appear in the following order:
+        * public, protected, private, abstract, static, final, synchronized,
+        * native, strictfp, transient, volatile. This order is consistent
+        * with the recommendations in JLS2 8.1.1, 8.3.1, and 8.4.3.
+        *
+        * @param flags bitwise or of modifier flags declared on {@link Modifier}
+        * @return a possibly empty list of new unparented modifier nodes
+        *   (element type <code>Modifier</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public List newModifiers(int flags) {
+               if (this.apiLevel == AST.JLS2) {
+                       unsupportedIn2();
+               }
+               List result = new ArrayList(3); // 3 modifiers is more than average
+               if (Modifier.isPublic(flags)) {
+                       result.add(newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
+               }
+               if (Modifier.isProtected(flags)) {
+                       result.add(newModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD));
+               }
+               if (Modifier.isPrivate(flags)) {
+                       result.add(newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD));
+               }
+               if (Modifier.isAbstract(flags)) {
+                       result.add(newModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD));
+               }
+               if (Modifier.isStatic(flags)) {
+                       result.add(newModifier(Modifier.ModifierKeyword.STATIC_KEYWORD));
+               }
+               if (Modifier.isFinal(flags)) {
+                       result.add(newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD));
+               }
+               if (Modifier.isSynchronized(flags)) {
+                       result.add(newModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD));
+               }
+               if (Modifier.isNative(flags)) {
+                       result.add(newModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD));
+               }
+               if (Modifier.isStrictfp(flags)) {
+                       result.add(newModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD));
+               }
+               if (Modifier.isTransient(flags)) {
+                       result.add(newModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD));
+               }
+               if (Modifier.isVolatile(flags)) {
+                       result.add(newModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD));
+               }
+               return result;
+       }
+
+       //=============================== COMMENTS ===========================
+
+       /**
+        * Creates and returns a new block comment placeholder node.
+        * <p>
+        * Note that this node type is used to recording the source
+        * range where a comment was found in the source string.
+        * These comment nodes are normally found (only) in
+        * {@linkplain CompilationUnit#getCommentList()
+        * the comment table} for parsed compilation units.
+        * </p>
+        *
+        * @return a new unparented block comment node
+        * @since 3.0
+        */
+       public BlockComment newBlockComment() {
+               BlockComment result = new BlockComment(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new line comment placeholder node.
+        * <p>
+        * Note that this node type is used to recording the source
+        * range where a comment was found in the source string.
+        * These comment nodes are normally found (only) in
+        * {@linkplain CompilationUnit#getCommentList()
+        * the comment table} for parsed compilation units.
+        * </p>
+        *
+        * @return a new unparented line comment node
+        * @since 3.0
+        */
+       public LineComment newLineComment() {
+               LineComment result = new LineComment(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new doc comment node.
+        * Initially the new node has an empty list of tag elements
+        * (and, for backwards compatability, an unspecified, but legal,
+        * doc comment string)
+        *
+        * @return a new unparented doc comment node
+        */
+       public Javadoc newJavadoc() {
+               Javadoc result = new Javadoc(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new tag element node.
+        * Initially the new node has no tag name and an empty list of fragments.
+        * <p>
+        * Note that this node type is used only inside doc comments
+        * ({@link Javadoc}).
+        * </p>
+        *
+        * @return a new unparented tag element node
+        * @since 3.0
+        */
+       public TagElement newTagElement() {
+               TagElement result = new TagElement(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new text element node.
+        * Initially the new node has an empty text string.
+        * <p>
+        * Note that this node type is used only inside doc comments
+        * ({@link Javadoc Javadoc}).
+        * </p>
+        *
+        * @return a new unparented text element node
+        * @since 3.0
+        */
+       public TextElement newTextElement() {
+               TextElement result = new TextElement(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new member reference node.
+        * Initially the new node has no qualifier name and
+        * an unspecified, but legal, member name.
+        * <p>
+        * Note that this node type is used only inside doc comments
+        * ({@link Javadoc}).
+        * </p>
+        *
+        * @return a new unparented member reference node
+        * @since 3.0
+        */
+       public MemberRef newMemberRef() {
+               MemberRef result = new MemberRef(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new method reference node.
+        * Initially the new node has no qualifier name,
+        * an unspecified, but legal, method name, and an
+        * empty parameter list.
+        * <p>
+        * Note that this node type is used only inside doc comments
+        * ({@link Javadoc Javadoc}).
+        * </p>
+        *
+        * @return a new unparented method reference node
+        * @since 3.0
+        */
+       public MethodRef newMethodRef() {
+               MethodRef result = new MethodRef(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new method reference node.
+        * Initially the new node has an unspecified, but legal,
+        * type, not variable arity, and no parameter name.
+        * <p>
+        * Note that this node type is used only inside doc comments
+        * ({@link Javadoc}).
+        * </p>
+        *
+        * @return a new unparented method reference parameter node
+        * @since 3.0
+        */
+       public MethodRefParameter newMethodRefParameter() {
+               MethodRefParameter result = new MethodRefParameter(this);
+               return result;
+       }
+
+       //=============================== STATEMENTS ===========================
+       /**
+        * Creates a new unparented local variable declaration statement node
+        * owned by this AST, for the given variable declaration fragment.
+        * By default, there are no modifiers and the base type is unspecified
+        * (but legal).
+        * <p>
+        * This method can be used to convert a variable declaration fragment
+        * (<code>VariableDeclarationFragment</code>) into a statement
+        * (<code>Statement</code>) by wrapping it. Additional variable
+        * declaration fragments can be added afterwards.
+        * </p>
+        *
+        * @param fragment the variable declaration fragment
+        * @return a new unparented variable declaration statement node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * <li>the variable declaration fragment is null</li>
+        * </ul>
+        */
+       public VariableDeclarationStatement
+                       newVariableDeclarationStatement(VariableDeclarationFragment fragment) {
+               if (fragment == null) {
+                       throw new IllegalArgumentException();
+               }
+               VariableDeclarationStatement result =
+                       new VariableDeclarationStatement(this);
+               result.fragments().add(fragment);
+               return result;
+       }
+
+       /**
+        * Creates a new unparented local type declaration statement node
+        * owned by this AST, for the given type declaration.
+        * <p>
+        * This method can be used to convert a type declaration
+        * (<code>TypeDeclaration</code>) into a statement
+        * (<code>Statement</code>) by wrapping it.
+        * </p>
+        *
+        * @param decl the type declaration
+        * @return a new unparented local type declaration statement node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */
+       public TypeDeclarationStatement
+                       newTypeDeclarationStatement(TypeDeclaration decl) {
+               TypeDeclarationStatement result = new TypeDeclarationStatement(this);
+               result.setDeclaration(decl);
+               return result;
+       }
+
+       /**
+        * Creates a new unparented local type declaration statement node
+        * owned by this AST, for the given type declaration.
+        * <p>
+        * This method can be used to convert any kind of type declaration
+        * (<code>AbstractTypeDeclaration</code>) into a statement
+        * (<code>Statement</code>) by wrapping it.
+        * </p>
+        *
+        * @param decl the type declaration
+        * @return a new unparented local type declaration statement node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        * @since 3.0
+        */
+       public TypeDeclarationStatement
+                       newTypeDeclarationStatement(AbstractTypeDeclaration decl) {
+               TypeDeclarationStatement result = new TypeDeclarationStatement(this);
+               if (this.apiLevel == AST.JLS2) {
+                       result.internalSetTypeDeclaration((TypeDeclaration) decl);
+               }
+               if (this.apiLevel >= AST.JLS3) {
+                       result.setDeclaration(decl);
+               }
+               return result;
+       }
+
+       /**
+        * Creates an unparented block node owned by this AST, for an empty list
+        * of statements.
+        *
+        * @return a new unparented, empty block node
+        */
+       public Block newBlock() {
+               return new Block(this);
+       }
+
+       /**
+        * Creates an unparented continue statement node owned by this AST.
+        * The continue statement has no label.
+        *
+        * @return a new unparented continue statement node
+        */
+       public ContinueStatement newContinueStatement() {
+               return new ContinueStatement(this);
+       }
+
+       /**
+        * Creates an unparented break statement node owned by this AST.
+        * The break statement has no label.
+        *
+        * @return a new unparented break statement node
+        */
+       public BreakStatement newBreakStatement() {
+               return new BreakStatement(this);
+       }
+
+       /**
+        * Creates a new unparented expression statement node owned by this AST,
+        * for the given expression.
+        * <p>
+        * This method can be used to convert an expression
+        * (<code>Expression</code>) into a statement (<code>Type</code>)
+        * by wrapping it. Note, however, that the result is only legal for
+        * limited expression types, including method invocations, assignments,
+        * and increment/decrement operations.
+        * </p>
+        *
+        * @param expression the expression
+        * @return a new unparented statement node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */
+       public ExpressionStatement newExpressionStatement(Expression expression) {
+               ExpressionStatement result = new ExpressionStatement(this);
+               result.setExpression(expression);
+               return result;
+       }
+
+       /**
+        * Creates a new unparented if statement node owned by this AST.
+        * By default, the expression is unspecified (but legal),
+        * the then statement is an empty block, and there is no else statement.
+        *
+        * @return a new unparented if statement node
+        */
+       public IfStatement newIfStatement() {
+               return new IfStatement(this);
+       }
+
+       /**
+        * Creates a new unparented while statement node owned by this AST.
+        * By default, the expression is unspecified (but legal), and
+        * the body statement is an empty block.
+        *
+        * @return a new unparented while statement node
+        */
+       public WhileStatement newWhileStatement() {
+               return new WhileStatement(this);
+       }
+
+       /**
+        * Creates a new unparented do statement node owned by this AST.
+        * By default, the expression is unspecified (but legal), and
+        * the body statement is an empty block.
+        *
+        * @return a new unparented do statement node
+        */
+       public DoStatement newDoStatement() {
+               return new DoStatement(this);
+       }
+
+       /**
+        * Creates a new unparented try statement node owned by this AST.
+        * By default, the try statement has an empty block, no catch
+        * clauses, and no finally block.
+        *
+        * @return a new unparented try statement node
+        */
+       public TryStatement newTryStatement() {
+               return new TryStatement(this);
+       }
+
+       /**
+        * Creates a new unparented catch clause node owned by this AST.
+        * By default, the catch clause declares an unspecified, but legal,
+        * exception declaration and has an empty block.
+        *
+        * @return a new unparented catch clause node
+        */
+       public CatchClause newCatchClause() {
+               return new CatchClause(this);
+       }
+
+       /**
+        * Creates a new unparented return statement node owned by this AST.
+        * By default, the return statement has no expression.
+        *
+        * @return a new unparented return statement node
+        */
+       public ReturnStatement newReturnStatement() {
+               return new ReturnStatement(this);
+       }
+
+       /**
+        * Creates a new unparented throw statement node owned by this AST.
+        * By default, the expression is unspecified, but legal.
+        *
+        * @return a new unparented throw statement node
+        */
+       public ThrowStatement newThrowStatement() {
+               return new ThrowStatement(this);
+       }
+
+       /**
+        * Creates a new unparented assert statement node owned by this AST.
+        * By default, the first expression is unspecified, but legal, and has no
+        * message expression.
+        *
+        * @return a new unparented assert statement node
+        */
+       public AssertStatement newAssertStatement() {
+               return new AssertStatement(this);
+       }
+
+       /**
+        * Creates a new unparented empty statement node owned by this AST.
+        *
+        * @return a new unparented empty statement node
+        */
+       public EmptyStatement newEmptyStatement() {
+               return new EmptyStatement(this);
+       }
+
+       /**
+        * Creates a new unparented labeled statement node owned by this AST.
+        * By default, the label and statement are both unspecified, but legal.
+        *
+        * @return a new unparented labeled statement node
+        */
+       public LabeledStatement newLabeledStatement() {
+               return new LabeledStatement(this);
+       }
+
+       /**
+        * Creates a new unparented switch statement node owned by this AST.
+        * By default, the expression is unspecified, but legal, and there are
+        * no statements or switch cases.
+        *
+        * @return a new unparented labeled statement node
+        */
+       public SwitchStatement newSwitchStatement() {
+               return new SwitchStatement(this);
+       }
+
+       /**
+        * Creates a new unparented switch case statement node owned by
+        * this AST. By default, the expression is unspecified, but legal.
+        *
+        * @return a new unparented switch case node
+        */
+       public SwitchCase newSwitchCase() {
+               return new SwitchCase(this);
+       }
+
+       /**
+        * Creates a new unparented synchronized statement node owned by this AST.
+        * By default, the expression is unspecified, but legal, and the body is
+        * an empty block.
+        *
+        * @return a new unparented synchronized statement node
+        */
+       public SynchronizedStatement newSynchronizedStatement() {
+               return new SynchronizedStatement(this);
+       }
+
+       /**
+        * Creates a new unparented for statement node owned by this AST.
+        * By default, there are no initializers, no condition expression,
+        * no updaters, and the body is an empty block.
+        *
+        * @return a new unparented for statement node
+        */
+       public ForStatement newForStatement() {
+               return new ForStatement(this);
+       }
+
+       /**
+        * Creates a new unparented enhanced for statement node owned by this AST.
+        * By default, the paramter and expression are unspecified
+        * but legal subtrees, and the body is an empty block.
+        *
+        * @return a new unparented throw statement node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public EnhancedForStatement newEnhancedForStatement() {
+               return new EnhancedForStatement(this);
+       }
+
+       //=============================== EXPRESSIONS ===========================
+       /**
+        * Creates and returns a new unparented string literal node for
+        * the empty string literal.
+        *
+        * @return a new unparented string literal node
+        */
+       public StringLiteral newStringLiteral() {
+               return new StringLiteral(this);
+       }
+
+
+       /**
+        * Creates and returns a new unparented character literal node.
+        * Initially the node has an unspecified character literal.
+        *
+        * @return a new unparented character literal node
+        */
+       public CharacterLiteral newCharacterLiteral() {
+               return new CharacterLiteral(this);
+       }
+
+       /**
+        * Creates and returns a new unparented number literal node.
+        *
+        * @param literal the token for the numeric literal as it would
+        *    appear in Java source code
+        * @return a new unparented number literal node
+        * @exception IllegalArgumentException if the literal is null
+        */
+       public NumberLiteral newNumberLiteral(String literal) {
+               if (literal == null) {
+                       throw new IllegalArgumentException();
+               }
+               NumberLiteral result = new NumberLiteral(this);
+               result.setToken(literal);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented number literal node.
+        * Initially the number literal token is <code>"0"</code>.
+        *
+        * @return a new unparented number literal node
+        */
+       public NumberLiteral newNumberLiteral() {
+               NumberLiteral result = new NumberLiteral(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented null literal node.
+        *
+        * @return a new unparented null literal node
+        */
+       public NullLiteral newNullLiteral() {
+               return new NullLiteral(this);
+       }
+
+       /**
+        * Creates and returns a new unparented boolean literal node.
+        * <p>
+        * For example, the assignment expression <code>foo = true</code>
+        * is generated by the following snippet:
+        * <code>
+        * <pre>
+        * Assignment e= ast.newAssignment();
+        * e.setLeftHandSide(ast.newSimpleName("foo"));
+        * e.setRightHandSide(ast.newBooleanLiteral(true));
+        * </pre>
+        * </code>
+        * </p>
+        *
+        * @param value the boolean value
+        * @return a new unparented boolean literal node
+        */
+       public BooleanLiteral newBooleanLiteral(boolean value) {
+               BooleanLiteral result = new BooleanLiteral(this);
+               result.setBooleanValue(value);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented assignment expression node
+        * owned by this AST. By default, the assignment operator is "=" and
+        * the left and right hand side expressions are unspecified, but
+        * legal, names.
+        *
+        * @return a new unparented assignment expression node
+        */
+       public Assignment newAssignment() {
+               Assignment result = new Assignment(this);
+               return result;
+       }
+
+       /**
+        * Creates an unparented method invocation expression node owned by this
+        * AST. By default, the name of the method is unspecified (but legal)
+        * there is no receiver expression, no type arguments, and the list of
+        * arguments is empty.
+        *
+        * @return a new unparented method invocation expression node
+        */
+       public MethodInvocation newMethodInvocation() {
+               MethodInvocation result = new MethodInvocation(this);
+               return result;
+       }
+
+       /**
+        * Creates an unparented "super" method invocation expression node owned by
+        * this AST. By default, the name of the method is unspecified (but legal)
+        * there is no qualifier, no type arguments, and the list of arguments is empty.
+        *
+        * @return a new unparented  "super" method invocation
+        *    expression node
+        */
+       public SuperMethodInvocation newSuperMethodInvocation() {
+               SuperMethodInvocation result = new SuperMethodInvocation(this);
+               return result;
+       }
+
+       /**
+        * Creates an unparented alternate constructor ("this(...);") invocation
+        * statement node owned by this AST. By default, the lists of arguments
+        * and type arguments are both empty.
+        * <p>
+        * Note that this type of node is a Statement, whereas a regular
+        * method invocation is an Expression. The only valid use of these
+        * statements are as the first statement of a constructor body.
+        * </p>
+        *
+        * @return a new unparented alternate constructor invocation statement node
+        */
+       public ConstructorInvocation newConstructorInvocation() {
+               ConstructorInvocation result = new ConstructorInvocation(this);
+               return result;
+       }
+
+       /**
+        * Creates an unparented alternate super constructor ("super(...);")
+        * invocation statement node owned by this AST. By default, there is no
+        * qualifier, no type arguments, and the list of arguments is empty.
+        * <p>
+        * Note that this type of node is a Statement, whereas a regular
+        * super method invocation is an Expression. The only valid use of these
+        * statements are as the first statement of a constructor body.
+        * </p>
+        *
+        * @return a new unparented super constructor invocation statement node
+        */
+       public SuperConstructorInvocation newSuperConstructorInvocation() {
+               SuperConstructorInvocation result =
+                       new SuperConstructorInvocation(this);
+               return result;
+       }
+
+       /**
+        * Creates a new unparented local variable declaration expression node
+        * owned by this AST, for the given variable declaration fragment. By
+        * default, there are no modifiers and the base type is unspecified
+        * (but legal).
+        * <p>
+        * This method can be used to convert a variable declaration fragment
+        * (<code>VariableDeclarationFragment</code>) into an expression
+        * (<code>Expression</code>) by wrapping it. Additional variable
+        * declaration fragments can be added afterwards.
+        * </p>
+        *
+        * @param fragment the first variable declaration fragment
+        * @return a new unparented variable declaration expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * <li>the given fragment is null</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */
+       public VariableDeclarationExpression
+                       newVariableDeclarationExpression(VariableDeclarationFragment fragment) {
+               if (fragment == null) {
+                       throw new IllegalArgumentException();
+               }
+               VariableDeclarationExpression result =
+                       new VariableDeclarationExpression(this);
+               result.fragments().add(fragment);
+               return result;
+       }
+
+       /**
+        * Creates a new unparented field declaration node owned by this AST,
+        * for the given variable declaration fragment. By default, there are no
+        * modifiers, no doc comment, and the base type is unspecified
+        * (but legal).
+        * <p>
+        * This method can be used to wrap a variable declaration fragment
+        * (<code>VariableDeclarationFragment</code>) into a field declaration
+        * suitable for inclusion in the body of a type declaration
+        * (<code>FieldDeclaration</code> implements <code>BodyDeclaration</code>).
+        * Additional variable declaration fragments can be added afterwards.
+        * </p>
+        *
+        * @param fragment the variable declaration fragment
+        * @return a new unparented field declaration node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * <li>the given fragment is null</li>
+        * </ul>
+        */
+       public FieldDeclaration newFieldDeclaration(VariableDeclarationFragment fragment) {
+               if (fragment == null) {
+                       throw new IllegalArgumentException();
+               }
+               FieldDeclaration result = new FieldDeclaration(this);
+               result.fragments().add(fragment);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented "this" expression node
+        * owned by this AST. By default, there is no qualifier.
+        *
+        * @return a new unparented "this" expression node
+        */
+       public ThisExpression newThisExpression() {
+               ThisExpression result = new ThisExpression(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented field access expression node
+        * owned by this AST. By default, the expression and field are both
+        * unspecified, but legal, names.
+        *
+        * @return a new unparented field access expression node
+        */
+       public FieldAccess newFieldAccess() {
+               FieldAccess result = new FieldAccess(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented super field access expression node
+        * owned by this AST. By default, the expression and field are both
+        * unspecified, but legal, names.
+        *
+        * @return a new unparented super field access expression node
+        */
+       public SuperFieldAccess newSuperFieldAccess() {
+               SuperFieldAccess result = new SuperFieldAccess(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented type literal expression node
+        * owned by this AST. By default, the type is unspecified (but legal).
+        *
+        * @return a new unparented type literal node
+        */
+       public TypeLiteral newTypeLiteral() {
+               TypeLiteral result = new TypeLiteral(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented cast expression node
+        * owned by this AST. By default, the type and expression are unspecified
+        * (but legal).
+        *
+        * @return a new unparented cast expression node
+        */
+       public CastExpression newCastExpression() {
+               CastExpression result = new CastExpression(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented parenthesized expression node
+        * owned by this AST. By default, the expression is unspecified (but legal).
+        *
+        * @return a new unparented parenthesized expression node
+        */
+       public ParenthesizedExpression newParenthesizedExpression() {
+               ParenthesizedExpression result = new ParenthesizedExpression(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented infix expression node
+        * owned by this AST. By default, the operator and left and right
+        * operand are unspecified (but legal), and there are no extended
+        * operands.
+        *
+        * @return a new unparented infix expression node
+        */
+       public InfixExpression newInfixExpression() {
+               InfixExpression result = new InfixExpression(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented instanceof expression node
+        * owned by this AST. By default, the operator and left and right
+        * operand are unspecified (but legal).
+        *
+        * @return a new unparented instanceof expression node
+        */
+       public InstanceofExpression newInstanceofExpression() {
+               InstanceofExpression result = new InstanceofExpression(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented postfix expression node
+        * owned by this AST. By default, the operator and operand are
+        * unspecified (but legal).
+        *
+        * @return a new unparented postfix expression node
+        */
+       public PostfixExpression newPostfixExpression() {
+               PostfixExpression result = new PostfixExpression(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented prefix expression node
+        * owned by this AST. By default, the operator and operand are
+        * unspecified (but legal).
+        *
+        * @return a new unparented prefix expression node
+        */
+       public PrefixExpression newPrefixExpression() {
+               PrefixExpression result = new PrefixExpression(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented array access expression node
+        * owned by this AST. By default, the array and index expression are
+        * both unspecified (but legal).
+        *
+        * @return a new unparented array access expression node
+        */
+       public ArrayAccess newArrayAccess() {
+               ArrayAccess result = new ArrayAccess(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented array creation expression node
+        * owned by this AST. By default, the array type is an unspecified
+        * 1-dimensional array, the list of dimensions is empty, and there is no
+        * array initializer.
+        * <p>
+        * Examples:
+        * <code>
+        * <pre>
+        * // new String[len]
+        * ArrayCreation ac1 = ast.newArrayCreation();
+        * ac1.setType(
+        *    ast.newArrayType(
+        *       ast.newSimpleType(ast.newSimpleName("String"))));
+        * ac1.dimensions().add(ast.newSimpleName("len"));
+     *
+        * // new double[7][24][]
+        * ArrayCreation ac2 = ast.newArrayCreation();
+        * ac2.setType(
+        *    ast.newArrayType(
+        *       ast.newPrimitiveType(PrimitiveType.DOUBLE), 3));
+        * ac2.dimensions().add(ast.newNumberLiteral("7"));
+        * ac2.dimensions().add(ast.newNumberLiteral("24"));
+        *
+        * // new int[] {1, 2}
+        * ArrayCreation ac3 = ast.newArrayCreation();
+        * ac3.setType(
+        *    ast.newArrayType(
+        *       ast.newPrimitiveType(PrimitiveType.INT)));
+        * ArrayInitializer ai = ast.newArrayInitializer();
+        * ac3.setInitializer(ai);
+        * ai.expressions().add(ast.newNumberLiteral("1"));
+        * ai.expressions().add(ast.newNumberLiteral("2"));
+        * </pre>
+        * </code>
+        * </p>
+        *
+        * @return a new unparented array creation expression node
+        */
+       public ArrayCreation newArrayCreation() {
+               ArrayCreation result = new ArrayCreation(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented class instance creation
+        * ("new") expression node owned by this AST. By default,
+        * there is no qualifying expression, no type parameters,
+        * an unspecified (but legal) type name, an empty list of
+        * arguments, and does not declare an anonymous class declaration.
+        *
+        * @return a new unparented class instance creation expression node
+        */
+       public ClassInstanceCreation newClassInstanceCreation() {
+               ClassInstanceCreation result = new ClassInstanceCreation(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented anonymous class declaration
+        * node owned by this AST. By default, the body declaration list is empty.
+        *
+        * @return a new unparented anonymous class declaration node
+        */
+       public AnonymousClassDeclaration newAnonymousClassDeclaration() {
+               AnonymousClassDeclaration result = new AnonymousClassDeclaration(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented array initializer node
+        * owned by this AST. By default, the initializer has no expressions.
+        *
+        * @return a new unparented array initializer node
+        */
+       public ArrayInitializer newArrayInitializer() {
+               ArrayInitializer result = new ArrayInitializer(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented conditional expression node
+        * owned by this AST. By default, the condition and both expressions
+        * are unspecified (but legal).
+        *
+        * @return a new unparented array conditional expression node
+        */
+       public ConditionalExpression newConditionalExpression() {
+               ConditionalExpression result = new ConditionalExpression(this);
+               return result;
+       }
+
+       //=============================== ANNOTATIONS ====================
+
+       /**
+        * Creates and returns a new unparented normal annotation node with
+        * an unspecified type name and an empty list of member value
+        * pairs.
+        *
+        * @return a new unparented normal annotation node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public NormalAnnotation newNormalAnnotation() {
+               NormalAnnotation result = new NormalAnnotation(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented marker annotation node with
+        * an unspecified type name.
+        *
+        * @return a new unparented marker annotation node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public MarkerAnnotation newMarkerAnnotation() {
+               MarkerAnnotation result = new MarkerAnnotation(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented single member annotation node with
+        * an unspecified type name and value.
+        *
+        * @return a new unparented single member annotation node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public SingleMemberAnnotation newSingleMemberAnnotation() {
+               SingleMemberAnnotation result = new SingleMemberAnnotation(this);
+               return result;
+       }
+
+       /**
+        * Creates and returns a new unparented member value pair node with
+        * an unspecified member name and value.
+        *
+        * @return a new unparented member value pair node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public MemberValuePair newMemberValuePair() {
+               MemberValuePair result = new MemberValuePair(this);
+               return result;
+       }
+
+       /**
+        * Enables the recording of changes to the given 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 the 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 if recording has already been enabled,
+        * or if <code>root</code> is not owned by this AST
+        * @see CompilationUnit#recordModifications()
+        * @since 3.0
+        */
+       void recordModifications(CompilationUnit root) {
+               if(this.modificationCount != this.originalModificationCount) {
+                       throw new IllegalArgumentException("AST is already modified"); //$NON-NLS-1$
+               } else if(this.rewriter  != null) {
+                       throw new IllegalArgumentException("AST modifications are already recorded"); //$NON-NLS-1$
+               } else if((root.getFlags() & ASTNode.PROTECT) != 0) {
+                       throw new IllegalArgumentException("Root node is unmodifiable"); //$NON-NLS-1$
+               } else if(root.getAST() != this) {
+                       throw new IllegalArgumentException("Root node is not owned by this ast"); //$NON-NLS-1$
+               }
+
+               this.rewriter = new InternalASTRewrite(root);
+               this.setEventHandler(this.rewriter);
+       }
+
+       /**
+        * Converts all modifications recorded into an object
+        * representing the corresponding text edits to the
+        * given document containing the original source
+        * code for the compilation unit that gave rise to
+        * this AST.
+        *
+        * @param document original document containing source code
+        * for the 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 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 CompilationUnit#rewrite(IDocument, Map)
+        * @since 3.0
+        */
+       TextEdit rewrite(IDocument document, Map options) {
+               if (document == null) {
+                       throw new IllegalArgumentException();
+               }
+               if (this.rewriter  == null) {
+                       throw new IllegalStateException("Modifications record is not enabled"); //$NON-NLS-1$
+               }
+               return this.rewriter.rewriteAST(document, options);
+       }
+
+       /**
+        * Returns true if the ast tree was created with bindings, false otherwise
+        *
+        * @return true if the ast tree was created with bindings, false otherwise
+        * @since 3.3
+        */
+       public boolean hasResolvedBindings() {
+               return (this.bits & RESOLVED_BINDINGS) != 0;
+       }
+
+       /**
+        * Returns true if the ast tree was created with statements recovery, false otherwise
+        *
+        * @return true if the ast tree was created with statements recovery, false otherwise
+        * @since 3.3
+        */
+       public boolean hasStatementsRecovery() {
+               return (this.bits & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0;
+       }
+
+       /**
+        * Returns true if the ast tree was created with bindings recovery, false otherwise
+        *
+        * @return true if the ast tree was created with bindings recovery, false otherwise
+        * @since 3.3
+        */
+       public boolean hasBindingsRecovery() {
+               return (this.bits & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0;
+       }
+
+       void setFlag(int newValue) {
+               this.bits |= newValue;
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTConverter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTConverter.java
new file mode 100644 (file)
index 0000000..811db7a
--- /dev/null
@@ -0,0 +1,5221 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.compiler.CategorizedProblem;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.core.dom.Modifier.ModifierKeyword;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractVariableDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Argument;
+import net.sourceforge.phpdt.internal.compiler.ast.ForeachStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.JavadocArgumentExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.JavadocFieldReference;
+import net.sourceforge.phpdt.internal.compiler.ast.JavadocMessageSend;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.MessageSend;
+import net.sourceforge.phpdt.internal.compiler.ast.OperatorIds;
+import net.sourceforge.phpdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedAllocationExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.SingleNameReference;
+import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.StringLiteralConcatenation;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.Wildcard;
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
+import net.sourceforge.phpdt.internal.compiler.parser.RecoveryScanner;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Internal class for converting internal compiler ASTs into public ASTs.
+ */
+class ASTConverter {
+
+       protected AST ast;
+       protected Comment[] commentsTable;
+       char[] compilationUnitSource;
+       int compilationUnitSourceLength;
+       protected DocCommentParser docParser;
+       // comments
+       protected boolean insideComments;
+       protected IProgressMonitor monitor;
+       protected Set pendingNameScopeResolution;       
+       protected Set pendingThisExpressionScopeResolution;
+       protected boolean resolveBindings;
+       Scanner scanner;
+       private DefaultCommentMapper commentMapper;
+
+       public ASTConverter(Map options, boolean resolveBindings, IProgressMonitor monitor) {
+               this.resolveBindings = resolveBindings;
+               Object sourceModeSetting = options.get(JavaCore.COMPILER_SOURCE);
+               long sourceLevel = CompilerOptions.versionToJdkLevel(sourceModeSetting);
+               if (sourceLevel == 0) {
+                       // unknown sourceModeSetting
+                       sourceLevel = ClassFileConstants.JDK1_3;
+               }
+               this.scanner = new Scanner(
+                       true /*comment*/,
+                       false /*whitespace*/,
+                       false /*nls*/,
+                       sourceLevel /*sourceLevel*/,
+                       null /*taskTags*/,
+                       null/*taskPriorities*/,
+                       true/*taskCaseSensitive*/);
+               this.monitor = monitor;
+               this.insideComments = JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_DOC_COMMENT_SUPPORT));
+       }
+       
+       protected void adjustSourcePositionsForParent(net.sourceforge.phpdt.internal.compiler.ast.Expression expression) {
+               int start = expression.sourceStart;
+               int end = expression.sourceEnd;
+               int leftParentCount = 1;
+               int rightParentCount = 0;
+               this.scanner.resetTo(start, end);
+               try {
+                       int token = this.scanner.getNextToken();
+                       expression.sourceStart = this.scanner.currentPosition;
+                       boolean stop = false;
+                       while (!stop && ((token  = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameLPAREN:
+                                               leftParentCount++;
+                                               break;
+                                       case TerminalTokens.TokenNameRPAREN:
+                                               rightParentCount++;
+                                               if (rightParentCount == leftParentCount) {
+                                                       // we found the matching parenthesis
+                                                       stop = true;
+                                               }
+                               }
+                       }
+                       expression.sourceEnd = this.scanner.startPosition - 1;
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+       }
+
+       protected void buildBodyDeclarations(net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration, AbstractTypeDeclaration typeDecl) {
+               // add body declaration in the lexical order
+               net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration[] members = typeDeclaration.memberTypes;
+               net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration[] fields = typeDeclaration.fields;
+               net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+               
+               int fieldsLength = fields == null? 0 : fields.length;
+               int methodsLength = methods == null? 0 : methods.length;
+               int membersLength = members == null ? 0 : members.length;
+               int fieldsIndex = 0;
+               int methodsIndex = 0;
+               int membersIndex = 0;
+               
+               while ((fieldsIndex < fieldsLength)
+                       || (membersIndex < membersLength)
+                       || (methodsIndex < methodsLength)) {
+                       net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
+                       net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
+               
+                       int position = Integer.MAX_VALUE;
+                       int nextDeclarationType = -1;
+                       if (fieldsIndex < fieldsLength) {
+                               nextFieldDeclaration = fields[fieldsIndex];
+                               if (nextFieldDeclaration.declarationSourceStart < position) {
+                                       position = nextFieldDeclaration.declarationSourceStart;
+                                       nextDeclarationType = 0; // FIELD
+                               }
+                       }
+                       if (methodsIndex < methodsLength) {
+                               nextMethodDeclaration = methods[methodsIndex];
+                               if (nextMethodDeclaration.declarationSourceStart < position) {
+                                       position = nextMethodDeclaration.declarationSourceStart;
+                                       nextDeclarationType = 1; // METHOD
+                               }
+                       }
+                       if (membersIndex < membersLength) {
+                               nextMemberDeclaration = members[membersIndex];
+                               if (nextMemberDeclaration.declarationSourceStart < position) {
+                                       position = nextMemberDeclaration.declarationSourceStart;
+                                       nextDeclarationType = 2; // MEMBER
+                               }
+                       }
+                       switch (nextDeclarationType) {
+                               case 0 :
+                                       if (nextFieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+                                               typeDecl.bodyDeclarations().add(convert(nextFieldDeclaration));
+                                       } else {
+                                               checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, typeDecl.bodyDeclarations());
+                                       }
+                                       fieldsIndex++;
+                                       break;
+                               case 1 :
+                                       methodsIndex++;
+                                       if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+                                               typeDecl.bodyDeclarations().add(convert(nextMethodDeclaration));
+                                       }
+                                       break;
+                               case 2 :
+                                       membersIndex++;
+                                       ASTNode node = convert(nextMemberDeclaration);
+                                       if (node == null) {
+                                               typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+                                       } else {
+                                               typeDecl.bodyDeclarations().add(node);
+                                       }
+                       }
+               }
+               // Convert javadoc
+               convert(typeDeclaration.javadoc, typeDecl);
+       }
+       
+       protected void buildBodyDeclarations(net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration enumDeclaration2, EnumDeclaration enumDeclaration) {
+               // add body declaration in the lexical order
+               net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration[] members = enumDeclaration2.memberTypes;
+               net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration[] fields = enumDeclaration2.fields;
+               net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = enumDeclaration2.methods;
+               
+               int fieldsLength = fields == null? 0 : fields.length;
+               int methodsLength = methods == null? 0 : methods.length;
+               int membersLength = members == null ? 0 : members.length;
+               int fieldsIndex = 0;
+               int methodsIndex = 0;
+               int membersIndex = 0;
+               
+               while ((fieldsIndex < fieldsLength)
+                       || (membersIndex < membersLength)
+                       || (methodsIndex < methodsLength)) {
+                       net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
+                       net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
+               
+                       int position = Integer.MAX_VALUE;
+                       int nextDeclarationType = -1;
+                       if (fieldsIndex < fieldsLength) {
+                               nextFieldDeclaration = fields[fieldsIndex];
+                               if (nextFieldDeclaration.declarationSourceStart < position) {
+                                       position = nextFieldDeclaration.declarationSourceStart;
+                                       nextDeclarationType = 0; // FIELD
+                               }
+                       }
+                       if (methodsIndex < methodsLength) {
+                               nextMethodDeclaration = methods[methodsIndex];
+                               if (nextMethodDeclaration.declarationSourceStart < position) {
+                                       position = nextMethodDeclaration.declarationSourceStart;
+                                       nextDeclarationType = 1; // METHOD
+                               }
+                       }
+                       if (membersIndex < membersLength) {
+                               nextMemberDeclaration = members[membersIndex];
+                               if (nextMemberDeclaration.declarationSourceStart < position) {
+                                       position = nextMemberDeclaration.declarationSourceStart;
+                                       nextDeclarationType = 2; // MEMBER
+                               }
+                       }
+                       switch (nextDeclarationType) {
+                               case 0 :
+                                       if (nextFieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+                                               enumDeclaration.enumConstants().add(convert(nextFieldDeclaration));
+                                       } else {
+                                               checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, enumDeclaration.bodyDeclarations());
+                                       }
+                                       fieldsIndex++;
+                                       break;
+                               case 1 :
+                                       methodsIndex++;
+                                       if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+                                               enumDeclaration.bodyDeclarations().add(convert(nextMethodDeclaration));
+                                       }
+                                       break;
+                               case 2 :
+                                       membersIndex++;
+                                       enumDeclaration.bodyDeclarations().add(convert(nextMemberDeclaration));
+                                       break;
+                       }
+               }
+               convert(enumDeclaration2.javadoc, enumDeclaration);
+       }
+       
+       protected void buildBodyDeclarations(net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration expression, AnonymousClassDeclaration anonymousClassDeclaration) {
+               // add body declaration in the lexical order
+               net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration[] members = expression.memberTypes;
+               net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration[] fields = expression.fields;
+               net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = expression.methods;
+               
+               int fieldsLength = fields == null? 0 : fields.length;
+               int methodsLength = methods == null? 0 : methods.length;
+               int membersLength = members == null ? 0 : members.length;
+               int fieldsIndex = 0;
+               int methodsIndex = 0;
+               int membersIndex = 0;
+               
+               while ((fieldsIndex < fieldsLength)
+                       || (membersIndex < membersLength)
+                       || (methodsIndex < methodsLength)) {
+                       net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
+                       net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
+               
+                       int position = Integer.MAX_VALUE;
+                       int nextDeclarationType = -1;
+                       if (fieldsIndex < fieldsLength) {
+                               nextFieldDeclaration = fields[fieldsIndex];
+                               if (nextFieldDeclaration.declarationSourceStart < position) {
+                                       position = nextFieldDeclaration.declarationSourceStart;
+                                       nextDeclarationType = 0; // FIELD
+                               }
+                       }
+                       if (methodsIndex < methodsLength) {
+                               nextMethodDeclaration = methods[methodsIndex];
+                               if (nextMethodDeclaration.declarationSourceStart < position) {
+                                       position = nextMethodDeclaration.declarationSourceStart;
+                                       nextDeclarationType = 1; // METHOD
+                               }
+                       }
+                       if (membersIndex < membersLength) {
+                               nextMemberDeclaration = members[membersIndex];
+                               if (nextMemberDeclaration.declarationSourceStart < position) {
+                                       position = nextMemberDeclaration.declarationSourceStart;
+                                       nextDeclarationType = 2; // MEMBER
+                               }
+                       }
+                       switch (nextDeclarationType) {
+                               case 0 :
+                                       if (nextFieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
+                                               anonymousClassDeclaration.bodyDeclarations().add(convert(nextFieldDeclaration));
+                                       } else {
+                                               checkAndAddMultipleFieldDeclaration(fields, fieldsIndex, anonymousClassDeclaration.bodyDeclarations());
+                                       }
+                                       fieldsIndex++;
+                                       break;
+                               case 1 :
+                                       methodsIndex++;
+                                       if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+                                               anonymousClassDeclaration.bodyDeclarations().add(convert(nextMethodDeclaration));
+                                       }
+                                       break;
+                               case 2 :
+                                       membersIndex++;
+                                       ASTNode node = convert(nextMemberDeclaration);
+                                       if (node == null) {
+                                               anonymousClassDeclaration.setFlags(anonymousClassDeclaration.getFlags() | ASTNode.MALFORMED);
+                                       } else {
+                                               anonymousClassDeclaration.bodyDeclarations().add(node);
+                                       }
+                       }
+               }
+       }
+       
+       /**
+        * @param compilationUnit
+        * @param comments
+        */
+       void buildCommentsTable(CompilationUnit compilationUnit, int[][] comments) {
+               // Build comment table
+               this.commentsTable = new Comment[comments.length];
+               int nbr = 0;
+               for (int i = 0; i < comments.length; i++) {
+                       Comment comment = createComment(comments[i]);
+                       if (comment != null) {
+                               comment.setAlternateRoot(compilationUnit);
+                               this.commentsTable[nbr++] = comment;
+                       }
+               }
+               // Resize table if  necessary
+               if (nbr<comments.length) {
+                       Comment[] newCommentsTable = new Comment[nbr];
+                       System.arraycopy(this.commentsTable, 0, newCommentsTable, 0, nbr);
+                       this.commentsTable = newCommentsTable;
+               }
+               compilationUnit.setCommentTable(this.commentsTable);
+       }
+       
+       protected void checkAndAddMultipleFieldDeclaration(net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration[] fields, int index, List bodyDeclarations) {
+               if (fields[index] instanceof net.sourceforge.phpdt.internal.compiler.ast.Initializer) {
+                       net.sourceforge.phpdt.internal.compiler.ast.Initializer oldInitializer = (net.sourceforge.phpdt.internal.compiler.ast.Initializer) fields[index];
+                       Initializer initializer = new Initializer(this.ast);
+                       initializer.setBody(convert(oldInitializer.block));
+                       setModifiers(initializer, oldInitializer);
+                       initializer.setSourceRange(oldInitializer.declarationSourceStart, oldInitializer.sourceEnd - oldInitializer.declarationSourceStart + 1);
+                       // The javadoc comment is now got from list store in compilation unit declaration
+                       convert(oldInitializer.javadoc, initializer);
+                       bodyDeclarations.add(initializer);
+                       return;
+               }
+               if (index > 0 && fields[index - 1].declarationSourceStart == fields[index].declarationSourceStart) {
+                       // we have a multiple field declaration
+                       // We retrieve the existing fieldDeclaration to add the new VariableDeclarationFragment
+                       FieldDeclaration fieldDeclaration = (FieldDeclaration) bodyDeclarations.get(bodyDeclarations.size() - 1);
+                       fieldDeclaration.fragments().add(convertToVariableDeclarationFragment(fields[index]));
+               } else {
+                       // we can create a new FieldDeclaration
+                       bodyDeclarations.add(convertToFieldDeclaration(fields[index]));
+               }
+       }
+
+       protected void checkAndAddMultipleLocalDeclaration(net.sourceforge.phpdt.internal.compiler.ast.Statement[] stmts, int index, List blockStatements) {
+               if (index > 0
+                               && stmts[index - 1] instanceof net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration local1 = (net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) stmts[index - 1];
+                       net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration local2 = (net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) stmts[index];
+                       if (local1.declarationSourceStart == local2.declarationSourceStart) {
+                               // we have a multiple local declarations
+                               // We retrieve the existing VariableDeclarationStatement to add the new VariableDeclarationFragment
+                               VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) blockStatements.get(blockStatements.size() - 1);
+                               variableDeclarationStatement.fragments().add(convertToVariableDeclarationFragment((net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
+                       } else {
+                               // we can create a new FieldDeclaration
+                               blockStatements.add(convertToVariableDeclarationStatement((net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
+                       }
+               } else {
+                       // we can create a new FieldDeclaration
+                       blockStatements.add(convertToVariableDeclarationStatement((net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
+               }
+       }
+
+       protected void checkCanceled() {
+               if (this.monitor != null && this.monitor.isCanceled())
+                       throw new OperationCanceledException();
+       }
+
+       protected void completeRecord(ArrayType arrayType, net.sourceforge.phpdt.internal.compiler.ast.ASTNode astNode) {
+               ArrayType array = arrayType;
+               int dimensions = array.getDimensions();
+               for (int i = 0; i < dimensions; i++) {
+                       Type componentType = array.getComponentType();
+                       this.recordNodes(componentType, astNode);
+                       if (componentType.isArrayType()) {
+                               array = (ArrayType) componentType;
+                       }
+               }
+       }
+               
+       public ASTNode convert(net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration) {
+               checkCanceled();
+               if (methodDeclaration instanceof net.sourceforge.phpdt.internal.compiler.ast.AnnotationMethodDeclaration) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.AnnotationMethodDeclaration) methodDeclaration);
+               }
+               MethodDeclaration methodDecl = new MethodDeclaration(this.ast);
+               setModifiers(methodDecl, methodDeclaration);
+               boolean isConstructor = methodDeclaration.isConstructor();
+               methodDecl.setConstructor(isConstructor);
+               final SimpleName methodName = new SimpleName(this.ast);
+               methodName.internalSetIdentifier(new String(methodDeclaration.selector));
+               int start = methodDeclaration.sourceStart;
+               int end = retrieveIdentifierEndPosition(start, methodDeclaration.sourceEnd);
+               methodName.setSourceRange(start, end - start + 1);
+               methodDecl.setName(methodName);
+               net.sourceforge.phpdt.internal.compiler.ast.TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
+               int methodHeaderEnd = methodDeclaration.sourceEnd;
+               int thrownExceptionsLength = thrownExceptions == null ? 0 : thrownExceptions.length;
+               if (thrownExceptionsLength > 0) {
+                       Name thrownException;
+                       int i = 0;
+                       do {
+                               thrownException = convert(thrownExceptions[i++]);
+                               methodDecl.thrownExceptions().add(thrownException);
+                       } while (i < thrownExceptionsLength);
+                       methodHeaderEnd = thrownException.getStartPosition() + thrownException.getLength();
+               }
+               net.sourceforge.phpdt.internal.compiler.ast.Argument[] parameters = methodDeclaration.arguments;
+               int parametersLength = parameters == null ? 0 : parameters.length;
+               if (parametersLength > 0) {
+                       SingleVariableDeclaration parameter;
+                       int i = 0;
+                       do {
+                               parameter = convert(parameters[i++]);
+                               methodDecl.parameters().add(parameter);
+                       } while (i < parametersLength);
+                       if (thrownExceptionsLength == 0) {
+                               methodHeaderEnd = parameter.getStartPosition() + parameter.getLength();
+                       }
+               }
+               net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall explicitConstructorCall = null;
+               if (isConstructor) {
+                       net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration constructorDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration) methodDeclaration;
+                       explicitConstructorCall = constructorDeclaration.constructorCall;
+                       switch(this.ast.apiLevel) {
+                               case AST.JLS2_INTERNAL :
+                                       // set the return type to VOID
+                                       PrimitiveType returnType = new PrimitiveType(this.ast);
+                                       returnType.setPrimitiveTypeCode(PrimitiveType.VOID);
+                                       returnType.setSourceRange(methodDeclaration.sourceStart, 0);
+                                       methodDecl.internalSetReturnType(returnType);
+                                       break;
+                               case AST.JLS3 :
+                                       methodDecl.setReturnType2(null);
+                       }
+               } else if (methodDeclaration instanceof net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration method = (net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration) methodDeclaration;
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeReference typeReference = method.returnType;
+                       if (typeReference != null) {
+                               Type returnType = convertType(typeReference);
+                               // get the positions of the right parenthesis
+                               int rightParenthesisPosition = retrieveEndOfRightParenthesisPosition(end, method.bodyEnd);
+                               int extraDimensions = retrieveExtraDimension(rightParenthesisPosition, method.bodyEnd);
+                               methodDecl.setExtraDimensions(extraDimensions);
+                               setTypeForMethodDeclaration(methodDecl, returnType, extraDimensions);
+                       } else {
+                               switch(this.ast.apiLevel) {
+                                       case AST.JLS2_INTERNAL :
+                                               methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+                                               break;
+                                       case AST.JLS3 :
+                                               methodDecl.setReturnType2(null);
+                               }
+                       }
+               }
+               int declarationSourceStart = methodDeclaration.declarationSourceStart;
+               int declarationSourceEnd = methodDeclaration.bodyEnd;
+               methodDecl.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+               int closingPosition = retrieveRightBraceOrSemiColonPosition(methodDeclaration.bodyEnd + 1, methodDeclaration.declarationSourceEnd);
+               if (closingPosition != -1) {
+                       int startPosition = methodDecl.getStartPosition();
+                       methodDecl.setSourceRange(startPosition, closingPosition - startPosition + 1);
+
+                       net.sourceforge.phpdt.internal.compiler.ast.Statement[] statements = methodDeclaration.statements;
+                       
+                       start = retrieveStartBlockPosition(methodHeaderEnd, methodDeclaration.bodyStart);
+                       if (start == -1) start = methodDeclaration.bodyStart; // use recovery position for body start
+                       end = retrieveRightBrace(methodDeclaration.bodyEnd, methodDeclaration.declarationSourceEnd);
+                       Block block = null;
+                       if (start != -1 && end != -1) {
+                               /*
+                                * start or end can be equal to -1 if we have an interface's method.
+                                */
+                               block = new Block(this.ast);
+                               block.setSourceRange(start, closingPosition - start + 1);
+                               methodDecl.setBody(block);
+                       }
+                       if (block != null && (statements != null || explicitConstructorCall != null)) {
+                               if (explicitConstructorCall != null && explicitConstructorCall.accessMode != net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall.ImplicitSuper) {
+                                       block.statements().add(convert(explicitConstructorCall));
+                               }
+                               int statementsLength = statements == null ? 0 : statements.length;
+                               for (int i = 0; i < statementsLength; i++) {
+                                       if (statements[i] instanceof net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) {
+                                               checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
+                                       } else {
+                                               final Statement statement = convert(statements[i]);
+                                               if (statement != null) {
+                                                       block.statements().add(statement);
+                                               }
+                                       }
+                               }
+                       }
+                       if (block != null && (Modifier.isAbstract(methodDecl.getModifiers()) || Modifier.isNative(methodDecl.getModifiers()))) {
+                               methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+                       }
+               } else {
+                       // syntax error in this method declaration
+                       methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+                       if (!methodDeclaration.isNative() && !methodDeclaration.isAbstract()) {
+                               start = retrieveStartBlockPosition(methodHeaderEnd, declarationSourceEnd);
+                               if (start == -1) start = methodDeclaration.bodyStart; // use recovery position for body start
+                               end = methodDeclaration.bodyEnd;
+                               // try to get the best end position
+                               CategorizedProblem[] problems = methodDeclaration.compilationResult().problems;
+                               if (problems != null) {
+                                       for (int i = 0, max = methodDeclaration.compilationResult().problemCount; i < max; i++) {
+                                               CategorizedProblem currentProblem = problems[i];
+                                               if (currentProblem.getSourceStart() == start && currentProblem.getID() == IProblem.ParsingErrorInsertToComplete) {
+                                                       end = currentProblem.getSourceEnd();
+                                                       break;
+                                               }
+                                       }
+                               }
+                               int startPosition = methodDecl.getStartPosition();
+                               methodDecl.setSourceRange(startPosition, end - startPosition + 1);
+                               if (start != -1 && end != -1) {
+                                       /*
+                                        * start or end can be equal to -1 if we have an interface's method.
+                                        */
+                                       Block block = new Block(this.ast);
+                                       block.setSourceRange(start, end - start + 1);
+                                       methodDecl.setBody(block);
+                               }
+                       }                       
+               }
+
+               net.sourceforge.phpdt.internal.compiler.ast.TypeParameter[] typeParameters = methodDeclaration.typeParameters();
+               if (typeParameters != null) {
+                       switch(this.ast.apiLevel) {
+                               case AST.JLS2_INTERNAL :
+                                       methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+                                       break;
+                               case AST.JLS3 :
+                                       for (int i = 0, max = typeParameters.length; i < max; i++) {
+                                               methodDecl.typeParameters().add(convert(typeParameters[i]));
+                                       }
+                       }
+               }
+               
+               // The javadoc comment is now got from list store in compilation unit declaration
+               convert(methodDeclaration.javadoc, methodDecl);
+               if (this.resolveBindings) {
+                       recordNodes(methodDecl, methodDeclaration);
+                       recordNodes(methodName, methodDeclaration);
+                       methodDecl.resolveBinding();
+               }
+               return methodDecl;
+       }       
+       
+       public ClassInstanceCreation convert(net.sourceforge.phpdt.internal.compiler.ast.AllocationExpression expression) {
+               ClassInstanceCreation classInstanceCreation = new ClassInstanceCreation(this.ast);
+               if (this.resolveBindings) {
+                       recordNodes(classInstanceCreation, expression);
+               }
+               if (expression.typeArguments != null) {
+                       switch(this.ast.apiLevel) {
+                               case AST.JLS2_INTERNAL :
+                                       classInstanceCreation.setFlags(classInstanceCreation.getFlags() | ASTNode.MALFORMED);
+                                       break;
+                               case AST.JLS3 :
+                                       for (int i = 0, max = expression.typeArguments.length; i < max; i++) {
+                                               classInstanceCreation.typeArguments().add(convertType(expression.typeArguments[i]));
+                                       }
+                       }
+               }
+               switch(this.ast.apiLevel) {
+                       case AST.JLS2_INTERNAL :
+                               classInstanceCreation.internalSetName(convert(expression.type));
+                               break;
+                       case AST.JLS3 :
+                               classInstanceCreation.setType(convertType(expression.type));
+               }
+               classInstanceCreation.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               net.sourceforge.phpdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
+               if (arguments != null) {
+                       int length = arguments.length;
+                       for (int i = 0; i < length; i++) {
+                               classInstanceCreation.arguments().add(convert(arguments[i]));
+                       }
+               }
+               removeTrailingCommentFromExpressionEndingWithAParen(classInstanceCreation);
+               return classInstanceCreation;
+       }
+
+       public Expression convert(net.sourceforge.phpdt.internal.compiler.ast.AND_AND_Expression expression) {
+               InfixExpression infixExpression = new InfixExpression(this.ast);
+               infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
+               if (this.resolveBindings) {
+                       this.recordNodes(infixExpression, expression);
+               }
+               final int expressionOperatorID = (expression.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorSHIFT;
+               if (expression.left instanceof net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression
+                               && ((expression.left.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)) {
+                       // create an extended string literal equivalent => use the extended operands list
+                       infixExpression.extendedOperands().add(convert(expression.right));
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression leftOperand = expression.left;
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression rightOperand = null;
+                       do {
+                               rightOperand = ((net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression) leftOperand).right;
+                               if ((((leftOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID
+                                                       && ((leftOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))
+                                        || ((rightOperand instanceof net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression
+                                                       && ((rightOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID)
+                                                       && ((rightOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))) {
+                                       List extendedOperands = infixExpression.extendedOperands();
+                                       InfixExpression temp = new InfixExpression(this.ast);
+                                       if (this.resolveBindings) {
+                                               this.recordNodes(temp, expression);
+                                       }
+                                       temp.setOperator(getOperatorFor(expressionOperatorID));
+                                       Expression leftSide = convert(leftOperand);
+                                       temp.setLeftOperand(leftSide);
+                                       temp.setSourceRange(leftSide.getStartPosition(), leftSide.getLength());
+                                       int size = extendedOperands.size();
+                                       for (int i = 0; i < size - 1; i++) {
+                                               Expression expr = temp;
+                                               temp = new InfixExpression(this.ast);
+                                               
+                                               if (this.resolveBindings) {
+                                                       this.recordNodes(temp, expression);
+                                               }                                       
+                                               temp.setLeftOperand(expr);
+                                               temp.setOperator(getOperatorFor(expressionOperatorID));
+                                               temp.setSourceRange(expr.getStartPosition(), expr.getLength());
+                                       }
+                                       infixExpression = temp;
+                                       for (int i = 0; i < size; i++) {
+                                               Expression extendedOperand = (Expression) extendedOperands.remove(size - 1 - i);
+                                               temp.setRightOperand(extendedOperand);
+                                               int startPosition = temp.getLeftOperand().getStartPosition();
+                                               temp.setSourceRange(startPosition, extendedOperand.getStartPosition() + extendedOperand.getLength() - startPosition);
+                                               if (temp.getLeftOperand().getNodeType() == ASTNode.INFIX_EXPRESSION) {
+                                                       temp = (InfixExpression) temp.getLeftOperand();
+                                               }
+                                       }
+                                       int startPosition = infixExpression.getLeftOperand().getStartPosition();
+                                       infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+                                       if (this.resolveBindings) {
+                                               this.recordNodes(infixExpression, expression);
+                                       }
+                                       return infixExpression;
+                               }
+                               infixExpression.extendedOperands().add(0, convert(rightOperand));
+                               leftOperand = ((net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression) leftOperand).left;
+                       } while (leftOperand instanceof net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression && ((leftOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0));
+                       Expression leftExpression = convert(leftOperand);
+                       infixExpression.setLeftOperand(leftExpression);
+                       infixExpression.setRightOperand((Expression)infixExpression.extendedOperands().remove(0));
+                       int startPosition = leftExpression.getStartPosition();
+                       infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+                       return infixExpression;
+               }
+               Expression leftExpression = convert(expression.left);
+               infixExpression.setLeftOperand(leftExpression);
+               infixExpression.setRightOperand(convert(expression.right));
+               infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
+               int startPosition = leftExpression.getStartPosition();
+               infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+               return infixExpression;
+       }
+
+       public AnnotationTypeDeclaration convertToAnnotationDeclaration(net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+               checkCanceled();
+               AnnotationTypeDeclaration typeDecl = this.ast.newAnnotationTypeDeclaration();
+               setModifiers(typeDecl, typeDeclaration);
+               final SimpleName typeName = new SimpleName(this.ast);
+               typeName.internalSetIdentifier(new String(typeDeclaration.name));
+               typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
+               typeDecl.setName(typeName);
+               typeDecl.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
+               
+               buildBodyDeclarations(typeDeclaration, typeDecl);
+               // The javadoc comment is now got from list store in compilation unit declaration
+               if (this.resolveBindings) {
+                       recordNodes(typeDecl, typeDeclaration);
+                       recordNodes(typeName, typeDeclaration);
+                       typeDecl.resolveBinding();
+               }
+               return typeDecl;
+       }
+       
+       public ASTNode convert(net.sourceforge.phpdt.internal.compiler.ast.AnnotationMethodDeclaration annotationTypeMemberDeclaration) {
+               checkCanceled();
+               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                       return null;
+               }
+               AnnotationTypeMemberDeclaration annotationTypeMemberDeclaration2 = new AnnotationTypeMemberDeclaration(this.ast);
+               setModifiers(annotationTypeMemberDeclaration2, annotationTypeMemberDeclaration);
+               final SimpleName methodName = new SimpleName(this.ast);
+               methodName.internalSetIdentifier(new String(annotationTypeMemberDeclaration.selector));
+               int start = annotationTypeMemberDeclaration.sourceStart;
+               int end = retrieveIdentifierEndPosition(start, annotationTypeMemberDeclaration.sourceEnd);
+               methodName.setSourceRange(start, end - start + 1);
+               annotationTypeMemberDeclaration2.setName(methodName);
+               net.sourceforge.phpdt.internal.compiler.ast.TypeReference typeReference = annotationTypeMemberDeclaration.returnType;
+               if (typeReference != null) {
+                       Type returnType = convertType(typeReference);
+                       setTypeForMethodDeclaration(annotationTypeMemberDeclaration2, returnType, 0);
+               }
+               int declarationSourceStart = annotationTypeMemberDeclaration.declarationSourceStart;
+               int declarationSourceEnd = annotationTypeMemberDeclaration.bodyEnd;
+               annotationTypeMemberDeclaration2.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+               // The javadoc comment is now got from list store in compilation unit declaration
+               convert(annotationTypeMemberDeclaration.javadoc, annotationTypeMemberDeclaration2);
+               net.sourceforge.phpdt.internal.compiler.ast.Expression memberValue = annotationTypeMemberDeclaration.defaultValue;
+               if (memberValue != null) {
+                       annotationTypeMemberDeclaration2.setDefault(convert(memberValue));
+               }
+               if (this.resolveBindings) {
+                       recordNodes(annotationTypeMemberDeclaration2, annotationTypeMemberDeclaration);
+                       recordNodes(methodName, annotationTypeMemberDeclaration);
+                       annotationTypeMemberDeclaration2.resolveBinding();
+               }
+               return annotationTypeMemberDeclaration2;
+       }
+       
+       public SingleVariableDeclaration convert(net.sourceforge.phpdt.internal.compiler.ast.Argument argument) {
+               SingleVariableDeclaration variableDecl = new SingleVariableDeclaration(this.ast);
+               setModifiers(variableDecl, argument);
+               final SimpleName name = new SimpleName(this.ast);
+               name.internalSetIdentifier(new String(argument.name));
+               int start = argument.sourceStart;
+               int nameEnd = argument.sourceEnd;
+               name.setSourceRange(start, nameEnd - start + 1);
+               variableDecl.setName(name);
+               final int typeSourceEnd = argument.type.sourceEnd;
+               final int extraDimensions = retrieveExtraDimension(nameEnd + 1, typeSourceEnd);
+               variableDecl.setExtraDimensions(extraDimensions);
+               final boolean isVarArgs = argument.isVarArgs();
+               if (isVarArgs && extraDimensions == 0) {
+                       // remove the ellipsis from the type source end
+                       argument.type.sourceEnd = retrieveEllipsisStartPosition(argument.type.sourceStart, typeSourceEnd);
+               }
+               Type type = convertType(argument.type);
+               int typeEnd = type.getStartPosition() + type.getLength() - 1;
+               int rightEnd = Math.max(typeEnd, argument.declarationSourceEnd);
+               /*
+                * There is extra work to do to set the proper type positions
+                * See PR http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284
+                */
+               if (isVarArgs) {
+                       setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions + 1);
+                       if (extraDimensions != 0) {
+                               variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+                       }
+               } else {
+                       setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions);
+               }
+               variableDecl.setSourceRange(argument.declarationSourceStart, rightEnd - argument.declarationSourceStart + 1);
+               
+               if (isVarArgs) {
+                       switch(this.ast.apiLevel) {
+                               case AST.JLS2_INTERNAL :
+                                       variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+                                       break;
+                               case AST.JLS3 :
+                                       variableDecl.setVarargs(true);
+                       }
+               }
+               if (this.resolveBindings) {
+                       recordNodes(name, argument);
+                       recordNodes(variableDecl, argument);
+                       variableDecl.resolveBinding();
+               }
+               return variableDecl;
+       }
+
+       
+       public Annotation convert(net.sourceforge.phpdt.internal.compiler.ast.Annotation annotation) {
+               if (annotation instanceof net.sourceforge.phpdt.internal.compiler.ast.SingleMemberAnnotation) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.SingleMemberAnnotation) annotation);
+               } else if (annotation instanceof net.sourceforge.phpdt.internal.compiler.ast.MarkerAnnotation) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.MarkerAnnotation) annotation);
+               } else {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.NormalAnnotation) annotation);
+               }
+       }
+
+       public ArrayCreation convert(net.sourceforge.phpdt.internal.compiler.ast.ArrayAllocationExpression expression) {
+               ArrayCreation arrayCreation = new ArrayCreation(this.ast);
+               if (this.resolveBindings) {
+                       recordNodes(arrayCreation, expression);
+               }
+               arrayCreation.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               net.sourceforge.phpdt.internal.compiler.ast.Expression[] dimensions = expression.dimensions;
+               
+               int dimensionsLength = dimensions.length;
+               for (int i = 0; i < dimensionsLength; i++) {
+                       if (dimensions[i] != null) {
+                               Expression dimension = convert(dimensions[i]);
+                               if (this.resolveBindings) {
+                                       recordNodes(dimension, dimensions[i]);
+                               }
+                               arrayCreation.dimensions().add(dimension);
+                       }
+               }
+               Type type = convertType(expression.type);
+               if (this.resolveBindings) {
+                       recordNodes(type, expression.type);
+               }               
+               ArrayType arrayType = null;
+               if (type.isArrayType()) {
+                       arrayType = (ArrayType) type;
+               } else {
+                       arrayType = this.ast.newArrayType(type, dimensionsLength);
+                       if (this.resolveBindings) {
+                               completeRecord(arrayType, expression);
+                       }                       
+                       int start = type.getStartPosition();
+                       int end = type.getStartPosition() + type.getLength();
+                       int previousSearchStart = end - 1;
+                       ArrayType componentType = (ArrayType) type.getParent();
+                       for (int i = 0; i < dimensionsLength; i++) {
+                               previousSearchStart = retrieveRightBracketPosition(previousSearchStart + 1, this.compilationUnitSourceLength);
+                               componentType.setSourceRange(start, previousSearchStart - start + 1);
+                               componentType = (ArrayType) componentType.getParent();
+                       }
+               }
+               arrayCreation.setType(arrayType);
+               if (this.resolveBindings) {
+                       recordNodes(arrayType, expression);
+               }       
+               if (expression.initializer != null) {
+                       arrayCreation.setInitializer(convert(expression.initializer));
+               }
+               return arrayCreation;
+       }
+
+       public ArrayInitializer convert(net.sourceforge.phpdt.internal.compiler.ast.ArrayInitializer expression) {
+               ArrayInitializer arrayInitializer = new ArrayInitializer(this.ast);
+               if (this.resolveBindings) {
+                       recordNodes(arrayInitializer, expression);
+               }
+               arrayInitializer.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               net.sourceforge.phpdt.internal.compiler.ast.Expression[] expressions = expression.expressions;
+               if (expressions != null) {
+                       int length = expressions.length;
+                       for (int i = 0; i < length; i++) {
+                               Expression expr = convert(expressions[i]);
+                               if (this.resolveBindings) {
+                                       recordNodes(expr, expressions[i]);
+                               }
+                               arrayInitializer.expressions().add(expr);
+                       }
+               }
+               return arrayInitializer;
+       }
+
+       public ArrayAccess convert(net.sourceforge.phpdt.internal.compiler.ast.ArrayReference reference) {
+               ArrayAccess arrayAccess = new ArrayAccess(this.ast);
+               if (this.resolveBindings) {
+                       recordNodes(arrayAccess, reference);
+               }
+               arrayAccess.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+               arrayAccess.setArray(convert(reference.receiver));
+               arrayAccess.setIndex(convert(reference.position));
+               return arrayAccess;
+       }
+
+       public AssertStatement convert(net.sourceforge.phpdt.internal.compiler.ast.AssertStatement statement) {
+               AssertStatement assertStatement = new AssertStatement(this.ast);
+               final Expression assertExpression = convert(statement.assertExpression);
+               Expression searchingNode = assertExpression;
+               assertStatement.setExpression(assertExpression);
+               net.sourceforge.phpdt.internal.compiler.ast.Expression exceptionArgument = statement.exceptionArgument;
+               if (exceptionArgument != null) {
+                       final Expression exceptionMessage = convert(exceptionArgument);
+                       assertStatement.setMessage(exceptionMessage);
+                       searchingNode = exceptionMessage;
+               }
+               int start = statement.sourceStart;
+               int sourceEnd = retrieveSemiColonPosition(searchingNode);
+               if (sourceEnd == -1) {
+                       sourceEnd = searchingNode.getStartPosition() + searchingNode.getLength() - 1;
+                       assertStatement.setSourceRange(start, sourceEnd - start + 1);
+               } else {
+                       assertStatement.setSourceRange(start, sourceEnd - start + 1);
+               }
+               return assertStatement;
+       }
+       
+       public Assignment convert(net.sourceforge.phpdt.internal.compiler.ast.Assignment expression) {
+               Assignment assignment = new Assignment(this.ast);
+               if (this.resolveBindings) {
+                       recordNodes(assignment, expression);
+               }
+               Expression lhs = convert(expression.lhs);
+               assignment.setLeftHandSide(lhs);
+               assignment.setOperator(Assignment.Operator.ASSIGN);
+               assignment.setRightHandSide(convert(expression.expression));
+               int start = lhs.getStartPosition();
+               assignment.setSourceRange(start, expression.sourceEnd - start + 1);
+               return assignment;
+       }
+
+       /*
+        * Internal use only
+        * Used to convert class body declarations
+        */
+       public TypeDeclaration convert(net.sourceforge.phpdt.internal.compiler.ast.ASTNode[] nodes) {
+               final TypeDeclaration typeDecl = new TypeDeclaration(this.ast);
+               typeDecl.setInterface(false);
+               int nodesLength = nodes.length;
+               for (int i = 0; i < nodesLength; i++) {
+                       net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = nodes[i];
+                       if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.Initializer) {
+                               net.sourceforge.phpdt.internal.compiler.ast.Initializer oldInitializer = (net.sourceforge.phpdt.internal.compiler.ast.Initializer) node;
+                               Initializer initializer = new Initializer(this.ast);
+                               initializer.setBody(convert(oldInitializer.block));
+                               setModifiers(initializer, oldInitializer);
+                               initializer.setSourceRange(oldInitializer.declarationSourceStart, oldInitializer.sourceEnd - oldInitializer.declarationSourceStart + 1);
+//                             setJavaDocComment(initializer);
+//                             initializer.setJavadoc(convert(oldInitializer.javadoc));
+                               convert(oldInitializer.javadoc, initializer);
+                               typeDecl.bodyDeclarations().add(initializer);
+                       } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) {
+                               net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) node;
+                               if (i > 0
+                                       && (nodes[i - 1] instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration)
+                                       && ((net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration)nodes[i - 1]).declarationSourceStart == fieldDeclaration.declarationSourceStart) {
+                                       // we have a multiple field declaration
+                                       // We retrieve the existing fieldDeclaration to add the new VariableDeclarationFragment
+                                       FieldDeclaration currentFieldDeclaration = (FieldDeclaration) typeDecl.bodyDeclarations().get(typeDecl.bodyDeclarations().size() - 1);
+                                       currentFieldDeclaration.fragments().add(convertToVariableDeclarationFragment(fieldDeclaration));
+                               } else {
+                                       // we can create a new FieldDeclaration
+                                       typeDecl.bodyDeclarations().add(convertToFieldDeclaration(fieldDeclaration));
+                               }
+                       } else if(node instanceof net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration) {
+                               AbstractMethodDeclaration nextMethodDeclaration = (AbstractMethodDeclaration) node;
+                               if (!nextMethodDeclaration.isDefaultConstructor() && !nextMethodDeclaration.isClinit()) {
+                                       typeDecl.bodyDeclarations().add(convert(nextMethodDeclaration));
+                               }
+                       } else if(node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
+                               net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
+                               ASTNode nextMemberDeclarationNode = convert(nextMemberDeclaration);
+                               if (nextMemberDeclarationNode == null) {
+                                       typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+                               } else {
+                                       typeDecl.bodyDeclarations().add(nextMemberDeclarationNode);
+                               }
+                       }
+               }
+               return typeDecl;
+       }
+       
+       public Expression convert(net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression expression) {
+               InfixExpression infixExpression = new InfixExpression(this.ast);
+               if (this.resolveBindings) {
+                       this.recordNodes(infixExpression, expression);
+               }
+
+               int expressionOperatorID = (expression.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorSHIFT;
+               switch (expressionOperatorID) {
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
+                               infixExpression.setOperator(InfixExpression.Operator.EQUALS);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.LESS_EQUAL :
+                               infixExpression.setOperator(InfixExpression.Operator.LESS_EQUALS);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.GREATER_EQUAL :
+                               infixExpression.setOperator(InfixExpression.Operator.GREATER_EQUALS);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
+                               infixExpression.setOperator(InfixExpression.Operator.NOT_EQUALS);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
+                               infixExpression.setOperator(InfixExpression.Operator.LEFT_SHIFT);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
+                               infixExpression.setOperator(InfixExpression.Operator.RIGHT_SHIFT_SIGNED);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
+                               infixExpression.setOperator(InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.OR_OR :
+                               infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_OR);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.AND_AND :
+                               infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.PLUS :
+                               infixExpression.setOperator(InfixExpression.Operator.PLUS);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.MINUS :
+                               infixExpression.setOperator(InfixExpression.Operator.MINUS);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.REMAINDER :
+                               infixExpression.setOperator(InfixExpression.Operator.REMAINDER);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.XOR :
+                               infixExpression.setOperator(InfixExpression.Operator.XOR);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.AND :
+                               infixExpression.setOperator(InfixExpression.Operator.AND);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.MULTIPLY :
+                               infixExpression.setOperator(InfixExpression.Operator.TIMES);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.OR :
+                               infixExpression.setOperator(InfixExpression.Operator.OR);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.DIVIDE :
+                               infixExpression.setOperator(InfixExpression.Operator.DIVIDE);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.GREATER :
+                               infixExpression.setOperator(InfixExpression.Operator.GREATER);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.LESS :
+                               infixExpression.setOperator(InfixExpression.Operator.LESS);
+               }
+               
+               if (expression.left instanceof net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression
+                               && ((expression.left.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)) {
+                       // create an extended string literal equivalent => use the extended operands list
+                       infixExpression.extendedOperands().add(convert(expression.right));
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression leftOperand = expression.left;
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression rightOperand = null;
+                       do {
+                               rightOperand = ((net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression) leftOperand).right;
+                               if ((((leftOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID
+                                                       && ((leftOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))
+                                        || ((rightOperand instanceof net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression
+                                                       && ((rightOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID)
+                                                       && ((rightOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))) {
+                                       List extendedOperands = infixExpression.extendedOperands();
+                                       InfixExpression temp = new InfixExpression(this.ast);
+                                       if (this.resolveBindings) {
+                                               this.recordNodes(temp, expression);
+                                       }
+                                       temp.setOperator(getOperatorFor(expressionOperatorID));
+                                       Expression leftSide = convert(leftOperand);
+                                       temp.setLeftOperand(leftSide);
+                                       temp.setSourceRange(leftSide.getStartPosition(), leftSide.getLength());
+                                       int size = extendedOperands.size();
+                                       for (int i = 0; i < size - 1; i++) {
+                                               Expression expr = temp;
+                                               temp = new InfixExpression(this.ast);
+                                               
+                                               if (this.resolveBindings) {
+                                                       this.recordNodes(temp, expression);
+                                               }                                       
+                                               temp.setLeftOperand(expr);
+                                               temp.setOperator(getOperatorFor(expressionOperatorID));
+                                               temp.setSourceRange(expr.getStartPosition(), expr.getLength());
+                                       }
+                                       infixExpression = temp;
+                                       for (int i = 0; i < size; i++) {
+                                               Expression extendedOperand = (Expression) extendedOperands.remove(size - 1 - i);
+                                               temp.setRightOperand(extendedOperand);
+                                               int startPosition = temp.getLeftOperand().getStartPosition();
+                                               temp.setSourceRange(startPosition, extendedOperand.getStartPosition() + extendedOperand.getLength() - startPosition);
+                                               if (temp.getLeftOperand().getNodeType() == ASTNode.INFIX_EXPRESSION) {
+                                                       temp = (InfixExpression) temp.getLeftOperand();
+                                               }
+                                       }
+                                       int startPosition = infixExpression.getLeftOperand().getStartPosition();
+                                       infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+                                       if (this.resolveBindings) {
+                                               this.recordNodes(infixExpression, expression);
+                                       }
+                                       return infixExpression;
+                               }
+                               infixExpression.extendedOperands().add(0, convert(rightOperand));
+                               leftOperand = ((net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression) leftOperand).left;
+                       } while (leftOperand instanceof net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression && ((leftOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0));
+                       Expression leftExpression = convert(leftOperand);
+                       infixExpression.setLeftOperand(leftExpression);
+                       infixExpression.setRightOperand((Expression)infixExpression.extendedOperands().remove(0));
+                       int startPosition = leftExpression.getStartPosition();
+                       infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+                       return infixExpression;
+               } else if (expression.left instanceof StringLiteralConcatenation
+                               && ((expression.left.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)
+                               && (OperatorIds.PLUS == expressionOperatorID)) {
+                       StringLiteralConcatenation literal = (StringLiteralConcatenation) expression.left;
+                       final net.sourceforge.phpdt.internal.compiler.ast.Expression[] stringLiterals = literal.literals;
+                       infixExpression.setLeftOperand(convert(stringLiterals[0]));
+                       infixExpression.setRightOperand(convert(stringLiterals[1]));
+                       for (int i = 2; i < literal.counter; i++) {
+                               infixExpression.extendedOperands().add(convert(stringLiterals[i]));
+                       }
+                       infixExpression.extendedOperands().add(convert(expression.right));
+                       int startPosition = literal.sourceStart;
+                       infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+                       return infixExpression;
+               }
+               Expression leftExpression = convert(expression.left);
+               infixExpression.setLeftOperand(leftExpression);
+               infixExpression.setRightOperand(convert(expression.right));
+               int startPosition = leftExpression.getStartPosition();
+               infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+               return infixExpression;
+       }
+
+       public Block convert(net.sourceforge.phpdt.internal.compiler.ast.Block statement) {
+               Block block = new Block(this.ast);
+               if (statement.sourceEnd > 0) {
+                       block.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+               }
+               net.sourceforge.phpdt.internal.compiler.ast.Statement[] statements = statement.statements;
+               if (statements != null) {
+                       int statementsLength = statements.length;
+                       for (int i = 0; i < statementsLength; i++) {
+                               if (statements[i] instanceof net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) {
+                                       checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
+                               } else {
+                                       Statement statement2 = convert(statements[i]);
+                                       if (statement2 != null) {
+                                               block.statements().add(statement2);
+                                       }
+                               }                               
+                       }
+               }
+               return block;
+       }
+       
+       public BreakStatement convert(net.sourceforge.phpdt.internal.compiler.ast.BreakStatement statement)  {
+               BreakStatement breakStatement = new BreakStatement(this.ast);
+               breakStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+               if (statement.label != null) {
+                       final SimpleName name = new SimpleName(this.ast);
+                       name.internalSetIdentifier(new String(statement.label));
+                       retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
+                       breakStatement.setLabel(name);
+               }
+               return breakStatement;
+       }
+               
+               
+       public SwitchCase convert(net.sourceforge.phpdt.internal.compiler.ast.CaseStatement statement) {
+               SwitchCase switchCase = new SwitchCase(this.ast);
+               net.sourceforge.phpdt.internal.compiler.ast.Expression constantExpression = statement.constantExpression;
+               if (constantExpression == null) {
+                       switchCase.setExpression(null);
+               } else {
+                       switchCase.setExpression(convert(constantExpression));
+               }
+               switchCase.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+               retrieveColonPosition(switchCase);
+               return switchCase;
+       }
+
+       public CastExpression convert(net.sourceforge.phpdt.internal.compiler.ast.CastExpression expression) {
+               CastExpression castExpression = new CastExpression(this.ast);
+               castExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               net.sourceforge.phpdt.internal.compiler.ast.Expression type = expression.type;
+               trimWhiteSpacesAndComments(type);
+               if (type instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeReference ) {
+                       castExpression.setType(convertType((net.sourceforge.phpdt.internal.compiler.ast.TypeReference)type));
+               } else if (type instanceof net.sourceforge.phpdt.internal.compiler.ast.NameReference) {
+                       castExpression.setType(convertToType((net.sourceforge.phpdt.internal.compiler.ast.NameReference)type));
+               }
+               castExpression.setExpression(convert(expression.expression));
+               if (this.resolveBindings) {
+                       recordNodes(castExpression, expression);
+               }
+               return castExpression;
+       }
+
+       public CharacterLiteral convert(net.sourceforge.phpdt.internal.compiler.ast.CharLiteral expression) {
+               int length = expression.sourceEnd - expression.sourceStart + 1; 
+               int sourceStart = expression.sourceStart;
+               CharacterLiteral literal = new CharacterLiteral(this.ast);
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.internalSetEscapedValue(new String(this.compilationUnitSource, sourceStart, length));
+               literal.setSourceRange(sourceStart, length);
+               removeLeadingAndTrailingCommentsFromLiteral(literal);
+               return literal;
+       }
+       public Expression convert(net.sourceforge.phpdt.internal.compiler.ast.ClassLiteralAccess expression) {
+               TypeLiteral typeLiteral = new TypeLiteral(this.ast);
+               if (this.resolveBindings) {
+                       this.recordNodes(typeLiteral, expression);
+               }
+               typeLiteral.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               typeLiteral.setType(convertType(expression.type));
+               return typeLiteral;
+       }
+       
+       public CompilationUnit convert(net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration unit, char[] source) {
+               if(unit.compilationResult.recoveryScannerData != null) {
+                       RecoveryScanner recoveryScanner = new RecoveryScanner(this.scanner, unit.compilationResult.recoveryScannerData.removeUnused());
+                       this.scanner = recoveryScanner;
+                       this.docParser.scanner = this.scanner;
+               }
+               this.compilationUnitSource = source;
+               this.compilationUnitSourceLength = source.length;
+               this.scanner.setSource(source, unit.compilationResult);
+               CompilationUnit compilationUnit = new CompilationUnit(this.ast);
+
+               // Parse comments
+               int[][] comments = unit.comments;
+               if (comments != null) {
+                       buildCommentsTable(compilationUnit, comments);
+               }
+
+               // handle the package declaration immediately
+               // There is no node corresponding to the package declaration
+               if (this.resolveBindings) {
+                       recordNodes(compilationUnit, unit);
+               }
+               if (unit.currentPackage != null) {
+                       PackageDeclaration packageDeclaration = convertPackage(unit);
+                       compilationUnit.setPackage(packageDeclaration);
+               }
+               net.sourceforge.phpdt.internal.compiler.ast.ImportReference[] imports = unit.imports;
+               if (imports != null) {
+                       int importLength = imports.length;
+                       for (int i = 0; i < importLength; i++) {
+                               compilationUnit.imports().add(convertImport(imports[i]));
+                       }
+               }
+
+               net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration[] types = unit.types;
+               if (types != null) {
+                       int typesLength = types.length;
+                       for (int i = 0; i < typesLength; i++) {
+                               net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration declaration = types[i];
+                               if (CharOperation.equals(declaration.name, TypeConstants.PACKAGE_INFO_NAME)) {
+                                       continue;
+                               }
+                               ASTNode type = convert(declaration);
+                               if (type == null) {
+                                       compilationUnit.setFlags(compilationUnit.getFlags() | ASTNode.MALFORMED);
+                               } else {
+                                       compilationUnit.types().add(type);
+                               }
+                       }
+               }
+               compilationUnit.setSourceRange(unit.sourceStart, unit.sourceEnd - unit.sourceStart  + 1);
+               
+               int problemLength = unit.compilationResult.problemCount;
+               if (problemLength != 0) {
+                       CategorizedProblem[] resizedProblems = null;
+                       final CategorizedProblem[] problems = unit.compilationResult.getProblems();
+                       final int realProblemLength=problems.length;
+                       if (realProblemLength == problemLength) {
+                               resizedProblems = problems;
+                       } else {
+                               System.arraycopy(problems, 0, (resizedProblems = new CategorizedProblem[realProblemLength]), 0, realProblemLength);
+                       }
+                       ASTSyntaxErrorPropagator syntaxErrorPropagator = new ASTSyntaxErrorPropagator(resizedProblems);
+                       compilationUnit.accept(syntaxErrorPropagator);
+                       ASTRecoveryPropagator recoveryPropagator =
+                               new ASTRecoveryPropagator(resizedProblems, unit.compilationResult.recoveryScannerData);
+                       compilationUnit.accept(recoveryPropagator);
+                       compilationUnit.setProblems(resizedProblems);
+               }
+               if (this.resolveBindings) {
+                       lookupForScopes();
+               }
+               compilationUnit.initCommentMapper(this.scanner);
+               return compilationUnit;
+       }
+
+       public Assignment convert(net.sourceforge.phpdt.internal.compiler.ast.CompoundAssignment expression) {
+               Assignment assignment = new Assignment(this.ast);
+               Expression lhs = convert(expression.lhs);
+               assignment.setLeftHandSide(lhs);
+               int start = lhs.getStartPosition();
+               assignment.setSourceRange(start, expression.sourceEnd - start + 1);
+               switch (expression.operator) {
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.PLUS :
+                               assignment.setOperator(Assignment.Operator.PLUS_ASSIGN);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.MINUS :
+                               assignment.setOperator(Assignment.Operator.MINUS_ASSIGN);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.MULTIPLY :
+                               assignment.setOperator(Assignment.Operator.TIMES_ASSIGN);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.DIVIDE :
+                               assignment.setOperator(Assignment.Operator.DIVIDE_ASSIGN);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.AND :
+                               assignment.setOperator(Assignment.Operator.BIT_AND_ASSIGN);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.OR :
+                               assignment.setOperator(Assignment.Operator.BIT_OR_ASSIGN);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.XOR :
+                               assignment.setOperator(Assignment.Operator.BIT_XOR_ASSIGN);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.REMAINDER :
+                               assignment.setOperator(Assignment.Operator.REMAINDER_ASSIGN);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
+                               assignment.setOperator(Assignment.Operator.LEFT_SHIFT_ASSIGN);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
+                               assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
+                               assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN);
+                               break;
+               }
+               assignment.setRightHandSide(convert(expression.expression));
+               if (this.resolveBindings) {
+                       recordNodes(assignment, expression);
+               }
+               return assignment;
+       }
+
+       public ConditionalExpression convert(net.sourceforge.phpdt.internal.compiler.ast.ConditionalExpression expression) {
+               ConditionalExpression conditionalExpression = new ConditionalExpression(this.ast);
+               if (this.resolveBindings) {
+                       recordNodes(conditionalExpression, expression);
+               }
+               conditionalExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               conditionalExpression.setExpression(convert(expression.condition));
+               conditionalExpression.setThenExpression(convert(expression.valueIfTrue));
+               conditionalExpression.setElseExpression(convert(expression.valueIfFalse));
+               return conditionalExpression;
+       }
+
+       public ContinueStatement convert(net.sourceforge.phpdt.internal.compiler.ast.ContinueStatement statement)  {
+               ContinueStatement continueStatement = new ContinueStatement(this.ast);
+               continueStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+               if (statement.label != null) {
+                       final SimpleName name = new SimpleName(this.ast);
+                       name.internalSetIdentifier(new String(statement.label));
+                       retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
+                       continueStatement.setLabel(name);
+               }
+               return continueStatement;
+       }
+       
+       public DoStatement convert(net.sourceforge.phpdt.internal.compiler.ast.DoStatement statement) {
+               DoStatement doStatement = new DoStatement(this.ast);
+               doStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+               doStatement.setExpression(convert(statement.condition));
+               final Statement action = convert(statement.action);
+               if (action == null) return null;
+               doStatement.setBody(action);
+               return doStatement;
+       }
+
+       public NumberLiteral convert(net.sourceforge.phpdt.internal.compiler.ast.DoubleLiteral expression) {
+               int length = expression.sourceEnd - expression.sourceStart + 1; 
+               int sourceStart = expression.sourceStart;
+               NumberLiteral literal = new NumberLiteral(this.ast);
+               literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.setSourceRange(sourceStart, length);
+               removeLeadingAndTrailingCommentsFromLiteral(literal);
+               return literal;
+       }
+       
+       public EmptyStatement convert(net.sourceforge.phpdt.internal.compiler.ast.EmptyStatement statement) {
+               EmptyStatement emptyStatement = new EmptyStatement(this.ast);
+               emptyStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+               return emptyStatement;
+       }
+       
+       // field is an enum constant
+       public EnumConstantDeclaration convert(net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration enumConstant) {
+               checkCanceled();
+               EnumConstantDeclaration enumConstantDeclaration = new EnumConstantDeclaration(this.ast);
+               final SimpleName typeName = new SimpleName(this.ast);
+               typeName.internalSetIdentifier(new String(enumConstant.name));
+               typeName.setSourceRange(enumConstant.sourceStart, enumConstant.sourceEnd - enumConstant.sourceStart + 1);
+               enumConstantDeclaration.setName(typeName);
+               int declarationSourceStart = enumConstant.declarationSourceStart;
+               int declarationSourceEnd = enumConstant.declarationSourceEnd;
+               final net.sourceforge.phpdt.internal.compiler.ast.Expression initialization = enumConstant.initialization;
+               if (initialization != null) {
+                       if (initialization instanceof QualifiedAllocationExpression) {
+                               net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration anonymousType = ((QualifiedAllocationExpression) initialization).anonymousType;
+                               if (anonymousType != null) {
+                                       AnonymousClassDeclaration anonymousClassDeclaration = new AnonymousClassDeclaration(this.ast);
+                                       int start = retrieveStartBlockPosition(anonymousType.sourceEnd, anonymousType.bodyEnd);
+                                       int end = retrieveRightBrace(anonymousType.bodyEnd, declarationSourceEnd);
+                                       if (end == -1) end = anonymousType.bodyEnd;
+                                       anonymousClassDeclaration.setSourceRange(start, end - start + 1);
+                                       enumConstantDeclaration.setAnonymousClassDeclaration(anonymousClassDeclaration);
+                                       buildBodyDeclarations(anonymousType, anonymousClassDeclaration);
+                                       if (this.resolveBindings) {
+                                               recordNodes(anonymousClassDeclaration, anonymousType);
+                                               anonymousClassDeclaration.resolveBinding();
+                                       }
+                                       enumConstantDeclaration.setSourceRange(declarationSourceStart, end - declarationSourceStart + 1);
+                               }
+                       } else {
+                               enumConstantDeclaration.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+                       }
+                       final net.sourceforge.phpdt.internal.compiler.ast.Expression[] arguments = ((net.sourceforge.phpdt.internal.compiler.ast.AllocationExpression) initialization).arguments;
+                       if (arguments != null) {
+                               for (int i = 0, max = arguments.length; i < max; i++) {
+                                       enumConstantDeclaration.arguments().add(convert(arguments[i]));
+                               }
+                       }
+               } else {
+                       enumConstantDeclaration.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
+               }
+               setModifiers(enumConstantDeclaration, enumConstant);
+               if (this.resolveBindings) {
+                       recordNodes(enumConstantDeclaration, enumConstant);
+                       recordNodes(typeName, enumConstant);
+                       enumConstantDeclaration.resolveVariable();
+               }
+               convert(enumConstant.javadoc, enumConstantDeclaration);
+               return enumConstantDeclaration;
+       }
+
+       public Expression convert(net.sourceforge.phpdt.internal.compiler.ast.EqualExpression expression) {
+               InfixExpression infixExpression = new InfixExpression(this.ast);
+               if (this.resolveBindings) {
+                       recordNodes(infixExpression, expression);
+               }
+               Expression leftExpression = convert(expression.left);
+               infixExpression.setLeftOperand(leftExpression);
+               infixExpression.setRightOperand(convert(expression.right));
+               int startPosition = leftExpression.getStartPosition();
+               infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+               switch ((expression.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
+                               infixExpression.setOperator(InfixExpression.Operator.EQUALS);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
+                               infixExpression.setOperator(InfixExpression.Operator.NOT_EQUALS);
+               }
+               return infixExpression;
+       
+       }
+       
+       public Statement convert(net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall statement) {
+               Statement newStatement;
+               int sourceStart = statement.sourceStart;
+               if (statement.isSuperAccess() || statement.isSuper()) {
+                       SuperConstructorInvocation superConstructorInvocation = new SuperConstructorInvocation(this.ast);
+                       if (statement.qualification != null) {
+                               superConstructorInvocation.setExpression(convert(statement.qualification));
+                       }
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression[] arguments = statement.arguments;
+                       if (arguments != null) {
+                               int length = arguments.length;
+                               for (int i = 0; i < length; i++) {
+                                       superConstructorInvocation.arguments().add(convert(arguments[i]));
+                               }
+                       }
+                       if (statement.typeArguments != null) {
+                               if (sourceStart > statement.typeArgumentsSourceStart) {
+                                       sourceStart = statement.typeArgumentsSourceStart;
+                               }
+                               switch(this.ast.apiLevel) {
+                                       case AST.JLS2_INTERNAL :
+                                               superConstructorInvocation.setFlags(superConstructorInvocation.getFlags() | ASTNode.MALFORMED);
+                                               break;
+                                       case AST.JLS3 :
+                                               for (int i = 0, max = statement.typeArguments.length; i < max; i++) {
+                                                       superConstructorInvocation.typeArguments().add(convertType(statement.typeArguments[i]));
+                                               }
+                                               break;
+                               }
+                       }
+                       newStatement = superConstructorInvocation;
+               } else {
+                       ConstructorInvocation constructorInvocation = new ConstructorInvocation(this.ast);
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression[] arguments = statement.arguments;
+                       if (arguments != null) {
+                               int length = arguments.length;
+                               for (int i = 0; i < length; i++) {
+                                       constructorInvocation.arguments().add(convert(arguments[i]));
+                               }
+                       }
+                       if (statement.typeArguments != null) {
+                               if (sourceStart > statement.typeArgumentsSourceStart) {
+                                       sourceStart = statement.typeArgumentsSourceStart;
+                               }
+                               switch(this.ast.apiLevel) {
+                                       case AST.JLS2_INTERNAL :
+                                               constructorInvocation.setFlags(constructorInvocation.getFlags() | ASTNode.MALFORMED);
+                                               break;
+                                       case AST.JLS3 :
+                                               for (int i = 0, max = statement.typeArguments.length; i < max; i++) {
+                                                       constructorInvocation.typeArguments().add(convertType(statement.typeArguments[i]));
+                                               }
+                                       break;
+                               }
+                       }
+                       if (statement.qualification != null) {
+                               // this is an error
+                               constructorInvocation.setFlags(constructorInvocation.getFlags() | ASTNode.MALFORMED);
+                       }
+                       newStatement = constructorInvocation;
+               }
+               newStatement.setSourceRange(sourceStart, statement.sourceEnd - sourceStart + 1);
+               if (this.resolveBindings) {
+                       recordNodes(newStatement, statement);
+               }
+               return newStatement;
+       }
+
+       public Expression convert(net.sourceforge.phpdt.internal.compiler.ast.Expression expression) {
+               if ((expression.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) {
+                       return convertToParenthesizedExpression(expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.Annotation) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.Annotation) expression);
+               }               
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.CastExpression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.CastExpression) expression);
+               }
+               // switch between all types of expression
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.ArrayAllocationExpression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ArrayAllocationExpression) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.QualifiedAllocationExpression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.QualifiedAllocationExpression) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.AllocationExpression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.AllocationExpression) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.ArrayInitializer) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ArrayInitializer) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.PrefixExpression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.PrefixExpression) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.PostfixExpression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.PostfixExpression) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.CompoundAssignment) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.CompoundAssignment) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.Assignment) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.Assignment) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.ClassLiteralAccess) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ClassLiteralAccess) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.FalseLiteral) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.FalseLiteral) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.TrueLiteral) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.TrueLiteral) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.NullLiteral) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.NullLiteral) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.CharLiteral) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.CharLiteral) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.DoubleLiteral) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.DoubleLiteral) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.FloatLiteral) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.FloatLiteral) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.IntLiteralMinValue) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.IntLiteralMinValue) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.IntLiteral) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.IntLiteral) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.LongLiteralMinValue) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.LongLiteralMinValue) expression);
+               }                               
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.LongLiteral) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.LongLiteral) expression);
+               }
+               if (expression instanceof StringLiteralConcatenation) {
+                       return convert((StringLiteralConcatenation) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.ExtendedStringLiteral) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ExtendedStringLiteral) expression);
+               }       
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.StringLiteral) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.StringLiteral) expression);
+               }                               
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.AND_AND_Expression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.AND_AND_Expression) expression);
+               }                               
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.OR_OR_Expression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.OR_OR_Expression) expression);
+               }                               
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.EqualExpression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.EqualExpression) expression);
+               }                               
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression) expression);
+               }                               
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.InstanceOfExpression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.InstanceOfExpression) expression);
+               }                               
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.UnaryExpression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.UnaryExpression) expression);
+               }                               
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.ConditionalExpression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ConditionalExpression) expression);
+               }                               
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.MessageSend) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.MessageSend) expression);
+               }                               
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.Reference) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.Reference) expression);
+               }
+               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeReference) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.TypeReference) expression);
+               }
+               return null;
+       }
+
+       public StringLiteral convert(net.sourceforge.phpdt.internal.compiler.ast.ExtendedStringLiteral expression) {
+               expression.computeConstant();
+               StringLiteral literal = new StringLiteral(this.ast);
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.setLiteralValue(expression.constant.stringValue());
+               literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               return literal;
+       }
+
+       public BooleanLiteral convert(net.sourceforge.phpdt.internal.compiler.ast.FalseLiteral expression) {
+               final BooleanLiteral literal =  new BooleanLiteral(this.ast);
+               literal.setBooleanValue(false);
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               return literal; 
+       }
+       
+       public Expression convert(net.sourceforge.phpdt.internal.compiler.ast.FieldReference reference) {
+               if (reference.receiver.isSuper()) {
+                       final SuperFieldAccess superFieldAccess = new SuperFieldAccess(this.ast);
+                       if (this.resolveBindings) {
+                               recordNodes(superFieldAccess, reference);
+                       }
+                       if (reference.receiver instanceof net.sourceforge.phpdt.internal.compiler.ast.QualifiedSuperReference) {
+                               Name qualifier = convert((net.sourceforge.phpdt.internal.compiler.ast.QualifiedSuperReference) reference.receiver);
+                               superFieldAccess.setQualifier(qualifier);
+                               if (this.resolveBindings) {
+                                       recordNodes(qualifier, reference.receiver);
+                               }
+                       }
+                       final SimpleName simpleName = new SimpleName(this.ast);
+                       simpleName.internalSetIdentifier(new String(reference.token));
+                       int sourceStart = (int)(reference.nameSourcePosition>>>32);
+                       int length = (int)(reference.nameSourcePosition & 0xFFFFFFFF) - sourceStart + 1;
+                       simpleName.setSourceRange(sourceStart, length);
+                       superFieldAccess.setName(simpleName);
+                       if (this.resolveBindings) {
+                               recordNodes(simpleName, reference);
+                       }
+                       superFieldAccess.setSourceRange(reference.receiver.sourceStart, reference.sourceEnd - reference.receiver.sourceStart + 1);
+                       return superFieldAccess;
+               } else {
+                       final FieldAccess fieldAccess = new FieldAccess(this.ast);
+                       if (this.resolveBindings) {
+                               recordNodes(fieldAccess, reference);
+                       }
+                       Expression receiver = convert(reference.receiver);
+                       fieldAccess.setExpression(receiver);
+                       final SimpleName simpleName = new SimpleName(this.ast);
+                       simpleName.internalSetIdentifier(new String(reference.token));
+                       int sourceStart = (int)(reference.nameSourcePosition>>>32);
+                       int length = (int)(reference.nameSourcePosition & 0xFFFFFFFF) - sourceStart + 1;
+                       simpleName.setSourceRange(sourceStart, length);
+                       fieldAccess.setName(simpleName);
+                       if (this.resolveBindings) {
+                               recordNodes(simpleName, reference);
+                       }
+                       fieldAccess.setSourceRange(receiver.getStartPosition(), reference.sourceEnd - receiver.getStartPosition() + 1);
+                       return fieldAccess;
+               }
+       }
+
+       public NumberLiteral convert(net.sourceforge.phpdt.internal.compiler.ast.FloatLiteral expression) {
+               int length = expression.sourceEnd - expression.sourceStart + 1; 
+               int sourceStart = expression.sourceStart;
+               NumberLiteral literal = new NumberLiteral(this.ast);
+               literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.setSourceRange(sourceStart, length);
+               removeLeadingAndTrailingCommentsFromLiteral(literal);
+               return literal;
+       }
+       
+       public Statement convert(ForeachStatement statement) {
+               switch(this.ast.apiLevel) {
+                       case AST.JLS2_INTERNAL :
+                               return createFakeEmptyStatement(statement);
+                       case AST.JLS3 :
+                               EnhancedForStatement enhancedForStatement = new EnhancedForStatement(this.ast);
+                               enhancedForStatement.setParameter(convertToSingleVariableDeclaration(statement.elementVariable));
+                               net.sourceforge.phpdt.internal.compiler.ast.Expression collection = statement.collection;
+                               if (collection == null) return null;
+                               enhancedForStatement.setExpression(convert(collection));
+                               final Statement action = convert(statement.action);
+                               if (action == null) return null;
+                               enhancedForStatement.setBody(action);
+                               int start = statement.sourceStart;
+                               int end = statement.sourceEnd;
+                               enhancedForStatement.setSourceRange(start, end - start + 1);
+                               return enhancedForStatement;
+                       default:
+                               return createFakeEmptyStatement(statement);
+               }
+       }
+       
+       public ForStatement convert(net.sourceforge.phpdt.internal.compiler.ast.ForStatement statement) {
+               ForStatement forStatement = new ForStatement(this.ast);
+               forStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+               net.sourceforge.phpdt.internal.compiler.ast.Statement[] initializations = statement.initializations;
+               if (initializations != null) {
+                       // we know that we have at least one initialization
+                       if (initializations[0] instanceof net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) {
+                               net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration initialization = (net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) initializations[0];
+                               VariableDeclarationExpression variableDeclarationExpression = convertToVariableDeclarationExpression(initialization);
+                               int initializationsLength = initializations.length;
+                               for (int i = 1; i < initializationsLength; i++) {
+                                       initialization = (net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration)initializations[i];
+                                       variableDeclarationExpression.fragments().add(convertToVariableDeclarationFragment(initialization));
+                               }
+                               if (initializationsLength != 1) {
+                                       int start = variableDeclarationExpression.getStartPosition();
+                                       int end = ((net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) initializations[initializationsLength - 1]).declarationSourceEnd;
+                                       variableDeclarationExpression.setSourceRange(start, end - start + 1);
+                               }
+                               forStatement.initializers().add(variableDeclarationExpression);
+                       } else {
+                               int initializationsLength = initializations.length;
+                               for (int i = 0; i < initializationsLength; i++) {
+                                       Expression initializer = convertToExpression(initializations[i]);
+                                       if (initializer != null) {
+                                               forStatement.initializers().add(initializer);
+                                       } else {
+                                               forStatement.setFlags(forStatement.getFlags() | ASTNode.MALFORMED);
+                                       }
+                               }
+                       }
+               }
+               if (statement.condition != null) {
+                       forStatement.setExpression(convert(statement.condition));
+               }
+               net.sourceforge.phpdt.internal.compiler.ast.Statement[] increments = statement.increments;
+               if (increments != null) {
+                       int incrementsLength = increments.length;
+                       for (int i = 0; i < incrementsLength; i++) {
+                               forStatement.updaters().add(convertToExpression(increments[i]));                                
+                       }
+               }
+               final Statement action = convert(statement.action);
+               if (action == null) return null;
+               forStatement.setBody(action);
+               return forStatement;
+       }
+       
+       public IfStatement convert(net.sourceforge.phpdt.internal.compiler.ast.IfStatement statement) {
+               IfStatement ifStatement = new IfStatement(this.ast);
+               ifStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+               ifStatement.setExpression(convert(statement.condition));
+               final Statement thenStatement = convert(statement.thenStatement);
+               if (thenStatement == null) return null;
+               ifStatement.setThenStatement(thenStatement);
+               net.sourceforge.phpdt.internal.compiler.ast.Statement statement2 = statement.elseStatement;
+               if (statement2 != null) {
+                       final Statement elseStatement = convert(statement2);
+                       if (elseStatement != null) {
+                               ifStatement.setElseStatement(elseStatement);
+                       }
+               }
+               return ifStatement;
+       }
+       
+       public InstanceofExpression convert(net.sourceforge.phpdt.internal.compiler.ast.InstanceOfExpression expression) {
+               InstanceofExpression instanceOfExpression = new InstanceofExpression(this.ast);
+               if (this.resolveBindings) {
+                       recordNodes(instanceOfExpression, expression);
+               }
+               Expression leftExpression = convert(expression.expression);
+               instanceOfExpression.setLeftOperand(leftExpression);
+               final Type convertType = convertType(expression.type);
+               instanceOfExpression.setRightOperand(convertType);
+               int startPosition = leftExpression.getStartPosition();
+               int sourceEnd = convertType.getStartPosition() + convertType.getLength() - 1;
+               instanceOfExpression.setSourceRange(startPosition, sourceEnd - startPosition + 1);
+               return instanceOfExpression;
+       }
+
+       public NumberLiteral convert(net.sourceforge.phpdt.internal.compiler.ast.IntLiteral expression) {
+               int length = expression.sourceEnd - expression.sourceStart + 1; 
+               int sourceStart = expression.sourceStart;
+               final NumberLiteral literal = new NumberLiteral(this.ast);
+               literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.setSourceRange(sourceStart, length);
+               removeLeadingAndTrailingCommentsFromLiteral(literal);
+               return literal;
+       }
+
+       public NumberLiteral convert(net.sourceforge.phpdt.internal.compiler.ast.IntLiteralMinValue expression) {
+               int length = expression.sourceEnd - expression.sourceStart + 1; 
+               int sourceStart = expression.sourceStart;
+               NumberLiteral literal = new NumberLiteral(this.ast);
+               literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.setSourceRange(sourceStart, length);
+               removeLeadingAndTrailingCommentsFromLiteral(literal);
+               return literal;
+       }
+
+       public void convert(net.sourceforge.phpdt.internal.compiler.ast.Javadoc javadoc, BodyDeclaration bodyDeclaration) {
+               if (bodyDeclaration.getJavadoc() == null) {
+                       if (javadoc != null) {
+                               if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
+                                       this.commentMapper = new DefaultCommentMapper(this.commentsTable);
+                               }
+                               Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
+                               if (comment != null && comment.isDocComment() && comment.getParent() == null) {
+                                       Javadoc docComment = (Javadoc) comment;
+                                       if (this.resolveBindings) {
+                                               recordNodes(docComment, javadoc);
+                                               // resolve member and method references binding
+                                               Iterator tags = docComment.tags().listIterator();
+                                               while (tags.hasNext()) {
+                                                       recordNodes(javadoc, (TagElement) tags.next());
+                                               }
+                                       }
+                                       bodyDeclaration.setJavadoc(docComment);
+                               }
+                       }
+               }
+       }
+
+       public void convert(net.sourceforge.phpdt.internal.compiler.ast.Javadoc javadoc, PackageDeclaration packageDeclaration) {
+               if (ast.apiLevel == AST.JLS3 && packageDeclaration.getJavadoc() == null) {
+                       if (javadoc != null) {
+                               if (this.commentMapper == null || !this.commentMapper.hasSameTable(this.commentsTable)) {
+                                       this.commentMapper = new DefaultCommentMapper(this.commentsTable);
+                               }
+                               Comment comment = this.commentMapper.getComment(javadoc.sourceStart);
+                               if (comment != null && comment.isDocComment() && comment.getParent() == null) {
+                                       Javadoc docComment = (Javadoc) comment;
+                                       if (this.resolveBindings) {
+                                               recordNodes(docComment, javadoc);
+                                               // resolve member and method references binding
+                                               Iterator tags = docComment.tags().listIterator();
+                                               while (tags.hasNext()) {
+                                                       recordNodes(javadoc, (TagElement) tags.next());
+                                               }
+                                       }
+                                       packageDeclaration.setJavadoc(docComment);
+                               }
+                       }
+               }
+       }
+       
+       public LabeledStatement convert(net.sourceforge.phpdt.internal.compiler.ast.LabeledStatement statement) {
+               LabeledStatement labeledStatement = new LabeledStatement(this.ast);
+               final int sourceStart = statement.sourceStart;
+               labeledStatement.setSourceRange(sourceStart, statement.sourceEnd - sourceStart + 1);
+               Statement body = convert(statement.statement);
+               if (body == null) return null;
+               labeledStatement.setBody(body);
+               final SimpleName name = new SimpleName(this.ast);
+               name.internalSetIdentifier(new String(statement.label));
+               name.setSourceRange(sourceStart, statement.labelEnd - sourceStart + 1);
+               labeledStatement.setLabel(name);
+               return labeledStatement;
+       }
+
+       public NumberLiteral convert(net.sourceforge.phpdt.internal.compiler.ast.LongLiteral expression) {
+               int length = expression.sourceEnd - expression.sourceStart + 1; 
+               int sourceStart = expression.sourceStart;
+               final NumberLiteral literal = new NumberLiteral(this.ast);
+               literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.setSourceRange(sourceStart, length);
+               removeLeadingAndTrailingCommentsFromLiteral(literal);
+               return literal;
+       }
+
+       public NumberLiteral convert(net.sourceforge.phpdt.internal.compiler.ast.LongLiteralMinValue expression) {
+               int length = expression.sourceEnd - expression.sourceStart + 1; 
+               int sourceStart = expression.sourceStart;
+               final NumberLiteral literal = new NumberLiteral(this.ast);
+               literal.internalSetToken(new String(this.compilationUnitSource, sourceStart, length));
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.setSourceRange(sourceStart, length);
+               removeLeadingAndTrailingCommentsFromLiteral(literal);
+               return literal;
+       }
+
+       public Expression convert(MessageSend expression) {
+               // will return a MethodInvocation or a SuperMethodInvocation or
+               Expression expr;
+               int sourceStart = expression.sourceStart;
+               if (expression.isSuperAccess()) {
+                       // returns a SuperMethodInvocation
+                       final SuperMethodInvocation superMethodInvocation = new SuperMethodInvocation(this.ast);
+                       if (this.resolveBindings) {
+                               recordNodes(superMethodInvocation, expression);
+                       }
+                       final SimpleName name = new SimpleName(this.ast);
+                       name.internalSetIdentifier(new String(expression.selector));
+                       int nameSourceStart =  (int) (expression.nameSourcePosition >>> 32);
+                       int nameSourceLength = ((int) expression.nameSourcePosition) - nameSourceStart + 1;
+                       name.setSourceRange(nameSourceStart, nameSourceLength);
+                       if (this.resolveBindings) {
+                               recordNodes(name, expression);
+                       }
+                       superMethodInvocation.setName(name);
+                       // expression.receiver is either a QualifiedSuperReference or a SuperReference
+                       // so the casting cannot fail
+                       if (expression.receiver instanceof net.sourceforge.phpdt.internal.compiler.ast.QualifiedSuperReference) {
+                               Name qualifier = convert((net.sourceforge.phpdt.internal.compiler.ast.QualifiedSuperReference) expression.receiver);
+                               superMethodInvocation.setQualifier(qualifier);
+                               if (this.resolveBindings) {
+                                       recordNodes(qualifier, expression.receiver);
+                               }
+                               if (qualifier != null) {
+                                       sourceStart = qualifier.getStartPosition();
+                               }                       
+                       }
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
+                       if (arguments != null) {
+                               int argumentsLength = arguments.length;
+                               for (int i = 0; i < argumentsLength; i++) {
+                                       Expression expri = convert(arguments[i]);
+                                       if (this.resolveBindings) {
+                                               recordNodes(expri, arguments[i]);
+                                       }
+                                       superMethodInvocation.arguments().add(expri);
+                               }
+                       }
+                       final TypeReference[] typeArguments = expression.typeArguments;
+                       if (typeArguments != null) {
+                               switch(this.ast.apiLevel) {
+                                       case AST.JLS2_INTERNAL :
+                                               superMethodInvocation.setFlags(superMethodInvocation.getFlags() | ASTNode.MALFORMED);
+                                               break;
+                                       case AST.JLS3 :
+                                               for (int i = 0, max = typeArguments.length; i < max; i++) {
+                                                       superMethodInvocation.typeArguments().add(convertType(typeArguments[i]));
+                                               }
+                                               break;
+                               }
+                       }
+                       expr = superMethodInvocation;
+               } else {
+                       // returns a MethodInvocation
+                       final MethodInvocation methodInvocation = new MethodInvocation(this.ast);
+                       if (this.resolveBindings) {
+                               recordNodes(methodInvocation, expression);
+                       }
+                       final SimpleName name = new SimpleName(this.ast);
+                       name.internalSetIdentifier(new String(expression.selector));
+                       int nameSourceStart =  (int) (expression.nameSourcePosition >>> 32);
+                       int nameSourceLength = ((int) expression.nameSourcePosition) - nameSourceStart + 1;
+                       name.setSourceRange(nameSourceStart, nameSourceLength);
+                       methodInvocation.setName(name);
+                       if (this.resolveBindings) {
+                               recordNodes(name, expression);
+                       }
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
+                       if (arguments != null) {
+                               int argumentsLength = arguments.length;
+                               for (int i = 0; i < argumentsLength; i++) {
+                                       Expression expri = convert(arguments[i]);
+                                       if (this.resolveBindings) {
+                                               recordNodes(expri, arguments[i]);
+                                       }
+                                       methodInvocation.arguments().add(expri);
+                               }
+                       }
+                       Expression qualifier = null;
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression receiver = expression.receiver;
+                       if (receiver instanceof MessageSend) {
+                               if ((receiver.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) {
+                                       qualifier = convertToParenthesizedExpression(receiver);
+                               } else {
+                                       qualifier = convert((MessageSend) receiver);
+                               }
+                       } else {
+                               qualifier = convert(receiver);
+                       }
+                       if (qualifier instanceof Name && this.resolveBindings) {
+                               recordNodes(qualifier, receiver);
+                       }
+                       methodInvocation.setExpression(qualifier);
+                       if (qualifier != null) {
+                               sourceStart = qualifier.getStartPosition();
+                       }
+                       final TypeReference[] typeArguments = expression.typeArguments;
+                       if (typeArguments != null) {
+                               switch(this.ast.apiLevel) {
+                                       case AST.JLS2_INTERNAL :
+                                               methodInvocation.setFlags(methodInvocation.getFlags() | ASTNode.MALFORMED);
+                                               break;
+                                       case AST.JLS3 :
+                                               for (int i = 0, max = typeArguments.length; i < max; i++) {
+                                                       methodInvocation.typeArguments().add(convertType(typeArguments[i]));
+                                               }
+                                               break;
+                               }
+                       }
+                       expr = methodInvocation;
+               }
+               expr.setSourceRange(sourceStart, expression.sourceEnd - sourceStart + 1);       
+               removeTrailingCommentFromExpressionEndingWithAParen(expr);
+               return expr;
+       }
+
+       public MarkerAnnotation convert(net.sourceforge.phpdt.internal.compiler.ast.MarkerAnnotation annotation) {
+               final MarkerAnnotation markerAnnotation = new MarkerAnnotation(this.ast);
+               setTypeNameForAnnotation(annotation, markerAnnotation);
+               int start = annotation.sourceStart;
+               int end = annotation.declarationSourceEnd;
+               markerAnnotation.setSourceRange(start, end - start + 1);
+               if (this.resolveBindings) {
+                       recordNodes(markerAnnotation, annotation);
+                       markerAnnotation.resolveAnnotationBinding();
+               }
+               return markerAnnotation;
+       }
+
+       public MemberValuePair convert(net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair memberValuePair) {
+               final MemberValuePair pair = new MemberValuePair(this.ast);
+               final SimpleName simpleName = new SimpleName(this.ast);
+               simpleName.internalSetIdentifier(new String(memberValuePair.name));
+               int start = memberValuePair.sourceStart;
+               int end = memberValuePair.sourceEnd;
+               simpleName.setSourceRange(start, end - start + 1);
+               pair.setName(simpleName);
+               final Expression value = convert(memberValuePair.value);
+               pair.setValue(value);
+               start = memberValuePair.sourceStart;
+               end = value.getStartPosition() + value.getLength() - 1;
+               pair.setSourceRange(start, end - start + 1);
+               
+               if (memberValuePair.value instanceof SingleNameReference &&
+                               ((SingleNameReference)memberValuePair.value).token == RecoveryScanner.FAKE_IDENTIFIER) {
+                       pair.setFlags(pair.getFlags() | ASTNode.RECOVERED);
+               }
+               
+               if (this.resolveBindings) {
+                       recordNodes(simpleName, memberValuePair);
+                       recordNodes(pair, memberValuePair);
+               }
+               return pair;
+       }
+
+       public Name convert(net.sourceforge.phpdt.internal.compiler.ast.NameReference reference) {
+               if (reference instanceof net.sourceforge.phpdt.internal.compiler.ast.QualifiedNameReference) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.QualifiedNameReference) reference);
+               } else {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.SingleNameReference) reference);
+               }
+       }
+
+       public InfixExpression convert(StringLiteralConcatenation expression) {
+               expression.computeConstant();
+               final InfixExpression infixExpression = new InfixExpression(this.ast);
+               infixExpression.setOperator(InfixExpression.Operator.PLUS);
+               net.sourceforge.phpdt.internal.compiler.ast.Expression[] stringLiterals = expression.literals;
+               infixExpression.setLeftOperand(convert(stringLiterals[0]));
+               infixExpression.setRightOperand(convert(stringLiterals[1]));
+               for (int i = 2; i < expression.counter; i++) {
+                       infixExpression.extendedOperands().add(convert(stringLiterals[i]));
+               }
+               if (this.resolveBindings) {
+                       this.recordNodes(infixExpression, expression);
+               }
+               infixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               return infixExpression;
+       }
+       
+       public NormalAnnotation convert(net.sourceforge.phpdt.internal.compiler.ast.NormalAnnotation annotation) {
+               final NormalAnnotation normalAnnotation = new NormalAnnotation(this.ast);
+               setTypeNameForAnnotation(annotation, normalAnnotation);
+               
+               int start = annotation.sourceStart;
+               int end = annotation.declarationSourceEnd;
+               
+               net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair[] memberValuePairs = annotation.memberValuePairs;
+               if (memberValuePairs != null) {
+                       for (int i = 0, max = memberValuePairs.length; i < max; i++) {
+                               MemberValuePair memberValuePair = convert(memberValuePairs[i]);
+                               int memberValuePairEnd = memberValuePair.getStartPosition() + memberValuePair.getLength() - 1;
+                               if (end == memberValuePairEnd) {
+                                       normalAnnotation.setFlags(normalAnnotation.getFlags() | ASTNode.RECOVERED);
+                               }
+                               normalAnnotation.values().add(memberValuePair);
+                       }
+               }
+               
+               normalAnnotation.setSourceRange(start, end - start + 1);
+               if (this.resolveBindings) {
+                       recordNodes(normalAnnotation, annotation);
+                       normalAnnotation.resolveAnnotationBinding();
+               }
+               return normalAnnotation;
+       }
+
+       public NullLiteral convert(net.sourceforge.phpdt.internal.compiler.ast.NullLiteral expression) {
+               final NullLiteral literal = new NullLiteral(this.ast);
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               return literal;         
+       }
+
+       public Expression convert(net.sourceforge.phpdt.internal.compiler.ast.OR_OR_Expression expression) {
+               InfixExpression infixExpression = new InfixExpression(this.ast);
+               infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_OR);
+               if (this.resolveBindings) {
+                       this.recordNodes(infixExpression, expression);
+               }
+               final int expressionOperatorID = (expression.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorSHIFT;
+               if (expression.left instanceof net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression
+                               && ((expression.left.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)) {
+                       // create an extended string literal equivalent => use the extended operands list
+                       infixExpression.extendedOperands().add(convert(expression.right));
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression leftOperand = expression.left;
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression rightOperand = null;
+                       do {
+                               rightOperand = ((net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression) leftOperand).right;
+                               if ((((leftOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID
+                                                       && ((leftOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))
+                                        || ((rightOperand instanceof net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression
+                                                       && ((rightOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID)
+                                                       && ((rightOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))) {
+                                       List extendedOperands = infixExpression.extendedOperands();
+                                       InfixExpression temp = new InfixExpression(this.ast);
+                                       if (this.resolveBindings) {
+                                               this.recordNodes(temp, expression);
+                                       }
+                                       temp.setOperator(getOperatorFor(expressionOperatorID));
+                                       Expression leftSide = convert(leftOperand);
+                                       temp.setLeftOperand(leftSide);
+                                       temp.setSourceRange(leftSide.getStartPosition(), leftSide.getLength());
+                                       int size = extendedOperands.size();
+                                       for (int i = 0; i < size - 1; i++) {
+                                               Expression expr = temp;
+                                               temp = new InfixExpression(this.ast);
+                                               
+                                               if (this.resolveBindings) {
+                                                       this.recordNodes(temp, expression);
+                                               }                                       
+                                               temp.setLeftOperand(expr);
+                                               temp.setOperator(getOperatorFor(expressionOperatorID));
+                                               temp.setSourceRange(expr.getStartPosition(), expr.getLength());
+                                       }
+                                       infixExpression = temp;
+                                       for (int i = 0; i < size; i++) {
+                                               Expression extendedOperand = (Expression) extendedOperands.remove(size - 1 - i);
+                                               temp.setRightOperand(extendedOperand);
+                                               int startPosition = temp.getLeftOperand().getStartPosition();
+                                               temp.setSourceRange(startPosition, extendedOperand.getStartPosition() + extendedOperand.getLength() - startPosition);
+                                               if (temp.getLeftOperand().getNodeType() == ASTNode.INFIX_EXPRESSION) {
+                                                       temp = (InfixExpression) temp.getLeftOperand();
+                                               }
+                                       }
+                                       int startPosition = infixExpression.getLeftOperand().getStartPosition();
+                                       infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+                                       if (this.resolveBindings) {
+                                               this.recordNodes(infixExpression, expression);
+                                       }
+                                       return infixExpression;
+                               }
+                               infixExpression.extendedOperands().add(0, convert(rightOperand));
+                               leftOperand = ((net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression) leftOperand).left;
+                       } while (leftOperand instanceof net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression && ((leftOperand.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0));
+                       Expression leftExpression = convert(leftOperand);
+                       infixExpression.setLeftOperand(leftExpression);
+                       infixExpression.setRightOperand((Expression)infixExpression.extendedOperands().remove(0));
+                       int startPosition = leftExpression.getStartPosition();
+                       infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+                       return infixExpression;
+               }
+               Expression leftExpression = convert(expression.left);
+               infixExpression.setLeftOperand(leftExpression);
+               infixExpression.setRightOperand(convert(expression.right));
+               infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_OR);
+               int startPosition = leftExpression.getStartPosition();
+               infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
+               return infixExpression;
+       }
+
+       public PostfixExpression convert(net.sourceforge.phpdt.internal.compiler.ast.PostfixExpression expression) {
+               final PostfixExpression postfixExpression = new PostfixExpression(this.ast);
+               if (this.resolveBindings) {
+                       recordNodes(postfixExpression, expression);
+               }
+               postfixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               postfixExpression.setOperand(convert(expression.lhs));
+               switch (expression.operator) {
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.PLUS :
+                               postfixExpression.setOperator(PostfixExpression.Operator.INCREMENT);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.MINUS :
+                               postfixExpression.setOperator(PostfixExpression.Operator.DECREMENT);
+                               break;
+               }
+               return postfixExpression;
+       }
+
+       public PrefixExpression convert(net.sourceforge.phpdt.internal.compiler.ast.PrefixExpression expression) {
+               final PrefixExpression prefixExpression = new PrefixExpression(this.ast);
+               if (this.resolveBindings) {
+                       recordNodes(prefixExpression, expression);
+               }
+               prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               prefixExpression.setOperand(convert(expression.lhs));
+               switch (expression.operator) {
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.PLUS :
+                               prefixExpression.setOperator(PrefixExpression.Operator.INCREMENT);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.MINUS :
+                               prefixExpression.setOperator(PrefixExpression.Operator.DECREMENT);
+                               break;
+               }
+               return prefixExpression;
+       }
+
+       public Expression convert(net.sourceforge.phpdt.internal.compiler.ast.QualifiedAllocationExpression allocation) {
+               final ClassInstanceCreation classInstanceCreation = new ClassInstanceCreation(this.ast);
+               if (allocation.enclosingInstance != null) {
+                       classInstanceCreation.setExpression(convert(allocation.enclosingInstance));
+               }
+               switch(this.ast.apiLevel) {
+                       case AST.JLS2_INTERNAL :
+                               classInstanceCreation.internalSetName(convert(allocation.type));
+                               break;
+                       case AST.JLS3 :
+                               classInstanceCreation.setType(convertType(allocation.type));
+               }
+               net.sourceforge.phpdt.internal.compiler.ast.Expression[] arguments = allocation.arguments;
+               if (arguments != null) {
+                       int length = arguments.length;
+                       for (int i = 0; i < length; i++) {
+                               Expression argument = convert(arguments[i]);
+                               if (this.resolveBindings) {
+                                       recordNodes(argument, arguments[i]);
+                               }
+                               classInstanceCreation.arguments().add(argument);
+                       }
+               }
+               if (allocation.typeArguments != null) {
+                       switch(this.ast.apiLevel) {
+                               case AST.JLS2_INTERNAL :
+                                       classInstanceCreation.setFlags(classInstanceCreation.getFlags() | ASTNode.MALFORMED);
+                                       break;
+                               case AST.JLS3 :
+                                       for (int i = 0, max = allocation.typeArguments.length; i < max; i++) {
+                                               classInstanceCreation.typeArguments().add(convertType(allocation.typeArguments[i]));
+                                       }
+                       }                       
+               }
+               if (allocation.anonymousType != null) {
+                       int declarationSourceStart = allocation.sourceStart;
+                       classInstanceCreation.setSourceRange(declarationSourceStart, allocation.anonymousType.bodyEnd - declarationSourceStart + 1);
+                       final AnonymousClassDeclaration anonymousClassDeclaration = new AnonymousClassDeclaration(this.ast);
+                       int start = retrieveStartBlockPosition(allocation.anonymousType.sourceEnd, allocation.anonymousType.bodyEnd);
+                       anonymousClassDeclaration.setSourceRange(start, allocation.anonymousType.bodyEnd - start + 1);
+                       classInstanceCreation.setAnonymousClassDeclaration(anonymousClassDeclaration);
+                       buildBodyDeclarations(allocation.anonymousType, anonymousClassDeclaration);
+                       if (this.resolveBindings) {
+                               recordNodes(classInstanceCreation, allocation.anonymousType);
+                               recordNodes(anonymousClassDeclaration, allocation.anonymousType);
+                               anonymousClassDeclaration.resolveBinding();
+                       }
+                       return classInstanceCreation;                   
+               } else {
+                       final int start = allocation.sourceStart;
+                       classInstanceCreation.setSourceRange(start, allocation.sourceEnd - start + 1);
+                       if (this.resolveBindings) {
+                               recordNodes(classInstanceCreation, allocation);
+                       }
+                       removeTrailingCommentFromExpressionEndingWithAParen(classInstanceCreation);
+                       return classInstanceCreation;
+               }
+       }
+
+       public Name convert(net.sourceforge.phpdt.internal.compiler.ast.QualifiedNameReference nameReference) {
+               return setQualifiedNameNameAndSourceRanges(nameReference.tokens, nameReference.sourcePositions, nameReference);
+       }
+
+       public Name convert(net.sourceforge.phpdt.internal.compiler.ast.QualifiedSuperReference reference) {
+               return convert(reference.qualification);
+       }
+
+       public ThisExpression convert(net.sourceforge.phpdt.internal.compiler.ast.QualifiedThisReference reference) {
+               final ThisExpression thisExpression = new ThisExpression(this.ast);
+               thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+               thisExpression.setQualifier(convert(reference.qualification));
+               if (this.resolveBindings) {
+                       recordNodes(thisExpression, reference);
+                       recordPendingThisExpressionScopeResolution(thisExpression);
+               }
+               return thisExpression;
+       }
+       
+       public Expression convert(net.sourceforge.phpdt.internal.compiler.ast.Reference reference) {
+               if (reference instanceof net.sourceforge.phpdt.internal.compiler.ast.NameReference) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.NameReference) reference);
+               }
+               if (reference instanceof net.sourceforge.phpdt.internal.compiler.ast.ThisReference) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ThisReference) reference);
+               }
+               if (reference instanceof net.sourceforge.phpdt.internal.compiler.ast.ArrayReference) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ArrayReference) reference);
+               }
+               if (reference instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldReference) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.FieldReference) reference);
+               }
+               return null; // cannot be reached
+       }
+       
+       public ReturnStatement convert(net.sourceforge.phpdt.internal.compiler.ast.ReturnStatement statement) {
+               final ReturnStatement returnStatement = new ReturnStatement(this.ast);
+               returnStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1); 
+               if (statement.expression != null) {
+                       returnStatement.setExpression(convert(statement.expression));
+               }
+               return returnStatement;
+       }
+       
+       public SingleMemberAnnotation convert(net.sourceforge.phpdt.internal.compiler.ast.SingleMemberAnnotation annotation) {
+               final SingleMemberAnnotation singleMemberAnnotation = new SingleMemberAnnotation(this.ast);
+               setTypeNameForAnnotation(annotation, singleMemberAnnotation);
+               singleMemberAnnotation.setValue(convert(annotation.memberValue));
+               int start = annotation.sourceStart;
+               int end = annotation.declarationSourceEnd;
+               singleMemberAnnotation.setSourceRange(start, end - start + 1);
+               if (this.resolveBindings) {
+                       recordNodes(singleMemberAnnotation, annotation);
+                       singleMemberAnnotation.resolveAnnotationBinding();
+               }
+               return singleMemberAnnotation;
+       }
+
+       public SimpleName convert(net.sourceforge.phpdt.internal.compiler.ast.SingleNameReference nameReference) {
+               final SimpleName name = new SimpleName(this.ast);
+               name.internalSetIdentifier(new String(nameReference.token));
+               if (this.resolveBindings) {
+                       recordNodes(name, nameReference);
+               }
+               name.setSourceRange(nameReference.sourceStart, nameReference.sourceEnd - nameReference.sourceStart + 1);
+               return name;
+       }
+
+       public Statement convert(net.sourceforge.phpdt.internal.compiler.ast.Statement statement) {
+               if (statement instanceof ForeachStatement) {
+                       return convert((ForeachStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration localDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration)statement;
+                       return convertToVariableDeclarationStatement(localDeclaration);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.AssertStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.AssertStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.Block) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.Block) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.BreakStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.BreakStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.ContinueStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ContinueStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.CaseStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.CaseStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.DoStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.DoStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.EmptyStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.EmptyStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.ForStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ForStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.IfStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.IfStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.LabeledStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.LabeledStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.ReturnStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ReturnStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.SwitchStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.SwitchStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.SynchronizedStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.SynchronizedStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.ThrowStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.ThrowStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.TryStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.TryStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
+                       ASTNode result = convert((net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) statement);
+                       if (result == null) {
+                               return createFakeEmptyStatement(statement);
+                       }
+                       switch(result.getNodeType()) {
+                               case ASTNode.ENUM_DECLARATION:
+                                       switch(this.ast.apiLevel) {
+                                               case AST.JLS2_INTERNAL :
+                                                       return createFakeEmptyStatement(statement);
+                                               case AST.JLS3 :
+                                                       final TypeDeclarationStatement typeDeclarationStatement = new TypeDeclarationStatement(this.ast);
+                                                       typeDeclarationStatement.setDeclaration((EnumDeclaration) result);
+                                                       AbstractTypeDeclaration typeDecl = typeDeclarationStatement.getDeclaration();
+                                                       typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
+                                                       return typeDeclarationStatement;
+                                       }
+                                       break;
+                               case ASTNode.ANNOTATION_TYPE_DECLARATION :
+                                       switch(this.ast.apiLevel) {
+                                               case AST.JLS2_INTERNAL :
+                                                       return createFakeEmptyStatement(statement);
+                                               case AST.JLS3 :
+                                                       TypeDeclarationStatement typeDeclarationStatement = new TypeDeclarationStatement(this.ast);
+                                                       typeDeclarationStatement.setDeclaration((AnnotationTypeDeclaration) result);
+                                                       AbstractTypeDeclaration typeDecl = typeDeclarationStatement.getDeclaration();
+                                                       typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
+                                                       return typeDeclarationStatement;
+                                       }
+                                       break;
+                               default:
+                                       TypeDeclaration typeDeclaration = (TypeDeclaration) result;
+                                       TypeDeclarationStatement typeDeclarationStatement = new TypeDeclarationStatement(this.ast);
+                                       typeDeclarationStatement.setDeclaration(typeDeclaration);
+                                       switch(this.ast.apiLevel) {
+                                               case AST.JLS2_INTERNAL :
+                                                       TypeDeclaration typeDecl = typeDeclarationStatement.internalGetTypeDeclaration();
+                                                       typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());                                     
+                                                       break;
+                                               case AST.JLS3 :
+                                                       AbstractTypeDeclaration typeDeclAST3 = typeDeclarationStatement.getDeclaration();
+                                                       typeDeclarationStatement.setSourceRange(typeDeclAST3.getStartPosition(), typeDeclAST3.getLength());
+                                                       break;
+                                       }
+                                       return typeDeclarationStatement;
+                       }
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.WhileStatement) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.WhileStatement) statement);
+               }
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.Expression) {
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression statement2 = (net.sourceforge.phpdt.internal.compiler.ast.Expression) statement;
+                       final Expression expr = convert(statement2);
+                       final ExpressionStatement stmt = new ExpressionStatement(this.ast);
+                       stmt.setExpression(expr);
+                       int sourceStart = expr.getStartPosition();
+                       int sourceEnd = statement2.statementEnd;
+                       stmt.setSourceRange(sourceStart, sourceEnd - sourceStart + 1);
+                       return stmt;
+               }
+               return createFakeEmptyStatement(statement);
+       }
+
+       public Expression convert(net.sourceforge.phpdt.internal.compiler.ast.StringLiteral expression) {
+               if (expression instanceof StringLiteralConcatenation) {
+                       return convert((StringLiteralConcatenation) expression);
+               }
+               int length = expression.sourceEnd - expression.sourceStart + 1; 
+               int sourceStart = expression.sourceStart;
+               StringLiteral literal = new StringLiteral(this.ast);
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.internalSetEscapedValue(new String(this.compilationUnitSource, sourceStart, length));
+               literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               return literal;
+       }
+       
+       public SwitchStatement convert(net.sourceforge.phpdt.internal.compiler.ast.SwitchStatement statement) {
+               SwitchStatement switchStatement = new SwitchStatement(this.ast);
+               switchStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1); 
+               switchStatement.setExpression(convert(statement.expression));
+               net.sourceforge.phpdt.internal.compiler.ast.Statement[] statements = statement.statements;
+               if (statements != null) {
+                       int statementsLength = statements.length;
+                       for (int i = 0; i < statementsLength; i++) {
+                               if (statements[i] instanceof net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) {
+                                       checkAndAddMultipleLocalDeclaration(statements, i, switchStatement.statements());
+                               } else {
+                                       final Statement currentStatement = convert(statements[i]);
+                                       if (currentStatement != null) {
+                                               switchStatement.statements().add(currentStatement);
+                                       }
+                               }
+                       }
+               }
+               return switchStatement;
+       }
+       
+       public SynchronizedStatement convert(net.sourceforge.phpdt.internal.compiler.ast.SynchronizedStatement statement) {
+               SynchronizedStatement synchronizedStatement = new SynchronizedStatement(this.ast);
+               synchronizedStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);   
+               synchronizedStatement.setBody(convert(statement.block));
+               synchronizedStatement.setExpression(convert(statement.expression));
+               return synchronizedStatement;
+       }
+       
+       public Expression convert(net.sourceforge.phpdt.internal.compiler.ast.ThisReference reference) {
+               if (reference.isImplicitThis()) {
+                       // There is no source associated with an implicit this
+                       return null;
+               } else if (reference instanceof net.sourceforge.phpdt.internal.compiler.ast.QualifiedSuperReference) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.QualifiedSuperReference) reference);
+               } else if (reference instanceof net.sourceforge.phpdt.internal.compiler.ast.QualifiedThisReference) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.QualifiedThisReference) reference);
+               }  else {
+                       ThisExpression thisExpression = new ThisExpression(this.ast);
+                       thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
+                       if (this.resolveBindings) {
+                               recordNodes(thisExpression, reference);
+                               recordPendingThisExpressionScopeResolution(thisExpression);
+                       }
+                       return thisExpression;
+               }
+       }
+       
+       public ThrowStatement convert(net.sourceforge.phpdt.internal.compiler.ast.ThrowStatement statement) {
+               final ThrowStatement throwStatement = new ThrowStatement(this.ast);
+               throwStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);  
+               throwStatement.setExpression(convert(statement.exception));
+               return throwStatement;
+       }
+               
+       public BooleanLiteral convert(net.sourceforge.phpdt.internal.compiler.ast.TrueLiteral expression) {
+               final BooleanLiteral literal = new BooleanLiteral(this.ast);
+               literal.setBooleanValue(true);
+               if (this.resolveBindings) {
+                       this.recordNodes(literal, expression);
+               }
+               literal.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               return literal;         
+       }
+       
+       public TryStatement convert(net.sourceforge.phpdt.internal.compiler.ast.TryStatement statement) {
+               final TryStatement tryStatement = new TryStatement(this.ast);
+               tryStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);    
+
+               tryStatement.setBody(convert(statement.tryBlock));
+               net.sourceforge.phpdt.internal.compiler.ast.Argument[] catchArguments = statement.catchArguments;
+               if (catchArguments != null) {
+                       int catchArgumentsLength = catchArguments.length;
+                       net.sourceforge.phpdt.internal.compiler.ast.Block[] catchBlocks = statement.catchBlocks;
+                       int start = statement.tryBlock.sourceEnd;
+                       for (int i = 0; i < catchArgumentsLength; i++) {
+                               CatchClause catchClause = new CatchClause(this.ast);
+                               int catchClauseSourceStart = retrieveStartingCatchPosition(start, catchArguments[i].sourceStart);
+                               catchClause.setSourceRange(catchClauseSourceStart, catchBlocks[i].sourceEnd - catchClauseSourceStart + 1);      
+                               catchClause.setBody(convert(catchBlocks[i]));
+                               catchClause.setException(convert(catchArguments[i]));
+                               tryStatement.catchClauses().add(catchClause);
+                               start = catchBlocks[i].sourceEnd;
+                       }
+               }
+               if (statement.finallyBlock != null) {
+                       tryStatement.setFinally(convert(statement.finallyBlock));
+               }
+               return tryStatement;
+       }
+
+       public ASTNode convert(net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+               int kind = net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration.kind(typeDeclaration.modifiers);
+               switch (kind) {
+                       case net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration.ENUM_DECL :
+                               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                                       return null;
+                               } else {
+                                       return convertToEnumDeclaration(typeDeclaration);
+                               }
+                       case net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration.ANNOTATION_TYPE_DECL :
+                               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                                       return null;
+                               } else {
+                                       return convertToAnnotationDeclaration(typeDeclaration);
+                               }
+               }
+
+               checkCanceled();
+               TypeDeclaration typeDecl = new TypeDeclaration(this.ast);
+               if (typeDeclaration.modifiersSourceStart != -1) {
+                       setModifiers(typeDecl, typeDeclaration);
+               }
+               typeDecl.setInterface(kind == net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration.INTERFACE_DECL);
+               final SimpleName typeName = new SimpleName(this.ast);
+               typeName.internalSetIdentifier(new String(typeDeclaration.name));
+               typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
+               typeDecl.setName(typeName);
+               typeDecl.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
+               
+               // need to set the superclass and super interfaces here since we cannot distinguish them at
+               // the type references level.
+               if (typeDeclaration.superclass != null) {
+                       switch(this.ast.apiLevel) {
+                               case AST.JLS2_INTERNAL :
+                                       typeDecl.internalSetSuperclass(convert(typeDeclaration.superclass));
+                                       break;
+                               case AST.JLS3 :
+                                       typeDecl.setSuperclassType(convertType(typeDeclaration.superclass));
+                                       break;
+                       }
+               }
+               
+               net.sourceforge.phpdt.internal.compiler.ast.TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+               if (superInterfaces != null) {
+                       switch(this.ast.apiLevel) {
+                               case AST.JLS2_INTERNAL :
+                                       for (int index = 0, length = superInterfaces.length; index < length; index++) {
+                                               typeDecl.internalSuperInterfaces().add(convert(superInterfaces[index]));
+                                       }
+                                       break;
+                               case AST.JLS3 :
+                                       for (int index = 0, length = superInterfaces.length; index < length; index++) {
+                                               typeDecl.superInterfaceTypes().add(convertType(superInterfaces[index]));
+                                       }
+                       }                                       
+               }
+               net.sourceforge.phpdt.internal.compiler.ast.TypeParameter[] typeParameters = typeDeclaration.typeParameters;
+               if (typeParameters != null) {
+                       switch(this.ast.apiLevel) {
+                               case AST.JLS2_INTERNAL :
+                                       typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+                                       break;
+                               case AST.JLS3 :
+                                       for (int index = 0, length = typeParameters.length; index < length; index++) {
+                                               typeDecl.typeParameters().add(convert(typeParameters[index]));
+                                       }
+                       }
+               }
+               buildBodyDeclarations(typeDeclaration, typeDecl);
+               if (this.resolveBindings) {
+                       recordNodes(typeDecl, typeDeclaration);
+                       recordNodes(typeName, typeDeclaration);
+                       typeDecl.resolveBinding();
+               }
+               return typeDecl;
+       }
+
+       public TypeParameter convert(net.sourceforge.phpdt.internal.compiler.ast.TypeParameter typeParameter) {
+               final TypeParameter typeParameter2 = new TypeParameter(this.ast);
+               final SimpleName simpleName = new SimpleName(this.ast);
+               simpleName.internalSetIdentifier(new String(typeParameter.name));
+               int start = typeParameter.sourceStart;
+               int end = typeParameter.sourceEnd;
+               simpleName.setSourceRange(start, end - start + 1);
+               typeParameter2.setName(simpleName);
+               final TypeReference superType = typeParameter.type;
+               end = typeParameter.declarationSourceEnd;
+               if (superType != null) {
+                       Type type = convertType(superType);
+                       typeParameter2.typeBounds().add(type);
+                       end = type.getStartPosition() + type.getLength() - 1;
+               }
+               TypeReference[] bounds = typeParameter.bounds;
+               if (bounds != null) {
+                       Type type = null;
+                       for (int index = 0, length = bounds.length; index < length; index++) {
+                               type = convertType(bounds[index]);
+                               typeParameter2.typeBounds().add(type);
+                               end = type.getStartPosition() + type.getLength() - 1;
+                       }
+               }
+               start = typeParameter.declarationSourceStart;
+               end = retrieveClosingAngleBracketPosition(end);
+               typeParameter2.setSourceRange(start, end - start + 1);
+               if (this.resolveBindings) {
+                       recordName(simpleName, typeParameter);
+                       recordNodes(typeParameter2, typeParameter);
+                       typeParameter2.resolveBinding();
+               }
+               return typeParameter2;
+       }
+       
+       public Name convert(net.sourceforge.phpdt.internal.compiler.ast.TypeReference typeReference) {
+               char[][] typeName = typeReference.getTypeName();
+               int length = typeName.length;
+               if (length > 1) {
+                       // QualifiedName
+                       net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference qualifiedTypeReference = (net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference) typeReference;
+                       final long[] positions = qualifiedTypeReference.sourcePositions;
+                       return setQualifiedNameNameAndSourceRanges(typeName, positions, typeReference);
+               } else {
+                       final SimpleName name = new SimpleName(this.ast);
+                       name.internalSetIdentifier(new String(typeName[0]));
+                       name.setSourceRange(typeReference.sourceStart, typeReference.sourceEnd - typeReference.sourceStart + 1);
+                       name.index = 1;
+                       if (this.resolveBindings) {
+                               recordNodes(name, typeReference);
+                       }
+                       return name;
+               }
+       }
+                       
+       public PrefixExpression convert(net.sourceforge.phpdt.internal.compiler.ast.UnaryExpression expression) {
+               final PrefixExpression prefixExpression = new PrefixExpression(this.ast);
+               if (this.resolveBindings) {
+                       this.recordNodes(prefixExpression, expression);
+               }
+               prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               prefixExpression.setOperand(convert(expression.expression));
+               switch ((expression.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.PLUS :
+                               prefixExpression.setOperator(PrefixExpression.Operator.PLUS);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.MINUS :
+                               prefixExpression.setOperator(PrefixExpression.Operator.MINUS);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.NOT :
+                               prefixExpression.setOperator(PrefixExpression.Operator.NOT);
+                               break;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.TWIDDLE :
+                               prefixExpression.setOperator(PrefixExpression.Operator.COMPLEMENT);
+               }
+               return prefixExpression;
+       }
+       
+       public WhileStatement convert(net.sourceforge.phpdt.internal.compiler.ast.WhileStatement statement) {
+               final WhileStatement whileStatement = new WhileStatement(this.ast);
+               whileStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
+               whileStatement.setExpression(convert(statement.condition));
+               final Statement action = convert(statement.action);
+               if (action == null) return null;
+               whileStatement.setBody(action);
+               return whileStatement;
+       }
+       
+       public ImportDeclaration convertImport(net.sourceforge.phpdt.internal.compiler.ast.ImportReference importReference) {
+               final ImportDeclaration importDeclaration = new ImportDeclaration(this.ast);
+               final boolean onDemand = (importReference.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OnDemand) != 0;
+               final char[][] tokens = importReference.tokens;
+               int length = importReference.tokens.length;
+               final long[] positions = importReference.sourcePositions;
+               if (length > 1) {
+                       importDeclaration.setName(setQualifiedNameNameAndSourceRanges(tokens, positions, importReference));
+               } else {
+                       final SimpleName name = new SimpleName(this.ast);
+                       name.internalSetIdentifier(new String(tokens[0]));
+                       final int start = (int)(positions[0]>>>32);
+                       final int end = (int)(positions[0] & 0xFFFFFFFF);
+                       name.setSourceRange(start, end - start + 1);
+                       name.index = 1;
+                       importDeclaration.setName(name);
+                       if (this.resolveBindings) {
+                               recordNodes(name, importReference);
+                       }
+               }
+               importDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1);
+               importDeclaration.setOnDemand(onDemand);
+               int modifiers = importReference.modifiers;
+               if (modifiers != ClassFileConstants.AccDefault) {
+                       switch(this.ast.apiLevel) {
+                               case AST.JLS2_INTERNAL :
+                                       importDeclaration.setFlags(importDeclaration.getFlags() | ASTNode.MALFORMED);
+                                       break;
+                               case AST.JLS3 :
+                                       if (modifiers == ClassFileConstants.AccStatic) {
+                                               importDeclaration.setStatic(true);
+                                       } else {
+                                               importDeclaration.setFlags(importDeclaration.getFlags() | ASTNode.MALFORMED);
+                                       }
+                       }
+               }
+               if (this.resolveBindings) {
+                       recordNodes(importDeclaration, importReference);
+               }
+               return importDeclaration;
+       }
+
+       public PackageDeclaration convertPackage(net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration) {
+               net.sourceforge.phpdt.internal.compiler.ast.ImportReference importReference = compilationUnitDeclaration.currentPackage;
+               final PackageDeclaration packageDeclaration = new PackageDeclaration(this.ast);
+               final char[][] tokens = importReference.tokens;
+               final int length = importReference.tokens.length;
+               long[] positions = importReference.sourcePositions;
+               if (length > 1) {
+                       packageDeclaration.setName(setQualifiedNameNameAndSourceRanges(tokens, positions, importReference));
+               } else {
+                       final SimpleName name = new SimpleName(this.ast);
+                       name.internalSetIdentifier(new String(tokens[0]));
+                       int start = (int)(positions[0]>>>32);
+                       int end = (int)(positions[length - 1] & 0xFFFFFFFF);
+                       name.setSourceRange(start, end - start + 1);
+                       name.index = 1;
+                       packageDeclaration.setName(name);
+                       if (this.resolveBindings) {
+                               recordNodes(name, compilationUnitDeclaration);
+                       }
+               }
+               packageDeclaration.setSourceRange(importReference.declarationSourceStart, importReference.declarationEnd - importReference.declarationSourceStart + 1);
+               net.sourceforge.phpdt.internal.compiler.ast.Annotation[] annotations = importReference.annotations;
+               if (annotations != null) {
+                       switch(this.ast.apiLevel) {
+                               case AST.JLS2_INTERNAL :
+                                       packageDeclaration.setFlags(packageDeclaration.getFlags() & ASTNode.MALFORMED);
+                                       break;
+                               case AST.JLS3 :
+                                       for (int i = 0, max = annotations.length; i < max; i++) {
+                                               packageDeclaration.annotations().add(convert(annotations[i]));
+                                       }
+                       }
+               }
+               if (this.resolveBindings) {
+                       recordNodes(packageDeclaration, importReference);
+               }
+               // Set javadoc
+               convert(compilationUnitDeclaration.javadoc, packageDeclaration);
+               return packageDeclaration;
+       }
+       
+       private EnumDeclaration convertToEnumDeclaration(net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+               checkCanceled();
+               final EnumDeclaration enumDeclaration2 = new EnumDeclaration(this.ast);
+               setModifiers(enumDeclaration2, typeDeclaration);
+               final SimpleName typeName = new SimpleName(this.ast);
+               typeName.internalSetIdentifier(new String(typeDeclaration.name));
+               typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
+               enumDeclaration2.setName(typeName);
+               enumDeclaration2.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
+               
+               net.sourceforge.phpdt.internal.compiler.ast.TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+               if (superInterfaces != null) {
+                       for (int index = 0, length = superInterfaces.length; index < length; index++) {
+                               enumDeclaration2.superInterfaceTypes().add(convertType(superInterfaces[index]));
+                       }                                       
+               }
+               buildBodyDeclarations(typeDeclaration, enumDeclaration2);
+               if (this.resolveBindings) {
+                       recordNodes(enumDeclaration2, typeDeclaration);
+                       recordNodes(typeName, typeDeclaration);
+                       enumDeclaration2.resolveBinding();
+               }
+               return enumDeclaration2;
+       }
+       public Expression convertToExpression(net.sourceforge.phpdt.internal.compiler.ast.Statement statement) {
+               if (statement instanceof net.sourceforge.phpdt.internal.compiler.ast.Expression) {
+                       return convert((net.sourceforge.phpdt.internal.compiler.ast.Expression) statement);
+               } else {
+                       return null;
+               }
+       }
+
+       protected FieldDeclaration convertToFieldDeclaration(net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDecl) {
+               VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(fieldDecl);
+               final FieldDeclaration fieldDeclaration = new FieldDeclaration(this.ast);
+               fieldDeclaration.fragments().add(variableDeclarationFragment);
+               if (this.resolveBindings) {
+                       recordNodes(variableDeclarationFragment, fieldDecl);
+                       variableDeclarationFragment.resolveBinding();
+               }
+               fieldDeclaration.setSourceRange(fieldDecl.declarationSourceStart, fieldDecl.declarationEnd - fieldDecl.declarationSourceStart + 1);
+               Type type = convertType(fieldDecl.type);
+               setTypeForField(fieldDeclaration, type, variableDeclarationFragment.getExtraDimensions());
+               setModifiers(fieldDeclaration, fieldDecl);
+               convert(fieldDecl.javadoc, fieldDeclaration);
+               return fieldDeclaration;
+       }
+
+       public ParenthesizedExpression convertToParenthesizedExpression(net.sourceforge.phpdt.internal.compiler.ast.Expression expression) {
+               final ParenthesizedExpression parenthesizedExpression = new ParenthesizedExpression(this.ast);
+               if (this.resolveBindings) {
+                       recordNodes(parenthesizedExpression, expression);
+               }
+               parenthesizedExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
+               adjustSourcePositionsForParent(expression);
+               trimWhiteSpacesAndComments(expression);
+               // decrement the number of parenthesis
+               int numberOfParenthesis = (expression.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) >> net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
+               expression.bits &= ~net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedMASK;
+               expression.bits |= (numberOfParenthesis - 1) << net.sourceforge.phpdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
+               parenthesizedExpression.setExpression(convert(expression));
+               return parenthesizedExpression;
+       }
+               
+       public Type convertToType(net.sourceforge.phpdt.internal.compiler.ast.NameReference reference) {
+               Name name = convert(reference);
+               final SimpleType type = new SimpleType(this.ast);
+               type.setName(name);
+               type.setSourceRange(name.getStartPosition(), name.getLength());
+               if (this.resolveBindings) {
+                       this.recordNodes(type, reference);
+               }
+               return type;
+       }
+       
+       protected VariableDeclarationExpression convertToVariableDeclarationExpression(net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+               final VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
+               final VariableDeclarationExpression variableDeclarationExpression = new VariableDeclarationExpression(this.ast);
+               variableDeclarationExpression.fragments().add(variableDeclarationFragment);
+               if (this.resolveBindings) {
+                       recordNodes(variableDeclarationFragment, localDeclaration);
+               }
+               variableDeclarationExpression.setSourceRange(localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd - localDeclaration.declarationSourceStart + 1);
+               Type type = convertType(localDeclaration.type);
+               setTypeForVariableDeclarationExpression(variableDeclarationExpression, type, variableDeclarationFragment.getExtraDimensions());
+               if (localDeclaration.modifiersSourceStart != -1) {
+                       setModifiers(variableDeclarationExpression, localDeclaration);
+               }
+               return variableDeclarationExpression;
+       }
+
+       protected SingleVariableDeclaration convertToSingleVariableDeclaration(LocalDeclaration localDeclaration) {
+               final SingleVariableDeclaration variableDecl = new SingleVariableDeclaration(this.ast);
+               setModifiers(variableDecl, localDeclaration);
+               final SimpleName name = new SimpleName(this.ast);
+               name.internalSetIdentifier(new String(localDeclaration.name));
+               int start = localDeclaration.sourceStart;
+               int nameEnd = localDeclaration.sourceEnd;
+               name.setSourceRange(start, nameEnd - start + 1);
+               variableDecl.setName(name);
+               final int extraDimensions = retrieveExtraDimension(nameEnd + 1, localDeclaration.type.sourceEnd);
+               variableDecl.setExtraDimensions(extraDimensions);
+               Type type = convertType(localDeclaration.type);
+               int typeEnd = type.getStartPosition() + type.getLength() - 1;
+               int rightEnd = Math.max(typeEnd, localDeclaration.declarationSourceEnd);
+               /*
+                * There is extra work to do to set the proper type positions
+                * See PR http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284
+                */
+               setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions);
+               variableDecl.setSourceRange(localDeclaration.declarationSourceStart, rightEnd - localDeclaration.declarationSourceStart + 1);
+               if (this.resolveBindings) {
+                       recordNodes(name, localDeclaration);
+                       recordNodes(variableDecl, localDeclaration);
+                       variableDecl.resolveBinding();
+               }
+               return variableDecl;
+       }
+       
+       protected VariableDeclarationFragment convertToVariableDeclarationFragment(net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration) {
+               final VariableDeclarationFragment variableDeclarationFragment = new VariableDeclarationFragment(this.ast);
+               final SimpleName name = new SimpleName(this.ast);
+               name.internalSetIdentifier(new String(fieldDeclaration.name));
+               name.setSourceRange(fieldDeclaration.sourceStart, fieldDeclaration.sourceEnd - fieldDeclaration.sourceStart + 1);
+               variableDeclarationFragment.setName(name);
+               int start = fieldDeclaration.sourceEnd;
+               int end = start;
+               int extraDimensions = retrieveExtraDimension(fieldDeclaration.sourceEnd + 1, fieldDeclaration.declarationSourceEnd );
+               variableDeclarationFragment.setExtraDimensions(extraDimensions);
+               if (fieldDeclaration.initialization != null) {
+                       final Expression expression = convert(fieldDeclaration.initialization);
+                       variableDeclarationFragment.setInitializer(expression);
+                       start = expression.getStartPosition() + expression.getLength();
+                       end = start - 1;
+               } else {
+                       // we need to do it even if extendedDimension is null in case of syntax error in an array initializer
+                       // need the exclusive range for retrieveEndOfPotentialExtendedDimensions
+                       int possibleEnd = retrieveEndOfPotentialExtendedDimensions(start + 1, fieldDeclaration.sourceEnd, fieldDeclaration.declarationSourceEnd);
+                       if (possibleEnd == Integer.MIN_VALUE) {
+                               end = fieldDeclaration.declarationSourceEnd;
+                               variableDeclarationFragment.setFlags(variableDeclarationFragment.getFlags() | ASTNode.MALFORMED);
+                       } if (possibleEnd < 0) {
+                               end = -possibleEnd;
+                               variableDeclarationFragment.setFlags(variableDeclarationFragment.getFlags() | ASTNode.MALFORMED);
+                       } else {
+                               end = possibleEnd;
+                       }
+               }
+               variableDeclarationFragment.setSourceRange(fieldDeclaration.sourceStart, end - fieldDeclaration.sourceStart + 1);
+               if (this.resolveBindings) {
+                       recordNodes(name, fieldDeclaration);
+                       recordNodes(variableDeclarationFragment, fieldDeclaration);
+                       variableDeclarationFragment.resolveBinding();
+               }
+               return variableDeclarationFragment;
+       }
+
+       protected VariableDeclarationFragment convertToVariableDeclarationFragment(net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+               final VariableDeclarationFragment variableDeclarationFragment = new VariableDeclarationFragment(this.ast);
+               final SimpleName name = new SimpleName(this.ast);
+               name.internalSetIdentifier(new String(localDeclaration.name));
+               name.setSourceRange(localDeclaration.sourceStart, localDeclaration.sourceEnd - localDeclaration.sourceStart + 1);
+               variableDeclarationFragment.setName(name);
+               int start = localDeclaration.sourceEnd; 
+               net.sourceforge.phpdt.internal.compiler.ast.Expression initialization = localDeclaration.initialization;
+               int extraDimension = retrieveExtraDimension(localDeclaration.sourceEnd + 1, this.compilationUnitSourceLength);
+               variableDeclarationFragment.setExtraDimensions(extraDimension);
+               boolean hasInitialization = initialization != null;
+               int end;
+               if (hasInitialization) {
+                       final Expression expression = convert(initialization);
+                       variableDeclarationFragment.setInitializer(expression);
+                       start = expression.getStartPosition() + expression.getLength();
+                       end = start - 1;
+               } else {
+                       // we need to do it even if extendedDimension is null in case of syntax error in an array initializer
+                       // start + 1 because we need the exclusive range for retrieveEndOfPotentialExtendedDimensions
+                       int possibleEnd = retrieveEndOfPotentialExtendedDimensions(start + 1, localDeclaration.sourceEnd, localDeclaration.declarationSourceEnd);
+                       if (possibleEnd == Integer.MIN_VALUE) {
+                               end = start;
+                               variableDeclarationFragment.setFlags(variableDeclarationFragment.getFlags() | ASTNode.MALFORMED);
+                       } else if (possibleEnd < 0) {
+                               end = -possibleEnd;
+                               variableDeclarationFragment.setFlags(variableDeclarationFragment.getFlags() | ASTNode.MALFORMED);
+                       } else {
+                               end = possibleEnd;
+                       }
+               }
+               variableDeclarationFragment.setSourceRange(localDeclaration.sourceStart, end - localDeclaration.sourceStart + 1);
+               if (this.resolveBindings) {
+                       recordNodes(variableDeclarationFragment, localDeclaration);
+                       recordNodes(name, localDeclaration);
+                       variableDeclarationFragment.resolveBinding();
+               }
+               return variableDeclarationFragment;
+       }
+
+       protected VariableDeclarationStatement convertToVariableDeclarationStatement(net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
+               final VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
+               final VariableDeclarationStatement variableDeclarationStatement = new VariableDeclarationStatement(this.ast);
+               variableDeclarationStatement.fragments().add(variableDeclarationFragment);
+               if (this.resolveBindings) {
+                       recordNodes(variableDeclarationFragment, localDeclaration);
+               }
+               variableDeclarationStatement.setSourceRange(localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd - localDeclaration.declarationSourceStart + 1);
+               Type type = convertType(localDeclaration.type);
+               setTypeForVariableDeclarationStatement(variableDeclarationStatement, type, variableDeclarationFragment.getExtraDimensions());
+               if (localDeclaration.modifiersSourceStart != -1) {
+                       setModifiers(variableDeclarationStatement, localDeclaration);
+               }
+               return variableDeclarationStatement;
+       }
+
+       public Type convertType(TypeReference typeReference) {
+               if (typeReference instanceof Wildcard) {
+                       final Wildcard wildcard = (Wildcard) typeReference;
+                       final WildcardType wildcardType = new WildcardType(this.ast);
+                       if (wildcard.bound != null) {
+                               final Type bound = convertType(wildcard.bound);
+                               wildcardType.setBound(bound, wildcard.kind == Wildcard.EXTENDS);
+                               int start = wildcard.sourceStart;
+                               wildcardType.setSourceRange(start, bound.getStartPosition() + bound.getLength() - start);
+                       } else {
+                               final int start = wildcard.sourceStart;
+                               final int end = wildcard.sourceEnd;
+                               wildcardType.setSourceRange(start, end - start + 1);
+                       }
+                       if (this.resolveBindings) {
+                               recordNodes(wildcardType, typeReference);
+                       }
+                       return wildcardType;
+               }
+               Type type = null;
+               int sourceStart = -1;
+               int length = 0;
+               int dimensions = typeReference.dimensions();
+               if (typeReference instanceof net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference) {
+                       // this is either an ArrayTypeReference or a SingleTypeReference
+                       char[] name = ((net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference) typeReference).getTypeName()[0];
+                       sourceStart = typeReference.sourceStart;
+                       length = typeReference.sourceEnd - typeReference.sourceStart + 1;
+                       // need to find out if this is an array type of primitive types or not
+                       if (isPrimitiveType(name)) {
+                               int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
+                               if (end == -1) {
+                                       end = sourceStart + length - 1;
+                               }                                       
+                               final PrimitiveType primitiveType = new PrimitiveType(this.ast);
+                               primitiveType.setPrimitiveTypeCode(getPrimitiveTypeCode(name));
+                               primitiveType.setSourceRange(sourceStart, end - sourceStart + 1);
+                               type = primitiveType;
+                       } else if (typeReference instanceof ParameterizedSingleTypeReference) {
+                               ParameterizedSingleTypeReference parameterizedSingleTypeReference = (ParameterizedSingleTypeReference) typeReference;
+                               final SimpleName simpleName = new SimpleName(this.ast);
+                               simpleName.internalSetIdentifier(new String(name));
+                               int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
+                               if (end == -1) {
+                                       end = sourceStart + length - 1;
+                               }
+                               simpleName.setSourceRange(sourceStart, end - sourceStart + 1);
+                               switch(this.ast.apiLevel) {
+                                       case AST.JLS2_INTERNAL :
+                                               SimpleType simpleType = new SimpleType(this.ast);
+                                               simpleType.setName(simpleName);
+                                               simpleType.setFlags(simpleType.getFlags() | ASTNode.MALFORMED);
+                                               simpleType.setSourceRange(sourceStart, end - sourceStart + 1);
+                                               type = simpleType;
+                                               if (this.resolveBindings) {
+                                                       this.recordNodes(simpleName, typeReference);
+                                               }
+                                               break;
+                                       case AST.JLS3 :
+                                               simpleType = new SimpleType(this.ast);
+                                               simpleType.setName(simpleName);
+                                               simpleType.setSourceRange(simpleName.getStartPosition(), simpleName.getLength());
+                                               final ParameterizedType parameterizedType = new ParameterizedType(this.ast);
+                                               parameterizedType.setType(simpleType);
+                                               type = parameterizedType;
+                                               TypeReference[] typeArguments = parameterizedSingleTypeReference.typeArguments;
+                                               if (typeArguments != null) {
+                                                       Type type2 = null;
+                                                       for (int i = 0, max = typeArguments.length; i < max; i++) {
+                                                               type2 = convertType(typeArguments[i]);
+                                                               ((ParameterizedType) type).typeArguments().add(type2);
+                                                               end = type2.getStartPosition() + type2.getLength() - 1;
+                                                       }
+                                                       end = retrieveClosingAngleBracketPosition(end + 1);
+                                                       type.setSourceRange(sourceStart, end - sourceStart + 1);
+                                               } else {
+                                                       type.setSourceRange(sourceStart, end - sourceStart + 1);
+                                               }
+                                               if (this.resolveBindings) {
+                                                       this.recordNodes(simpleName, typeReference);
+                                                       this.recordNodes(simpleType, typeReference);
+                                               }
+                               }
+                       } else {
+                               final SimpleName simpleName = new SimpleName(this.ast);
+                               simpleName.internalSetIdentifier(new String(name));
+                               // we need to search for the starting position of the first brace in order to set the proper length
+                               // PR http://dev.eclipse.org/bugs/show_bug.cgi?id=10759
+                               int end = retrieveEndOfElementTypeNamePosition(sourceStart, sourceStart + length);
+                               if (end == -1) {
+                                       end = sourceStart + length - 1;
+                               }
+                               simpleName.setSourceRange(sourceStart, end - sourceStart + 1);
+                               final SimpleType simpleType = new SimpleType(this.ast);
+                               simpleType.setName(simpleName);
+                               type = simpleType;
+                               type.setSourceRange(sourceStart, end - sourceStart + 1);
+                               type = simpleType;
+                               if (this.resolveBindings) {
+                                       this.recordNodes(simpleName, typeReference);
+                               }
+                       }
+                       if (dimensions != 0) {
+                               type = this.ast.newArrayType(type, dimensions);
+                               type.setSourceRange(sourceStart, length);
+                               ArrayType subarrayType = (ArrayType) type;
+                               int index = dimensions - 1;
+                               while (index > 0) {
+                                       subarrayType = (ArrayType) subarrayType.getComponentType();
+                                       int end = retrieveProperRightBracketPosition(index, sourceStart);
+                                       subarrayType.setSourceRange(sourceStart, end - sourceStart + 1);
+                                       index--;
+                               }
+                               if (this.resolveBindings) {
+                                       // store keys for inner types
+                                       completeRecord((ArrayType) type, typeReference);
+                               }
+                       }
+               } else {
+                       if (typeReference instanceof ParameterizedQualifiedTypeReference) {
+                               ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference = (ParameterizedQualifiedTypeReference) typeReference;
+                               char[][] tokens = parameterizedQualifiedTypeReference.tokens;
+                               TypeReference[][] typeArguments = parameterizedQualifiedTypeReference.typeArguments;
+                               long[] positions = parameterizedQualifiedTypeReference.sourcePositions;
+                               sourceStart = (int)(positions[0]>>>32);
+                               switch(this.ast.apiLevel) {
+                                       case AST.JLS2_INTERNAL : {
+                                                       char[][] name = ((net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference) typeReference).getTypeName();
+                                                       int nameLength = name.length;
+                                                       sourceStart = (int)(positions[0]>>>32);
+                                                       length = (int)(positions[nameLength - 1] & 0xFFFFFFFF) - sourceStart + 1;
+                                                       Name qualifiedName = this.setQualifiedNameNameAndSourceRanges(name, positions, typeReference);
+                                                       final SimpleType simpleType = new SimpleType(this.ast);
+                                                       simpleType.setName(qualifiedName);
+                                                       simpleType.setSourceRange(sourceStart, length);
+                                                       type = simpleType;
+                                               }
+                                               break;
+                                       case AST.JLS3 :
+                                               if (typeArguments != null) {
+                                                       int numberOfEnclosingType = 0;
+                            int startingIndex = 0;
+                            int endingIndex = 0;
+                                                       for (int i = 0, max = typeArguments.length; i < max; i++) {
+                                                               if (typeArguments[i] != null) {
+                                                                       numberOfEnclosingType++;
+                                                               } else if (numberOfEnclosingType == 0) {
+                                    endingIndex++;
+                                }
+                                                       }
+                                                       Name name = null;
+                                                       if (endingIndex - startingIndex == 0) {
+                                                               final SimpleName simpleName = new SimpleName(this.ast);
+                                                               simpleName.internalSetIdentifier(new String(tokens[startingIndex]));
+                                                               recordPendingNameScopeResolution(simpleName);
+                                                               int start = (int)(positions[startingIndex]>>>32);
+                                                               int end = (int) positions[startingIndex];
+                                                               simpleName.setSourceRange(start, end - start + 1);
+                                                               simpleName.index = 1;
+                                                               name = simpleName;
+                                                               if (this.resolveBindings) {
+                                                                       recordNodes(simpleName, typeReference);
+                                                               }
+                                                       } else {
+                                                               name = this.setQualifiedNameNameAndSourceRanges(tokens, positions, endingIndex, typeReference);
+                                                       }
+                                                       SimpleType simpleType = new SimpleType(this.ast);
+                                                       simpleType.setName(name);
+                                                       int start = (int)(positions[startingIndex]>>>32);
+                                                       int end = (int) positions[endingIndex];
+                                                       simpleType.setSourceRange(start, end - start + 1);
+                                                       ParameterizedType parameterizedType = new ParameterizedType(this.ast);
+                                                       parameterizedType.setType(simpleType);
+                            if (this.resolveBindings) {
+                                recordNodes(simpleType, typeReference);
+                                recordNodes(parameterizedType, typeReference);
+                            }
+                                                       start = simpleType.getStartPosition();
+                                                       end = start + simpleType.getLength() - 1;
+                                                       for (int i = 0, max = typeArguments[endingIndex].length; i < max; i++) {
+                                                               final Type type2 = convertType(typeArguments[endingIndex][i]);
+                                                               parameterizedType.typeArguments().add(type2);
+                                                               end = type2.getStartPosition() + type2.getLength() - 1;
+                                                       }
+                                                       int indexOfEnclosingType = 1;
+                                                       parameterizedType.index = indexOfEnclosingType;
+                                                       end = retrieveClosingAngleBracketPosition(end + 1);
+                                                       length = end + 1;
+                                                       parameterizedType.setSourceRange(start, end - start + 1);
+                                                       startingIndex = endingIndex + 1;
+                                                       Type currentType = parameterizedType;
+                                                       while(startingIndex < typeArguments.length) {
+                                                               SimpleName simpleName = new SimpleName(this.ast);
+                                                               simpleName.internalSetIdentifier(new String(tokens[startingIndex]));
+                                                               simpleName.index = startingIndex + 1;
+                                                               start = (int)(positions[startingIndex]>>>32);
+                                                               end = (int) positions[startingIndex];
+                                                               simpleName.setSourceRange(start, end - start + 1);
+                                                               recordPendingNameScopeResolution(simpleName);
+                                                               QualifiedType qualifiedType = new QualifiedType(this.ast);
+                                                               qualifiedType.setQualifier(currentType);
+                                                               qualifiedType.setName(simpleName);      
+                                if (this.resolveBindings) {
+                                    recordNodes(simpleName, typeReference);
+                                    recordNodes(qualifiedType, typeReference);
+                                }
+                                                               start = currentType.getStartPosition();
+                                                               end = simpleName.getStartPosition() + simpleName.getLength() - 1;
+                                                               qualifiedType.setSourceRange(start, end - start + 1);
+                                                               indexOfEnclosingType++;
+                                                               if (typeArguments[startingIndex] != null) {
+                                       qualifiedType.index = indexOfEnclosingType;
+                                                                       ParameterizedType parameterizedType2 = new ParameterizedType(this.ast);
+                                                                       parameterizedType2.setType(qualifiedType);
+                                                                       parameterizedType2.index = indexOfEnclosingType;
+                                   if (this.resolveBindings) {
+                                        recordNodes(parameterizedType2, typeReference);
+                                    }
+                                                                       for (int i = 0, max = typeArguments[startingIndex].length; i < max; i++) {
+                                                                               final Type type2 = convertType(typeArguments[startingIndex][i]);
+                                                                               parameterizedType2.typeArguments().add(type2);
+                                                                               end = type2.getStartPosition() + type2.getLength() - 1;
+                                                                       }
+                                                                       end = retrieveClosingAngleBracketPosition(end + 1);
+                                                                       length = end + 1;
+                                                                       parameterizedType2.setSourceRange(start, end - start + 1);                                                      
+                                                                       currentType = parameterizedType2;
+                                                               } else {
+                                                                       currentType = qualifiedType;
+                                               qualifiedType.index = indexOfEnclosingType;
+                                                               }
+                                                               startingIndex++;
+                                                       }
+                                                       if (this.resolveBindings) {
+                                                               this.recordNodes(currentType, typeReference);
+                                                       }
+                                                       type = currentType;
+                                                       length -= sourceStart;
+                                               }
+                               }
+                       } else {
+                               char[][] name = ((net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference) typeReference).getTypeName();
+                               int nameLength = name.length;
+                               long[] positions = ((net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference) typeReference).sourcePositions;
+                               sourceStart = (int)(positions[0]>>>32);
+                               length = (int)(positions[nameLength - 1] & 0xFFFFFFFF) - sourceStart + 1;
+                               final Name qualifiedName = this.setQualifiedNameNameAndSourceRanges(name, positions, typeReference);
+                               final SimpleType simpleType = new SimpleType(this.ast);
+                               simpleType.setName(qualifiedName);
+                               type = simpleType;
+                               type.setSourceRange(sourceStart, length);
+                       }
+
+                       length = typeReference.sourceEnd - sourceStart + 1;
+                       if (dimensions != 0) {
+                               type = this.ast.newArrayType(type, dimensions);
+                               if (this.resolveBindings) {
+                                       completeRecord((ArrayType) type, typeReference);
+                               }
+                               int end = retrieveEndOfDimensionsPosition(sourceStart+length, this.compilationUnitSourceLength);
+                               if (end != -1) {
+                                       type.setSourceRange(sourceStart, end - sourceStart + 1);
+                               } else {
+                                       type.setSourceRange(sourceStart, length);
+                               }
+                               ArrayType subarrayType = (ArrayType) type;
+                               int index = dimensions - 1;
+                               while (index > 0) {
+                                       subarrayType = (ArrayType) subarrayType.getComponentType();
+                                       end = retrieveProperRightBracketPosition(index, sourceStart);
+                                       subarrayType.setSourceRange(sourceStart, end - sourceStart + 1);
+                                       index--;
+                               }
+                       }
+               }
+               if (this.resolveBindings) {
+                       this.recordNodes(type, typeReference);
+               }
+               return type;
+       }
+
+       protected Comment createComment(int[] positions) {
+               // Create comment node
+               Comment comment = null;
+               int start = positions[0];
+               int end = positions[1];
+               if (positions[1]>0) { // Javadoc comments have positive end position
+                       Javadoc docComment = this.docParser.parse(positions);
+                       if (docComment == null) return null;
+                       comment = docComment;
+               } else {
+                       end = -end;
+                       if (positions[0] == 0) { // we cannot know without testing chars again
+                               if (this.docParser.scanner.source[1] == '/') {
+                                       comment = new LineComment(this.ast);
+                               } else {
+                                       comment = new BlockComment(this.ast);
+                               }
+                       }
+                       else if (positions[0]>0) { // Block comment have positive start position
+                               comment = new BlockComment(this.ast);
+                       } else { // Line comment have negative start and end position
+                               start = -start;
+                               comment = new LineComment(this.ast);
+                       }
+                       comment.setSourceRange(start, end - start);
+               }
+               return comment;
+       }
+       
+       protected Statement createFakeEmptyStatement(net.sourceforge.phpdt.internal.compiler.ast.Statement statement) {
+               if (statement == null) return null;
+               EmptyStatement emptyStatement = new EmptyStatement(this.ast);
+               emptyStatement.setFlags(emptyStatement.getFlags() | ASTNode.MALFORMED);
+               int start = statement.sourceStart;
+               int end = statement.sourceEnd;
+               emptyStatement.setSourceRange(start, end - start + 1);
+               return emptyStatement;
+       }
+       /**
+        * @return a new modifier
+        */
+       private Modifier createModifier(ModifierKeyword keyword) {
+               final Modifier modifier = new Modifier(this.ast);
+               modifier.setKeyword(keyword);
+               int start = this.scanner.getCurrentTokenStartPosition();
+               int end = this.scanner.getCurrentTokenEndPosition();
+               modifier.setSourceRange(start, end - start + 1);
+               return modifier;
+       }
+       
+       protected InfixExpression.Operator getOperatorFor(int operatorID) {
+               switch (operatorID) {
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
+                               return InfixExpression.Operator.EQUALS;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.LESS_EQUAL :
+                               return InfixExpression.Operator.LESS_EQUALS;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.GREATER_EQUAL :
+                               return InfixExpression.Operator.GREATER_EQUALS;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
+                               return InfixExpression.Operator.NOT_EQUALS;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
+                               return InfixExpression.Operator.LEFT_SHIFT;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
+                               return InfixExpression.Operator.RIGHT_SHIFT_SIGNED;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
+                               return InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.OR_OR :
+                               return InfixExpression.Operator.CONDITIONAL_OR;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.AND_AND :
+                               return InfixExpression.Operator.CONDITIONAL_AND;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.PLUS :
+                               return InfixExpression.Operator.PLUS;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.MINUS :
+                               return InfixExpression.Operator.MINUS;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.REMAINDER :
+                               return InfixExpression.Operator.REMAINDER;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.XOR :
+                               return InfixExpression.Operator.XOR;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.AND :
+                               return InfixExpression.Operator.AND;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.MULTIPLY :
+                               return InfixExpression.Operator.TIMES;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.OR :
+                               return InfixExpression.Operator.OR;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.DIVIDE :
+                               return InfixExpression.Operator.DIVIDE;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.GREATER :
+                               return InfixExpression.Operator.GREATER;
+                       case net.sourceforge.phpdt.internal.compiler.ast.OperatorIds.LESS :
+                               return InfixExpression.Operator.LESS;
+               }
+               return null;
+       }
+       
+       protected PrimitiveType.Code getPrimitiveTypeCode(char[] name) {
+               switch(name[0]) {
+                       case 'i' :
+                               if (name.length == 3 && name[1] == 'n' && name[2] == 't') {
+                                       return PrimitiveType.INT;
+                               }
+                               break;
+                       case 'l' :
+                               if (name.length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g') {
+                                       return PrimitiveType.LONG;
+                               }
+                               break;
+                       case 'd' :
+                               if (name.length == 6
+                                        && name[1] == 'o'
+                                        && name[2] == 'u'
+                                        && name[3] == 'b'
+                                        && name[4] == 'l'
+                                        && name[5] == 'e') {
+                                       return PrimitiveType.DOUBLE;
+                               }
+                               break;
+                       case 'f' :
+                               if (name.length == 5
+                                        && name[1] == 'l'
+                                        && name[2] == 'o'
+                                        && name[3] == 'a'
+                                        && name[4] == 't') {
+                                       return PrimitiveType.FLOAT;
+                               }
+                               break;
+                       case 'b' :
+                               if (name.length == 4
+                                        && name[1] == 'y'
+                                        && name[2] == 't'
+                                        && name[3] == 'e') {
+                                       return PrimitiveType.BYTE;
+                               } else
+                                       if (name.length == 7
+                                                && name[1] == 'o'
+                                                && name[2] == 'o'
+                                                && name[3] == 'l'
+                                                && name[4] == 'e'
+                                                && name[5] == 'a'
+                                                && name[6] == 'n') {
+                                       return PrimitiveType.BOOLEAN;
+                               }
+                               break;
+                       case 'c' :
+                               if (name.length == 4
+                                        && name[1] == 'h'
+                                        && name[2] == 'a'
+                                        && name[3] == 'r') {
+                                       return PrimitiveType.CHAR;
+                               }
+                               break;
+                       case 's' :
+                               if (name.length == 5
+                                        && name[1] == 'h'
+                                        && name[2] == 'o'
+                                        && name[3] == 'r'
+                                        && name[4] == 't') {
+                                       return PrimitiveType.SHORT;
+                               }
+                               break;
+                       case 'v' :
+                               if (name.length == 4
+                                        && name[1] == 'o'
+                                        && name[2] == 'i'
+                                        && name[3] == 'd') {
+                                       return PrimitiveType.VOID;
+                               }
+               }
+               return null; // cannot be reached
+       }
+       
+       protected boolean isPrimitiveType(char[] name) {
+               switch(name[0]) {
+                       case 'i' :
+                               if (name.length == 3 && name[1] == 'n' && name[2] == 't') {
+                                       return true;
+                               }
+                               return false;
+                       case 'l' :
+                               if (name.length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g') {
+                                       return true;
+                               }
+                               return false;
+                       case 'd' :
+                               if (name.length == 6
+                                        && name[1] == 'o'
+                                        && name[2] == 'u'
+                                        && name[3] == 'b'
+                                        && name[4] == 'l'
+                                        && name[5] == 'e') {
+                                       return true;
+                               }
+                               return false;
+                       case 'f' :
+                               if (name.length == 5
+                                        && name[1] == 'l'
+                                        && name[2] == 'o'
+                                        && name[3] == 'a'
+                                        && name[4] == 't') {
+                                       return true;
+                               }
+                               return false;
+                       case 'b' :
+                               if (name.length == 4
+                                        && name[1] == 'y'
+                                        && name[2] == 't'
+                                        && name[3] == 'e') {
+                                       return true;
+                               } else
+                                       if (name.length == 7
+                                                && name[1] == 'o'
+                                                && name[2] == 'o'
+                                                && name[3] == 'l'
+                                                && name[4] == 'e'
+                                                && name[5] == 'a'
+                                                && name[6] == 'n') {
+                                       return true;
+                               }
+                               return false;
+                       case 'c' :
+                               if (name.length == 4
+                                        && name[1] == 'h'
+                                        && name[2] == 'a'
+                                        && name[3] == 'r') {
+                                       return true;
+                               }
+                               return false;
+                       case 's' :
+                               if (name.length == 5
+                                        && name[1] == 'h'
+                                        && name[2] == 'o'
+                                        && name[3] == 'r'
+                                        && name[4] == 't') {
+                                       return true;
+                               }
+                               return false;
+                       case 'v' :
+                               if (name.length == 4
+                                        && name[1] == 'o'
+                                        && name[2] == 'i'
+                                        && name[3] == 'd') {
+                                       return true;
+                               }
+                               return false;
+               }
+               return false;
+       }
+       
+       private void lookupForScopes() {
+               if (this.pendingNameScopeResolution != null) {
+                       for (Iterator iterator = this.pendingNameScopeResolution.iterator(); iterator.hasNext(); ) {
+                               Name name = (Name) iterator.next();
+                               this.ast.getBindingResolver().recordScope(name, lookupScope(name));
+                       }
+               }
+               if (this.pendingThisExpressionScopeResolution != null) {
+                       for (Iterator iterator = this.pendingThisExpressionScopeResolution.iterator(); iterator.hasNext(); ) {
+                               ThisExpression thisExpression = (ThisExpression) iterator.next();
+                               this.ast.getBindingResolver().recordScope(thisExpression, lookupScope(thisExpression));
+                       }
+               }
+               
+       }
+       
+       private BlockScope lookupScope(ASTNode node) {
+               ASTNode currentNode = node;
+               while(currentNode != null
+                       &&!(currentNode instanceof MethodDeclaration)
+                       && !(currentNode instanceof Initializer)
+                       && !(currentNode instanceof FieldDeclaration)
+                       && !(currentNode instanceof AbstractTypeDeclaration)) {
+                       currentNode = currentNode.getParent();
+               }
+               if (currentNode == null) {
+                       return null;
+               }
+               if (currentNode instanceof Initializer) {
+                       Initializer initializer = (Initializer) currentNode;
+                       while(!(currentNode instanceof AbstractTypeDeclaration)) {
+                               currentNode = currentNode.getParent();
+                       }
+                       if (currentNode instanceof TypeDeclaration
+                               || currentNode instanceof EnumDeclaration
+                               || currentNode instanceof AnnotationTypeDeclaration) {
+                               net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDecl = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+                               if ((initializer.getModifiers() & Modifier.STATIC) != 0) {
+                                       return typeDecl.staticInitializerScope;
+                               } else {
+                                       return typeDecl.initializerScope;
+                               }
+                       }
+               } else if (currentNode instanceof FieldDeclaration) {
+                       FieldDeclaration fieldDeclaration = (FieldDeclaration) currentNode;
+                       while(!(currentNode instanceof AbstractTypeDeclaration)) {
+                               currentNode = currentNode.getParent();
+                       }
+                       if (currentNode instanceof AbstractTypeDeclaration) {
+                               net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDecl = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+                               if ((fieldDeclaration.getModifiers() & Modifier.STATIC) != 0) {
+                                       return typeDecl.staticInitializerScope;
+                               } else {
+                                       return typeDecl.initializerScope;
+                               }
+                       }
+               } else if (currentNode instanceof AbstractTypeDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDecl = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+                       return typeDecl.initializerScope;
+               }
+               AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) this.ast.getBindingResolver().getCorrespondingNode(currentNode);
+               return abstractMethodDeclaration.scope;
+       }
+
+       protected void recordName(Name name, net.sourceforge.phpdt.internal.compiler.ast.ASTNode compilerNode) {
+               if (compilerNode != null) {
+                       recordNodes(name, compilerNode);
+                       if (compilerNode instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeReference) {
+                               net.sourceforge.phpdt.internal.compiler.ast.TypeReference typeRef = (net.sourceforge.phpdt.internal.compiler.ast.TypeReference) compilerNode;
+                               if (name.isQualifiedName()) {
+                                       SimpleName simpleName = null;
+                                       while (name.isQualifiedName()) {
+                                               simpleName = ((QualifiedName) name).getName();
+                                               recordNodes(simpleName, typeRef);
+                                               name = ((QualifiedName) name).getQualifier();
+                                               recordNodes(name, typeRef);
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       protected void recordNodes(ASTNode node, net.sourceforge.phpdt.internal.compiler.ast.ASTNode oldASTNode) {
+               this.ast.getBindingResolver().store(node, oldASTNode);
+       }
+       
+       protected void recordNodes(net.sourceforge.phpdt.internal.compiler.ast.Javadoc javadoc, TagElement tagElement) {
+               Iterator fragments = tagElement.fragments().listIterator();
+               while (fragments.hasNext()) {
+                       ASTNode node = (ASTNode) fragments.next();
+                       if (node.getNodeType() == ASTNode.MEMBER_REF) {
+                               MemberRef memberRef = (MemberRef) node;
+                               Name name = memberRef.getName();
+                               // get compiler node and record nodes
+                               int start = name.getStartPosition();
+                               net.sourceforge.phpdt.internal.compiler.ast.ASTNode compilerNode = javadoc.getNodeStartingAt(start);
+                               if (compilerNode!= null) {
+                                       recordNodes(name, compilerNode);
+                                       recordNodes(node, compilerNode);
+                               }
+                               // Replace qualifier to have all nodes recorded
+                               if (memberRef.getQualifier() != null) {
+                                       net.sourceforge.phpdt.internal.compiler.ast.TypeReference typeRef = null;
+                                       if (compilerNode instanceof JavadocFieldReference) {
+                                               net.sourceforge.phpdt.internal.compiler.ast.Expression expression = ((JavadocFieldReference)compilerNode).receiver;
+                                               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeReference) {
+                                                       typeRef = (net.sourceforge.phpdt.internal.compiler.ast.TypeReference) expression;
+                                               }
+                                       } 
+                                       else if (compilerNode instanceof JavadocMessageSend) {
+                                               net.sourceforge.phpdt.internal.compiler.ast.Expression expression = ((JavadocMessageSend)compilerNode).receiver;
+                                               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeReference) {
+                                                       typeRef = (net.sourceforge.phpdt.internal.compiler.ast.TypeReference) expression;
+                                               }
+                                       }
+                                       if (typeRef != null) {
+                                               recordName(memberRef.getQualifier(), typeRef);
+                                       }
+                               }
+                       } else if (node.getNodeType() == ASTNode.METHOD_REF) {
+                               MethodRef methodRef = (MethodRef) node;
+                               Name name = methodRef.getName();
+                               // get method name start position
+                               int start = methodRef.getStartPosition();
+                               this.scanner.resetTo(start, start + name.getStartPosition()+name.getLength());
+                               int token;
+                               try {
+                                       nextToken: while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF && token != TerminalTokens.TokenNameLPAREN)  {
+                                               if (token == TerminalTokens.TokenNameERROR && this.scanner.currentCharacter == '#') {
+                                                       start = this.scanner.getCurrentTokenEndPosition()+1;
+                                                       break nextToken;
+                                               }
+                                       }
+                               }
+                               catch(InvalidInputException e) {
+                                       // ignore
+                               }
+                               // get compiler node and record nodes
+                               net.sourceforge.phpdt.internal.compiler.ast.ASTNode compilerNode = javadoc.getNodeStartingAt(start);
+                               // record nodes
+                               if (compilerNode != null) {
+                                       recordNodes(methodRef, compilerNode);
+                                       // get type ref
+                                       net.sourceforge.phpdt.internal.compiler.ast.TypeReference typeRef = null;
+                                       if (compilerNode instanceof net.sourceforge.phpdt.internal.compiler.ast.JavadocAllocationExpression) {
+                                               typeRef = ((net.sourceforge.phpdt.internal.compiler.ast.JavadocAllocationExpression)compilerNode).type;
+                                               if (typeRef != null) recordNodes(name, compilerNode);
+                                       } 
+                                       else if (compilerNode instanceof net.sourceforge.phpdt.internal.compiler.ast.JavadocMessageSend) {
+                                               net.sourceforge.phpdt.internal.compiler.ast.Expression expression = ((net.sourceforge.phpdt.internal.compiler.ast.JavadocMessageSend)compilerNode).receiver;
+                                               if (expression instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeReference) {
+                                                       typeRef = (net.sourceforge.phpdt.internal.compiler.ast.TypeReference) expression;
+                                               }
+                                               // TODO (frederic) remove following line to fix bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=62650
+                                               recordNodes(name, compilerNode);
+                                       }
+                                       // record name and qualifier
+                                       if (typeRef != null && methodRef.getQualifier() != null) {
+                                               recordName(methodRef.getQualifier(), typeRef);
+                                       }
+                               }
+                               // Resolve parameters
+                               Iterator parameters = methodRef.parameters().listIterator();
+                               while (parameters.hasNext()) {
+                                       MethodRefParameter param = (MethodRefParameter) parameters.next();
+                                       net.sourceforge.phpdt.internal.compiler.ast.Expression expression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) javadoc.getNodeStartingAt(param.getStartPosition());
+                                       if (expression != null) {
+                                               recordNodes(param, expression);
+                                               if (expression instanceof JavadocArgumentExpression) {
+                                                       JavadocArgumentExpression argExpr = (JavadocArgumentExpression) expression;
+                                                       net.sourceforge.phpdt.internal.compiler.ast.TypeReference typeRef = argExpr.argument.type;
+                                                       if (this.ast.apiLevel >= AST.JLS3) param.setVarargs(argExpr.argument.isVarArgs());
+                                                       recordNodes(param.getType(), typeRef);
+                                                       if (param.getType().isSimpleType()) {
+                                                               recordName(((SimpleType)param.getType()).getName(), typeRef);
+                                                       } else if (param.getType().isArrayType()) {
+                                                               Type type = ((ArrayType) param.getType()).getElementType();
+                                                               recordNodes(type, typeRef);
+                                                               if (type.isSimpleType()) {
+                                                                       recordName(((SimpleType)type).getName(), typeRef);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       } else if (node.getNodeType() == ASTNode.SIMPLE_NAME ||
+                                       node.getNodeType() == ASTNode.QUALIFIED_NAME) {
+                               net.sourceforge.phpdt.internal.compiler.ast.ASTNode compilerNode = javadoc.getNodeStartingAt(node.getStartPosition());
+                               recordName((Name) node, compilerNode);
+                       } else if (node.getNodeType() == ASTNode.TAG_ELEMENT) {
+                               // resolve member and method references binding
+                               recordNodes(javadoc, (TagElement) node);
+                       }
+               }
+       }
+       
+       protected void recordPendingNameScopeResolution(Name name) {
+               if (this.pendingNameScopeResolution == null) {
+                       this.pendingNameScopeResolution = new HashSet();
+               }
+               this.pendingNameScopeResolution.add(name);
+       }
+       
+       protected void recordPendingThisExpressionScopeResolution(ThisExpression thisExpression) {
+               if (this.pendingThisExpressionScopeResolution == null) {
+                       this.pendingThisExpressionScopeResolution = new HashSet();
+               }
+               this.pendingThisExpressionScopeResolution.add(thisExpression);
+       }
+       
+       /**
+        * Remove whitespaces and comments before and after the expression.
+        */     
+       private void trimWhiteSpacesAndComments(net.sourceforge.phpdt.internal.compiler.ast.Expression expression) {
+               int start = expression.sourceStart;
+               int end = expression.sourceEnd;
+               int token;
+               int trimLeftPosition = expression.sourceStart;
+               int trimRightPosition = expression.sourceEnd;
+               boolean first = true;
+               Scanner removeBlankScanner = this.ast.scanner;
+               try {
+                       removeBlankScanner.setSource(this.compilationUnitSource);
+                       removeBlankScanner.resetTo(start, end);
+                       while (true) {
+                               token = removeBlankScanner.getNextToken();
+                               switch (token) {
+                                       case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+                                       case TerminalTokens.TokenNameCOMMENT_LINE :
+                                       case TerminalTokens.TokenNameCOMMENT_BLOCK :
+                                               if (first) {
+                                                       trimLeftPosition = removeBlankScanner.currentPosition;
+                                               }
+                                               break;
+                                       case TerminalTokens.TokenNameWHITESPACE :
+                                               if (first) {
+                                                       trimLeftPosition = removeBlankScanner.currentPosition;
+                                               }
+                                               break;
+                                       case TerminalTokens.TokenNameEOF :
+                                               expression.sourceStart = trimLeftPosition;
+                                               expression.sourceEnd = trimRightPosition;
+                                               return;
+                                       default :
+                                               /*
+                                                * if we find something else than a whitespace or a comment,
+                                                * then we reset the trimRigthPosition to the expression
+                                                * source end.
+                                                */
+                                               trimRightPosition = removeBlankScanner.currentPosition - 1;
+                                               first = false;                          
+                               }
+                       }
+               } catch (InvalidInputException e){
+                       // ignore
+               }
+       }
+
+       /**
+        * Remove potential trailing comment by settings the source end on the closing parenthesis
+        */
+       protected void removeLeadingAndTrailingCommentsFromLiteral(ASTNode node) {
+               int start = node.getStartPosition();
+               this.scanner.resetTo(start, start + node.getLength());
+               int token;
+               int startPosition = -1;
+               try {
+                       while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)  {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameIntegerLiteral :
+                                       case TerminalTokens.TokenNameFloatingPointLiteral :
+                                       case TerminalTokens.TokenNameLongLiteral :
+                                       case TerminalTokens.TokenNameDoubleLiteral :
+                                       case TerminalTokens.TokenNameCharacterLiteral :
+                                               if (startPosition == -1) {
+                                                       startPosition = this.scanner.startPosition;
+                                               }
+                                               int end = this.scanner.currentPosition;
+                                               node.setSourceRange(startPosition, end - startPosition);
+                                               return;
+                                       case TerminalTokens.TokenNameMINUS :
+                                               startPosition = this.scanner.startPosition;
+                                               break;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+       }
+       
+       /**
+        * Remove potential trailing comment by settings the source end on the closing parenthesis
+        */
+       protected void removeTrailingCommentFromExpressionEndingWithAParen(ASTNode node) {
+               int start = node.getStartPosition();
+               this.scanner.resetTo(start, start + node.getLength());
+               int token;
+               int parenCounter = 0;
+               try {
+                       while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)  {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameLPAREN :
+                                               parenCounter++;
+                                               break;
+                                       case TerminalTokens.TokenNameRPAREN :
+                                               parenCounter--;
+                                               if (parenCounter == 0) {
+                                                       int end = this.scanner.currentPosition - 1;
+                                                       node.setSourceRange(start, end - start + 1);
+                                               }
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+       }
+
+       /**
+        * This method is used to retrieve the end position of the block.
+        * @return int the dimension found, -1 if none
+        */
+       protected int retrieveClosingAngleBracketPosition(int start) {
+               this.scanner.resetTo(start, this.compilationUnitSourceLength);
+               this.scanner.returnOnlyGreater = true;
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameGREATER:
+                                               return this.scanner.currentPosition - 1;
+                                       default:
+                                               return start;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               this.scanner.returnOnlyGreater = false;
+               return start;
+       }
+
+       /**
+        * This method is used to set the right end position for expression
+        * statement. The actual AST nodes don't include the trailing semicolon.
+        * This method fixes the length of the corresponding node.
+        */
+       protected void retrieveColonPosition(ASTNode node) {
+               int start = node.getStartPosition();
+               int length = node.getLength();
+               int end = start + length;
+               this.scanner.resetTo(end, this.compilationUnitSourceLength);
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameCOLON:
+                                               node.setSourceRange(start, this.scanner.currentPosition - start);
+                                               return;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+       }
+       /**
+        * This method is used to retrieve the start position of the Ellipsis
+        */
+       protected int retrieveEllipsisStartPosition(int start, int end) {
+               this.scanner.resetTo(start, end);
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameELLIPSIS:
+                                               return this.scanner.startPosition - 1;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       
+       }
+       /**
+        * This method is used to retrieve the end position of the block.
+        * @return int the dimension found, -1 if none
+        */
+       protected int retrieveEndBlockPosition(int start, int end) {
+               this.scanner.resetTo(start, end);
+               int count = 0;
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameLBRACE://110
+                                               count++;
+                                               break;
+                                       case TerminalTokens.TokenNameRBRACE://95
+                                               count--;
+                                               if (count == 0) {
+                                                       return this.scanner.currentPosition - 1;
+                                               }
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       }
+
+       protected int retrieveSemiColonPosition(Expression node) {
+               int start = node.getStartPosition();
+               int length = node.getLength();
+               int end = start + length;
+               this.scanner.resetTo(end, this.compilationUnitSourceLength);
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameSEMICOLON:
+                                               return this.scanner.currentPosition - 1;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       }
+
+       /**
+        * This method is used to retrieve the ending position for a type declaration when the dimension is right after the type
+        * name.
+        * For example:
+        *    int[] i; => return 5, but int i[] => return -1;
+        * @return int the dimension found
+        */
+       protected int retrieveEndOfDimensionsPosition(int start, int end) {
+               this.scanner.resetTo(start, end);
+               int foundPosition = -1;
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameLBRACKET:
+                                       case TerminalTokens.TokenNameCOMMENT_BLOCK:
+                                       case TerminalTokens.TokenNameCOMMENT_JAVADOC:
+                                       case TerminalTokens.TokenNameCOMMENT_LINE:
+                                               break;
+                                       case TerminalTokens.TokenNameRBRACKET://166
+                                               foundPosition = this.scanner.currentPosition - 1;
+                                               break;
+                                       default:
+                                               return foundPosition;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return foundPosition;
+       }
+
+       /**
+        * This method is used to retrieve the position just before the left bracket.
+        * @return int the dimension found, -1 if none
+        */
+       protected int retrieveEndOfElementTypeNamePosition(int start, int end) {
+               this.scanner.resetTo(start, end);
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameIdentifier:
+                                       case TerminalTokens.TokenNamebyte:
+                                       case TerminalTokens.TokenNamechar:
+                                       case TerminalTokens.TokenNamedouble:
+                                       case TerminalTokens.TokenNamefloat:
+                                       case TerminalTokens.TokenNameint:
+                                       case TerminalTokens.TokenNamelong:
+                                       case TerminalTokens.TokenNameshort:
+                                       case TerminalTokens.TokenNameboolean:
+                                               return this.scanner.currentPosition - 1;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       }
+
+       /**
+        * This method is used to retrieve the position after the right parenthesis.
+        * @return int the position found
+        */
+       protected int retrieveEndOfRightParenthesisPosition(int start, int end) {
+               this.scanner.resetTo(start, end);
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameRPAREN:
+                                               return this.scanner.currentPosition;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       }
+
+       /**
+        * This method is used to retrieve the array dimension declared after the
+        * name of a local or a field declaration.
+        * For example:
+        *    int i, j[] = null, k[][] = {{}};
+        *    It should return 0 for i, 1 for j and 2 for k.
+        * @return int the dimension found
+        */
+       protected int retrieveExtraDimension(int start, int end) {
+               this.scanner.resetTo(start, end);
+               int dimensions = 0;
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameLBRACKET:
+                                       case TerminalTokens.TokenNameCOMMENT_BLOCK:
+                                       case TerminalTokens.TokenNameCOMMENT_JAVADOC:
+                                       case TerminalTokens.TokenNameCOMMENT_LINE:
+                                               break;
+                                       case TerminalTokens.TokenNameRBRACKET://166
+                                               dimensions++;
+                                               break;
+                                       default:
+                                               return dimensions;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return dimensions;
+       }
+
+       protected void retrieveIdentifierAndSetPositions(int start, int end, Name name) {
+               this.scanner.resetTo(start, end);
+               int token;
+               try {
+                       while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF)  {
+                               if (token == TerminalTokens.TokenNameIdentifier) {
+                                       int startName = this.scanner.startPosition;
+                                       int endName = this.scanner.currentPosition - 1;
+                                       name.setSourceRange(startName, endName - startName + 1);
+                                       return;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+       }
+       
+       /**
+        * This method is used to retrieve the start position of the block.
+        * @return int the dimension found, -1 if none
+        */
+       protected int retrieveIdentifierEndPosition(int start, int end) {
+               this.scanner.resetTo(start, end);
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameIdentifier://110
+                                               return this.scanner.getCurrentTokenEndPosition();
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       }       
+
+       /**
+        * This method is used to retrieve position before the next comma or semi-colon.
+        * @param initializerEnd the given initializer end exclusive
+        * @return int the position found.
+        */
+       protected int retrieveEndOfPotentialExtendedDimensions(int initializerEnd, int nameEnd, int end) {
+               this.scanner.resetTo(initializerEnd, end);
+               boolean hasTokens = false;
+               int balance = 0;
+               int pos = initializerEnd > nameEnd ? initializerEnd - 1 : nameEnd;
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               hasTokens = true;
+                               switch(token) {
+                                       case TerminalTokens.TokenNameLBRACE :
+                                       case TerminalTokens.TokenNameLBRACKET :
+                                               balance++;
+                                               break;
+                                       case TerminalTokens.TokenNameRBRACKET :
+                                       case TerminalTokens.TokenNameRBRACE :
+                                               balance --;
+                                               pos = this.scanner.currentPosition - 1;
+                                               break;
+                                       case TerminalTokens.TokenNameCOMMA :
+                                               if (balance == 0) return pos;
+                                               // case where a missing closing brace doesn't close an array initializer
+                                               pos = this.scanner.currentPosition - 1;
+                                               break;
+                                       case TerminalTokens.TokenNameSEMICOLON :
+                                               if (balance == 0) return pos;
+                                               return -pos;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               // no token, we simply return pos as the right position
+               return hasTokens ? Integer.MIN_VALUE : pos;
+       }
+
+       protected int retrieveProperRightBracketPosition(int bracketNumber, int start) {
+               this.scanner.resetTo(start, this.compilationUnitSourceLength);
+               try {
+                       int token, count = 0;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameRBRACKET:
+                                               count++;
+                                               if (count == bracketNumber) {
+                                                       return this.scanner.currentPosition - 1;
+                                               }
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       }
+
+       /**
+        * This method is used to retrieve position before the next right brace or semi-colon.
+        * @return int the position found.
+        */
+       protected int retrieveRightBraceOrSemiColonPosition(int start, int end) {
+               this.scanner.resetTo(start, end);
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameRBRACE :
+                                               return this.scanner.currentPosition - 1;
+                                       case TerminalTokens.TokenNameSEMICOLON :
+                                               return this.scanner.currentPosition - 1;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       }
+
+       /**
+        * This method is used to retrieve position before the next right brace or semi-colon.
+        * @return int the position found.
+        */
+       protected int retrieveRightBrace(int start, int end) {
+               this.scanner.resetTo(start, end);
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameRBRACE :
+                                               return this.scanner.currentPosition - 1;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       }
+       
+       /**
+        * This method is used to retrieve the position of the right bracket.
+        * @return int the dimension found, -1 if none
+        */
+       protected int retrieveRightBracketPosition(int start, int end) {
+               this.scanner.resetTo(start, end);
+               try {
+                       int token;
+                       int balance = 0;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameLBRACKET :
+                                               balance++;
+                                               break;
+                                       case TerminalTokens.TokenNameRBRACKET :
+                                               balance--;
+                                               if (balance == 0) return this.scanner.currentPosition - 1;
+                                               break;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       }
+
+       /**
+        * This method is used to retrieve the start position of the block.
+        * @return int the dimension found, -1 if none
+        */
+       protected int retrieveStartBlockPosition(int start, int end) {
+               this.scanner.resetTo(start, end);
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameLBRACE://110
+                                               return this.scanner.startPosition;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       }
+
+       /**
+        * This method is used to retrieve the starting position of the catch keyword.
+        * @return int the dimension found, -1 if none
+        */
+       protected int retrieveStartingCatchPosition(int start, int end) {
+               this.scanner.resetTo(start, end);
+               try {
+                       int token;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNamecatch://225
+                                               return this.scanner.startPosition;
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+               return -1;
+       }
+       
+       public void setAST(AST ast) {
+               this.ast = ast;
+               this.docParser = new DocCommentParser(this.ast, this.scanner, this.insideComments);
+       }
+
+       protected void setModifiers(AnnotationTypeDeclaration typeDecl, net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+               this.scanner.resetTo(typeDeclaration.declarationSourceStart, typeDeclaration.sourceStart);
+               this.setModifiers(typeDecl, typeDeclaration.annotations, typeDeclaration.sourceStart);
+       }
+       
+       protected void setModifiers(AnnotationTypeMemberDeclaration annotationTypeMemberDecl, net.sourceforge.phpdt.internal.compiler.ast.AnnotationMethodDeclaration annotationTypeMemberDeclaration) {
+               this.scanner.resetTo(annotationTypeMemberDeclaration.declarationSourceStart, annotationTypeMemberDeclaration.sourceStart);
+               this.setModifiers(annotationTypeMemberDecl, annotationTypeMemberDeclaration.annotations, annotationTypeMemberDeclaration.sourceStart);
+       }
+
+       /**
+        * @param bodyDeclaration
+        */
+       protected void setModifiers(BodyDeclaration bodyDeclaration, net.sourceforge.phpdt.internal.compiler.ast.Annotation[] annotations, int modifiersEnd) {
+               this.scanner.tokenizeWhiteSpace = false;
+               try {
+                       int token;
+                       int indexInAnnotations = 0;
+                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               IExtendedModifier modifier = null;
+                               switch(token) {
+                                       case TerminalTokens.TokenNameabstract:
+                                               modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+                                               break;
+                                       case TerminalTokens.TokenNamepublic:
+                                               modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+                                               break;
+                                       case TerminalTokens.TokenNamestatic:
+                                               modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+                                               break;
+                                       case TerminalTokens.TokenNameprotected:
+                                               modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+                                               break;
+                                       case TerminalTokens.TokenNameprivate:
+                                               modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+                                               break;
+                                       case TerminalTokens.TokenNamefinal:
+                                               modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+                                               break;
+                                       case TerminalTokens.TokenNamenative:
+                                               modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+                                               break;
+                                       case TerminalTokens.TokenNamesynchronized:
+                                               modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+                                               break;
+                                       case TerminalTokens.TokenNametransient:
+                                               modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+                                               break;
+                                       case TerminalTokens.TokenNamevolatile:
+                                               modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+                                               break;
+                                       case TerminalTokens.TokenNamestrictfp:
+                                               modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+                                               break;
+                                       case TerminalTokens.TokenNameAT :
+                                               // we have an annotation
+                                               if (annotations != null && indexInAnnotations < annotations.length) {
+                                                       net.sourceforge.phpdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+                                                       modifier = convert(annotation);
+                                                       this.scanner.resetTo(annotation.declarationSourceEnd + 1, modifiersEnd);
+                                               }
+                                               break;
+                                       case TerminalTokens.TokenNameCOMMENT_BLOCK :
+                                       case TerminalTokens.TokenNameCOMMENT_LINE :
+                                       case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+                                               break;
+                                       default :
+                                               // there is some syntax errors in source code
+                                               break;
+                               }
+                               if (modifier != null) {
+                                       bodyDeclaration.modifiers().add(modifier);
+                               }
+                       }
+               } catch(InvalidInputException e) {
+                       // ignore
+               }
+       }
+
+       protected void setModifiers(EnumDeclaration enumDeclaration, net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration enumDeclaration2) {
+               this.scanner.resetTo(enumDeclaration2.declarationSourceStart, enumDeclaration2.sourceStart);
+               this.setModifiers(enumDeclaration, enumDeclaration2.annotations, enumDeclaration2.sourceStart);
+       }
+       
+       protected void setModifiers(EnumConstantDeclaration enumConstantDeclaration, net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration) {
+               switch(this.ast.apiLevel) {
+                       case AST.JLS2_INTERNAL :
+                               enumConstantDeclaration.internalSetModifiers(fieldDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag);
+                               if (fieldDeclaration.annotations != null) {
+                                       enumConstantDeclaration.setFlags(enumConstantDeclaration.getFlags() | ASTNode.MALFORMED);
+                               }
+                               break;
+                       case AST.JLS3 :
+                               this.scanner.resetTo(fieldDeclaration.declarationSourceStart, fieldDeclaration.sourceStart);
+                               this.setModifiers(enumConstantDeclaration, fieldDeclaration.annotations, fieldDeclaration.sourceStart);
+               }
+       }
+       
+       /**
+        * @param fieldDeclaration
+        * @param fieldDecl
+        */
+       protected void setModifiers(FieldDeclaration fieldDeclaration, net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDecl) {
+               switch(this.ast.apiLevel) {
+                       case AST.JLS2_INTERNAL :
+                               fieldDeclaration.internalSetModifiers(fieldDecl.modifiers & ExtraCompilerModifiers.AccJustFlag);
+                               if (fieldDecl.annotations != null) {
+                                       fieldDeclaration.setFlags(fieldDeclaration.getFlags() | ASTNode.MALFORMED);
+                               }
+                               break;
+                       case AST.JLS3 :
+                               this.scanner.resetTo(fieldDecl.declarationSourceStart, fieldDecl.sourceStart);
+                               this.setModifiers(fieldDeclaration, fieldDecl.annotations, fieldDecl.sourceStart);
+               }
+       }
+       
+       /**
+        * @param initializer
+        * @param oldInitializer
+        */
+       protected void setModifiers(Initializer initializer, net.sourceforge.phpdt.internal.compiler.ast.Initializer oldInitializer) {
+               switch(this.ast.apiLevel) {
+                       case AST.JLS2_INTERNAL: 
+                               initializer.internalSetModifiers(oldInitializer.modifiers & ExtraCompilerModifiers.AccJustFlag);
+                               if (oldInitializer.annotations != null) {
+                                       initializer.setFlags(initializer.getFlags() | ASTNode.MALFORMED);
+                               }
+                               break;
+                       case AST.JLS3 :
+                               this.scanner.resetTo(oldInitializer.declarationSourceStart, oldInitializer.bodyStart);
+                               this.setModifiers(initializer, oldInitializer.annotations, oldInitializer.bodyStart);
+               }
+       }
+       /**
+        * @param methodDecl
+        * @param methodDeclaration
+        */
+       protected void setModifiers(MethodDeclaration methodDecl, AbstractMethodDeclaration methodDeclaration) {
+               switch(this.ast.apiLevel) {
+                       case AST.JLS2_INTERNAL :
+                               methodDecl.internalSetModifiers(methodDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag);
+                               if (methodDeclaration.annotations != null) {
+                                       methodDecl.setFlags(methodDecl.getFlags() | ASTNode.MALFORMED);
+                               }
+                               break;
+                       case AST.JLS3 :
+                               this.scanner.resetTo(methodDeclaration.declarationSourceStart, methodDeclaration.sourceStart);
+                               this.setModifiers(methodDecl, methodDeclaration.annotations, methodDeclaration.sourceStart);
+               }
+       }
+
+       /**
+        * @param variableDecl
+        * @param argument
+        */
+       protected void setModifiers(SingleVariableDeclaration variableDecl, Argument argument) {
+               switch(this.ast.apiLevel) {
+                       case AST.JLS2_INTERNAL :
+                               variableDecl.internalSetModifiers(argument.modifiers & ExtraCompilerModifiers.AccJustFlag);
+                               if (argument.annotations != null) {
+                                       variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+                               }
+                               break;
+                       case AST.JLS3 :
+                               this.scanner.resetTo(argument.declarationSourceStart, argument.sourceStart);
+                               net.sourceforge.phpdt.internal.compiler.ast.Annotation[] annotations = argument.annotations;
+                               int indexInAnnotations = 0;
+                               try {
+                                       int token;
+                                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                                               IExtendedModifier modifier = null;
+                                               switch(token) {
+                                                       case TerminalTokens.TokenNameabstract:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamepublic:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamestatic:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNameprotected:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNameprivate:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamefinal:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamenative:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamesynchronized:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNametransient:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamevolatile:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamestrictfp:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNameAT :
+                                                               // we have an annotation
+                                                               if (annotations != null && indexInAnnotations < annotations.length) {
+                                                                       net.sourceforge.phpdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+                                                                       modifier = convert(annotation);
+                                                                       this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.compilationUnitSourceLength);
+                                                               }
+                                                               break;
+                                                       case TerminalTokens.TokenNameCOMMENT_BLOCK :
+                                                       case TerminalTokens.TokenNameCOMMENT_LINE :
+                                                       case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+                                                               break;
+                                                       default :
+                                                               return;
+                                               }
+                                               if (modifier != null) {
+                                                       variableDecl.modifiers().add(modifier);
+                                               }
+                                       }
+                               } catch(InvalidInputException e) {
+                                       // ignore
+                               }
+               }
+       }
+       
+       protected void setModifiers(SingleVariableDeclaration variableDecl, LocalDeclaration localDeclaration) {
+               switch(this.ast.apiLevel) {
+               case AST.JLS2_INTERNAL :
+                       variableDecl.internalSetModifiers(localDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag);
+                       if (localDeclaration.annotations != null) {
+                               variableDecl.setFlags(variableDecl.getFlags() | ASTNode.MALFORMED);
+                       }
+                       break;
+               case AST.JLS3 :
+                       this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+                       net.sourceforge.phpdt.internal.compiler.ast.Annotation[] annotations = localDeclaration.annotations;
+                       int indexInAnnotations = 0;
+                       try {
+                               int token;
+                               while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                                       IExtendedModifier modifier = null;
+                                       switch(token) {
+                                               case TerminalTokens.TokenNameabstract:
+                                                       modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+                                                       break;
+                                               case TerminalTokens.TokenNamepublic:
+                                                       modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+                                                       break;
+                                               case TerminalTokens.TokenNamestatic:
+                                                       modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+                                                       break;
+                                               case TerminalTokens.TokenNameprotected:
+                                                       modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+                                                       break;
+                                               case TerminalTokens.TokenNameprivate:
+                                                       modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+                                                       break;
+                                               case TerminalTokens.TokenNamefinal:
+                                                       modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+                                                       break;
+                                               case TerminalTokens.TokenNamenative:
+                                                       modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+                                                       break;
+                                               case TerminalTokens.TokenNamesynchronized:
+                                                       modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+                                                       break;
+                                               case TerminalTokens.TokenNametransient:
+                                                       modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+                                                       break;
+                                               case TerminalTokens.TokenNamevolatile:
+                                                       modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+                                                       break;
+                                               case TerminalTokens.TokenNamestrictfp:
+                                                       modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+                                                       break;
+                                               case TerminalTokens.TokenNameAT :
+                                                       // we have an annotation
+                                                       if (annotations != null && indexInAnnotations < annotations.length) {
+                                                               net.sourceforge.phpdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+                                                               modifier = convert(annotation);
+                                                               this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.compilationUnitSourceLength);
+                                                       }
+                                                       break;
+                                               case TerminalTokens.TokenNameCOMMENT_BLOCK :
+                                               case TerminalTokens.TokenNameCOMMENT_LINE :
+                                               case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+                                                       break;
+                                               default :
+                                                       return;
+                                       }
+                                       if (modifier != null) {
+                                               variableDecl.modifiers().add(modifier);
+                                       }
+                               }
+                       } catch(InvalidInputException e) {
+                               // ignore
+                       }
+               }
+       }
+
+       /**
+        * @param typeDecl
+        * @param typeDeclaration
+        */
+       protected void setModifiers(TypeDeclaration typeDecl, net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
+               switch(this.ast.apiLevel) { 
+                       case AST.JLS2_INTERNAL :
+                               int modifiers = typeDeclaration.modifiers;
+                               modifiers &= ~ClassFileConstants.AccInterface; // remove AccInterface flags
+                               modifiers &= ExtraCompilerModifiers.AccJustFlag;
+                               typeDecl.internalSetModifiers(modifiers);
+                               if (typeDeclaration.annotations != null) {
+                                       typeDecl.setFlags(typeDecl.getFlags() | ASTNode.MALFORMED);
+                               }
+                               break;
+                       case AST.JLS3 :
+                               this.scanner.resetTo(typeDeclaration.declarationSourceStart, typeDeclaration.sourceStart);
+                               this.setModifiers(typeDecl, typeDeclaration.annotations, typeDeclaration.sourceStart);
+               }
+       }
+       
+       /**
+        * @param variableDeclarationExpression
+        * @param localDeclaration
+        */
+       protected void setModifiers(VariableDeclarationExpression variableDeclarationExpression, LocalDeclaration localDeclaration) {
+               switch(this.ast.apiLevel) {
+                       case AST.JLS2_INTERNAL :
+                               int modifiers = localDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag;
+                               modifiers &= ~ExtraCompilerModifiers.AccBlankFinal;
+                               variableDeclarationExpression.internalSetModifiers(modifiers);
+                               if (localDeclaration.annotations != null) {
+                                       variableDeclarationExpression.setFlags(variableDeclarationExpression.getFlags() | ASTNode.MALFORMED);
+                               }
+                               break;
+                       case AST.JLS3 :
+                               this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+                               net.sourceforge.phpdt.internal.compiler.ast.Annotation[] annotations = localDeclaration.annotations;
+                               int indexInAnnotations = 0;
+                               try {
+                                       int token;
+                                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                                               IExtendedModifier modifier = null;
+                                               switch(token) {
+                                                       case TerminalTokens.TokenNameabstract:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamepublic:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamestatic:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNameprotected:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNameprivate:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamefinal:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamenative:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamesynchronized:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNametransient:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamevolatile:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamestrictfp:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNameAT :
+                                                               // we have an annotation
+                                                               if (annotations != null && indexInAnnotations < annotations.length) {
+                                                                       net.sourceforge.phpdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+                                                                       modifier = convert(annotation);
+                                                                       this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.compilationUnitSourceLength);
+                                                               }
+                                                               break;
+                                                       case TerminalTokens.TokenNameCOMMENT_BLOCK :
+                                                       case TerminalTokens.TokenNameCOMMENT_LINE :
+                                                       case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+                                                               break;
+                                                       default :
+                                                               return;
+                                               }
+                                               if (modifier != null) {
+                                                       variableDeclarationExpression.modifiers().add(modifier);
+                                               }
+                                       }
+                               } catch(InvalidInputException e) {
+                                       // ignore
+                               }
+               }               
+       }
+
+       /**
+        * @param variableDeclarationStatement
+        * @param localDeclaration
+        */
+       protected void setModifiers(VariableDeclarationStatement variableDeclarationStatement, LocalDeclaration localDeclaration) {
+               switch(this.ast.apiLevel) {
+                       case AST.JLS2_INTERNAL :
+                               int modifiers = localDeclaration.modifiers & ExtraCompilerModifiers.AccJustFlag;
+                               modifiers &= ~ExtraCompilerModifiers.AccBlankFinal;
+                               variableDeclarationStatement.internalSetModifiers(modifiers);
+                               if (localDeclaration.annotations != null) {
+                                       variableDeclarationStatement.setFlags(variableDeclarationStatement.getFlags() | ASTNode.MALFORMED);
+                               }
+                               break;
+                       case AST.JLS3 :
+                               this.scanner.resetTo(localDeclaration.declarationSourceStart, localDeclaration.sourceStart);
+                               net.sourceforge.phpdt.internal.compiler.ast.Annotation[] annotations = localDeclaration.annotations;
+                               int indexInAnnotations = 0;
+                               try {
+                                       int token;
+                                       while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                                               IExtendedModifier modifier = null;
+                                               switch(token) {
+                                                       case TerminalTokens.TokenNameabstract:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamepublic:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamestatic:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.STATIC_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNameprotected:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.PROTECTED_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNameprivate:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamefinal:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.FINAL_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamenative:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.NATIVE_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamesynchronized:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.SYNCHRONIZED_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNametransient:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.TRANSIENT_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamevolatile:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.VOLATILE_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNamestrictfp:
+                                                               modifier = createModifier(Modifier.ModifierKeyword.STRICTFP_KEYWORD);
+                                                               break;
+                                                       case TerminalTokens.TokenNameAT :
+                                                               // we have an annotation
+                                                               if (annotations != null && indexInAnnotations < annotations.length) {
+                                                                       net.sourceforge.phpdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++];
+                                                                       modifier = convert(annotation);
+                                                                       this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.compilationUnitSourceLength);
+                                                               }
+                                                               break;
+                                                       case TerminalTokens.TokenNameCOMMENT_BLOCK :
+                                                       case TerminalTokens.TokenNameCOMMENT_LINE :
+                                                       case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+                                                               break;
+                                                       default :
+                                                               return;
+                                               }
+                                               if (modifier != null) {
+                                                       variableDeclarationStatement.modifiers().add(modifier);
+                                               }
+                                       }
+                               } catch(InvalidInputException e) {
+                                       // ignore
+                               }
+               }                               
+       }
+
+       protected QualifiedName setQualifiedNameNameAndSourceRanges(char[][] typeName, long[] positions, net.sourceforge.phpdt.internal.compiler.ast.ASTNode node) {
+               int length = typeName.length;
+               final SimpleName firstToken = new SimpleName(this.ast);
+               firstToken.internalSetIdentifier(new String(typeName[0]));
+               firstToken.index = 1;
+               int start0 = (int)(positions[0]>>>32);
+               int start = start0;
+               int end = (int)(positions[0] & 0xFFFFFFFF);
+               firstToken.setSourceRange(start, end - start + 1);
+               final SimpleName secondToken = new SimpleName(this.ast);
+               secondToken.internalSetIdentifier(new String(typeName[1]));
+               secondToken.index = 2;
+               start = (int)(positions[1]>>>32);
+               end = (int)(positions[1] & 0xFFFFFFFF);
+               secondToken.setSourceRange(start, end - start + 1);
+               QualifiedName qualifiedName = new QualifiedName(this.ast);
+               qualifiedName.setQualifier(firstToken);
+               qualifiedName.setName(secondToken);
+               if (this.resolveBindings) {
+                       recordNodes(qualifiedName, node);
+                       recordPendingNameScopeResolution(qualifiedName);
+                       recordNodes(firstToken, node);
+                       recordNodes(secondToken, node);
+                       recordPendingNameScopeResolution(firstToken);
+                       recordPendingNameScopeResolution(secondToken);
+               }
+               qualifiedName.index = 2;
+               qualifiedName.setSourceRange(start0, end - start0 + 1);
+               SimpleName newPart = null;
+               for (int i = 2; i < length; i++) {
+                       newPart = new SimpleName(this.ast);
+                       newPart.internalSetIdentifier(new String(typeName[i]));
+                       newPart.index = i + 1;
+                       start = (int)(positions[i]>>>32);
+                       end = (int)(positions[i] & 0xFFFFFFFF);
+                       newPart.setSourceRange(start,  end - start + 1);
+                       QualifiedName qualifiedName2 = new QualifiedName(this.ast);
+                       qualifiedName2.setQualifier(qualifiedName);
+                       qualifiedName2.setName(newPart);
+                       qualifiedName = qualifiedName2;
+                       qualifiedName.index = newPart.index;
+                       qualifiedName.setSourceRange(start0, end - start0 + 1);
+                       if (this.resolveBindings) {
+                               recordNodes(qualifiedName, node);
+                               recordNodes(newPart, node);                             
+                               recordPendingNameScopeResolution(qualifiedName);
+                               recordPendingNameScopeResolution(newPart);
+                       }
+               }
+               QualifiedName name = qualifiedName;
+               if (this.resolveBindings) {
+                       recordNodes(name, node);
+                       recordPendingNameScopeResolution(name);
+               }
+               return name;
+       }
+       
+       protected QualifiedName setQualifiedNameNameAndSourceRanges(char[][] typeName, long[] positions, int endingIndex, net.sourceforge.phpdt.internal.compiler.ast.ASTNode node) {
+               int length = endingIndex + 1;
+               final SimpleName firstToken = new SimpleName(this.ast);
+               firstToken.internalSetIdentifier(new String(typeName[0]));
+               firstToken.index = 1;
+               int start0 = (int)(positions[0]>>>32);
+               int start = start0;
+               int end = (int) positions[0];
+               firstToken.setSourceRange(start, end - start + 1);
+               final SimpleName secondToken = new SimpleName(this.ast);
+               secondToken.internalSetIdentifier(new String(typeName[1]));
+               secondToken.index = 2;
+               start = (int)(positions[1]>>>32);
+               end = (int) positions[1];
+               secondToken.setSourceRange(start, end - start + 1);
+               QualifiedName qualifiedName = new QualifiedName(this.ast);
+               qualifiedName.setQualifier(firstToken);
+               qualifiedName.setName(secondToken);
+               if (this.resolveBindings) {
+                       recordNodes(qualifiedName, node);
+                       recordPendingNameScopeResolution(qualifiedName);
+                       recordNodes(firstToken, node);
+                       recordNodes(secondToken, node);
+                       recordPendingNameScopeResolution(firstToken);
+                       recordPendingNameScopeResolution(secondToken);
+               }
+               qualifiedName.index = 2;
+               qualifiedName.setSourceRange(start0, end - start0 + 1);
+               SimpleName newPart = null;
+               for (int i = 2; i < length; i++) {
+                       newPart = new SimpleName(this.ast);
+                       newPart.internalSetIdentifier(new String(typeName[i]));
+                       newPart.index = i + 1;
+                       start = (int)(positions[i]>>>32);
+                       end = (int) positions[i];
+                       newPart.setSourceRange(start,  end - start + 1);
+                       QualifiedName qualifiedName2 = new QualifiedName(this.ast);
+                       qualifiedName2.setQualifier(qualifiedName);
+                       qualifiedName2.setName(newPart);
+                       qualifiedName = qualifiedName2;
+                       qualifiedName.index = newPart.index;
+                       qualifiedName.setSourceRange(start0, end - start0 + 1);
+                       if (this.resolveBindings) {
+                               recordNodes(qualifiedName, node);
+                               recordNodes(newPart, node);                             
+                               recordPendingNameScopeResolution(qualifiedName);
+                               recordPendingNameScopeResolution(newPart);
+                       }
+               }
+        if (newPart == null && this.resolveBindings) {
+            recordNodes(qualifiedName, node);
+            recordPendingNameScopeResolution(qualifiedName);
+        }
+               return qualifiedName;
+       }
+       
+       protected void setTypeNameForAnnotation(net.sourceforge.phpdt.internal.compiler.ast.Annotation compilerAnnotation, Annotation annotation) {
+               TypeReference typeReference = compilerAnnotation.type;
+               if (typeReference instanceof QualifiedTypeReference) {
+                       QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) typeReference;
+                       char[][] tokens = qualifiedTypeReference.tokens;
+                       long[] positions = qualifiedTypeReference.sourcePositions;
+                       // QualifiedName
+                       annotation.setTypeName(setQualifiedNameNameAndSourceRanges(tokens, positions, typeReference));
+               } else {
+                       SingleTypeReference singleTypeReference = (SingleTypeReference) typeReference;
+                       final SimpleName name = new SimpleName(this.ast);
+                       name.internalSetIdentifier(new String(singleTypeReference.token));
+                       int start = singleTypeReference.sourceStart;
+                       int end = singleTypeReference.sourceEnd;
+                       name.setSourceRange(start, end - start + 1);
+                       name.index = 1;
+                       annotation.setTypeName(name);
+                       if (this.resolveBindings) {
+                               recordNodes(name, typeReference);
+                       }
+               }
+       }
+       
+       protected void setTypeForField(FieldDeclaration fieldDeclaration, Type type, int extraDimension) {
+               if (extraDimension != 0) {
+                       if (type.isArrayType()) {
+                               ArrayType arrayType = (ArrayType) type;
+                               int remainingDimensions = arrayType.getDimensions() - extraDimension;
+                               if (remainingDimensions == 0)  {
+                                       // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+                                       Type elementType = arrayType.getElementType();
+                                       // cut the child loose from its parent (without creating garbage)
+                                       elementType.setParent(null, null);
+                                       this.ast.getBindingResolver().updateKey(type, elementType);
+                                       fieldDeclaration.setType(elementType);
+                               } else {
+                                       int start = type.getStartPosition();
+                                       ArrayType subarrayType = arrayType;
+                                       int index = extraDimension;
+                                       while (index > 0) {
+                                               subarrayType = (ArrayType) subarrayType.getComponentType();
+                                               index--;
+                                       }
+                                       int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+                                       subarrayType.setSourceRange(start, end - start + 1);
+                                       // cut the child loose from its parent (without creating garbage)
+                                       subarrayType.setParent(null, null);
+                                       fieldDeclaration.setType(subarrayType);
+                                       updateInnerPositions(subarrayType, remainingDimensions);
+                                       this.ast.getBindingResolver().updateKey(type, subarrayType);
+                               }
+                       } else {
+                               fieldDeclaration.setType(type);
+                       }
+               } else {
+                       if (type.isArrayType()) {
+                               // update positions of the component types of the array type
+                               int dimensions = ((ArrayType) type).getDimensions();
+                               updateInnerPositions(type, dimensions);
+                       }
+                       fieldDeclaration.setType(type);
+               }
+       }
+       
+       protected void setTypeForMethodDeclaration(MethodDeclaration methodDeclaration, Type type, int extraDimension) {
+               if (extraDimension != 0) {
+                       if (type.isArrayType()) {
+                               ArrayType arrayType = (ArrayType) type;
+                               int remainingDimensions = arrayType.getDimensions() - extraDimension;
+                               if (remainingDimensions == 0)  {
+                                       // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+                                       Type elementType = arrayType.getElementType();
+                                       // cut the child loose from its parent (without creating garbage)
+                                       elementType.setParent(null, null);
+                                       this.ast.getBindingResolver().updateKey(type, elementType);
+                                       switch(this.ast.apiLevel) {
+                                               case AST.JLS2_INTERNAL :
+                                                       methodDeclaration.internalSetReturnType(elementType);
+                                                       break;
+                                               case AST.JLS3 :
+                                                       methodDeclaration.setReturnType2(elementType);
+                                               break;
+                                       }
+                               } else {
+                                       int start = type.getStartPosition();
+                                       ArrayType subarrayType = arrayType;
+                                       int index = extraDimension;
+                                       while (index > 0) {
+                                               subarrayType = (ArrayType) subarrayType.getComponentType();
+                                               index--;
+                                       }
+                                       int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+                                       subarrayType.setSourceRange(start, end - start + 1);
+                                       // cut the child loose from its parent (without creating garbage)
+                                       subarrayType.setParent(null, null);
+                                       updateInnerPositions(subarrayType, remainingDimensions);
+                                       switch(this.ast.apiLevel) {
+                                               case AST.JLS2_INTERNAL :
+                                                       methodDeclaration.internalSetReturnType(subarrayType);
+                                                       break;
+                                               case AST.JLS3 :
+                                                       methodDeclaration.setReturnType2(subarrayType);
+                                               break;
+                                       }
+                                       this.ast.getBindingResolver().updateKey(type, subarrayType);
+                               }
+                       } else {
+                               switch(this.ast.apiLevel) {
+                                       case AST.JLS2_INTERNAL :
+                                               methodDeclaration.internalSetReturnType(type);
+                                               break;
+                                       case AST.JLS3 :
+                                               methodDeclaration.setReturnType2(type);
+                                       break;
+                               }
+                       }
+               } else {
+                       switch(this.ast.apiLevel) {
+                               case AST.JLS2_INTERNAL :
+                                       methodDeclaration.internalSetReturnType(type);
+                                       break;
+                               case AST.JLS3 :
+                                       methodDeclaration.setReturnType2(type);
+                               break;
+                       }
+               }
+       }
+       
+       protected void setTypeForMethodDeclaration(AnnotationTypeMemberDeclaration annotationTypeMemberDeclaration, Type type, int extraDimension) {
+               annotationTypeMemberDeclaration.setType(type);
+       }
+
+       protected void setTypeForSingleVariableDeclaration(SingleVariableDeclaration singleVariableDeclaration, Type type, int extraDimension) {
+               if (extraDimension != 0) {
+                       if (type.isArrayType()) {
+                               ArrayType arrayType = (ArrayType) type;
+                               int remainingDimensions = arrayType.getDimensions() - extraDimension;
+                               if (remainingDimensions == 0)  {
+                                       // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+                                       Type elementType = arrayType.getElementType();
+                                       // cut the child loose from its parent (without creating garbage)
+                                       elementType.setParent(null, null);
+                                       this.ast.getBindingResolver().updateKey(type, elementType);
+                                       singleVariableDeclaration.setType(elementType);
+                               } else {
+                                       int start = type.getStartPosition();
+                                       ArrayType subarrayType = arrayType;
+                                       int index = extraDimension;
+                                       while (index > 0) {
+                                               subarrayType = (ArrayType) subarrayType.getComponentType();
+                                               index--;
+                                       }
+                                       int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+                                       subarrayType.setSourceRange(start, end - start + 1);
+                                       // cut the child loose from its parent (without creating garbage)
+                                       subarrayType.setParent(null, null);
+                                       updateInnerPositions(subarrayType, remainingDimensions);
+                                       singleVariableDeclaration.setType(subarrayType);
+                                       this.ast.getBindingResolver().updateKey(type, subarrayType);
+                               }
+                       } else {
+                               singleVariableDeclaration.setType(type);
+                       }
+               } else {
+                       singleVariableDeclaration.setType(type);
+               }
+       }
+
+       protected void setTypeForVariableDeclarationExpression(VariableDeclarationExpression variableDeclarationExpression, Type type, int extraDimension) {
+               if (extraDimension != 0) {
+                       if (type.isArrayType()) {
+                               ArrayType arrayType = (ArrayType) type;
+                               int remainingDimensions = arrayType.getDimensions() - extraDimension;
+                               if (remainingDimensions == 0)  {
+                                       // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+                                       Type elementType = arrayType.getElementType();
+                                       // cut the child loose from its parent (without creating garbage)
+                                       elementType.setParent(null, null);
+                                       this.ast.getBindingResolver().updateKey(type, elementType);
+                                       variableDeclarationExpression.setType(elementType);
+                               } else {
+                                       int start = type.getStartPosition();
+                                       ArrayType subarrayType = arrayType;
+                                       int index = extraDimension;
+                                       while (index > 0) {
+                                               subarrayType = (ArrayType) subarrayType.getComponentType();
+                                               index--;
+                                       }
+                                       int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+                                       subarrayType.setSourceRange(start, end - start + 1);
+                                       // cut the child loose from its parent (without creating garbage)
+                                       subarrayType.setParent(null, null);
+                                       updateInnerPositions(subarrayType, remainingDimensions);
+                                       variableDeclarationExpression.setType(subarrayType);
+                                       this.ast.getBindingResolver().updateKey(type, subarrayType);
+                               }
+                       } else {
+                               variableDeclarationExpression.setType(type);
+                       }
+               } else {
+                       variableDeclarationExpression.setType(type);
+               }
+       }
+
+       protected void setTypeForVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, Type type, int extraDimension) {
+               if (extraDimension != 0) {
+                       if (type.isArrayType()) {
+                               ArrayType arrayType = (ArrayType) type;
+                               int remainingDimensions = arrayType.getDimensions() - extraDimension;
+                               if (remainingDimensions == 0)  {
+                                       // the dimensions are after the name so the type of the fieldDeclaration is a simpleType
+                                       Type elementType = arrayType.getElementType();
+                                       // cut the child loose from its parent (without creating garbage)
+                                       elementType.setParent(null, null);
+                                       this.ast.getBindingResolver().updateKey(type, elementType);
+                                       variableDeclarationStatement.setType(elementType);
+                               } else {
+                                       int start = type.getStartPosition();
+                                       ArrayType subarrayType = arrayType;
+                                       int index = extraDimension;
+                                       while (index > 0) {
+                                               subarrayType = (ArrayType) subarrayType.getComponentType();
+                                               index--;
+                                       }
+                                       int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+                                       subarrayType.setSourceRange(start, end - start + 1);
+                                       // cut the child loose from its parent (without creating garbage)
+                                       subarrayType.setParent(null, null);
+                                       updateInnerPositions(subarrayType, remainingDimensions);
+                                       variableDeclarationStatement.setType(subarrayType);
+                                       this.ast.getBindingResolver().updateKey(type, subarrayType);
+                               }
+                       } else {
+                               variableDeclarationStatement.setType(type);
+                       }
+               } else {
+                       variableDeclarationStatement.setType(type);
+               }
+       }
+
+       protected void updateInnerPositions(Type type, int dimensions) {
+               if (dimensions > 1) {
+                       // need to set positions for intermediate array type see 42839
+                       int start = type.getStartPosition();
+                       Type currentComponentType = ((ArrayType) type).getComponentType();
+                       int searchedDimension = dimensions - 1;
+                       int rightBracketEndPosition = start;
+                       while (currentComponentType.isArrayType()) {
+                               rightBracketEndPosition = retrieveProperRightBracketPosition(searchedDimension, start);
+                               currentComponentType.setSourceRange(start, rightBracketEndPosition - start + 1);
+                               currentComponentType = ((ArrayType) currentComponentType).getComponentType();
+                               searchedDimension--;
+                       }               
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTMatcher.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTMatcher.java
new file mode 100644 (file)
index 0000000..b9f49fd
--- /dev/null
@@ -0,0 +1,2366 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Concrete superclass and default implementation of an AST subtree matcher.
+ * <p>
+ * For example, to compute whether two ASTs subtrees are structurally 
+ * isomorphic, use <code>n1.subtreeMatch(new ASTMatcher(), n2)</code> where 
+ * <code>n1</code> and <code>n2</code> are the AST root nodes of the subtrees.
+ * </p>
+ * <p>
+ * For each different concrete AST node type <i>T</i> there is a
+ * <code>public boolean match(<i>T</i> node, Object other)</code> method
+ * that matches the given node against another object (typically another
+ * AST node, although this is not essential). The default implementations
+ * provided by this class tests whether the other object is a node of the
+ * same type with structurally isomorphic child subtrees. For nodes with 
+ * list-valued properties, the child nodes within the list are compared in
+ * order. For nodes with multiple properties, the child nodes are compared
+ * in the order that most closely corresponds to the lexical reading order
+ * of the source program. For instance, for a type declaration node, the 
+ * child ordering is: name, superclass, superinterfaces, and body 
+ * declarations.
+ * </p>
+ * <p>
+ * Subclasses may override (extend or reimplement) some or all of the 
+ * <code>match</code> methods in order to define more specialized subtree
+ * matchers.
+ * </p>
+ * 
+ * @see org.eclipse.jdt.core.dom.ASTNode#subtreeMatch(ASTMatcher, Object)
+ * @since 2.0
+ */
+public class ASTMatcher {
+       
+       /**
+        * Indicates whether doc tags should be matched.
+        * @since 3.0
+        */
+       private boolean matchDocTags;
+       
+       /**
+        * Creates a new AST matcher instance.
+        * <p>
+        * For backwards compatibility, the matcher ignores tag
+        * elements below doc comments by default. Use 
+        * {@link #ASTMatcher(boolean) ASTMatcher(true)}
+        * for a matcher that compares doc tags by default.
+        * </p>
+        */
+       public ASTMatcher() {
+               this(false);
+       }
+
+       /**
+        * Creates a new AST matcher instance.
+        * 
+        * @param matchDocTags <code>true</code> if doc comment tags are
+        * to be compared by default, and <code>false</code> otherwise
+        * @see #match(Javadoc,Object)
+        * @since 3.0
+        */
+       public ASTMatcher(boolean matchDocTags) {
+               this.matchDocTags = matchDocTags;
+       }
+
+       /**
+        * Returns whether the given lists of AST nodes match pair wise according
+        * to <code>ASTNode.subtreeMatch</code>.
+        * <p>
+        * Note that this is a convenience method, useful for writing recursive
+        * subtree matchers.
+        * </p>
+        * 
+        * @param list1 the first list of AST nodes
+        *    (element type: <code>ASTNode</code>)
+        * @param list2 the second list of AST nodes
+        *    (element type: <code>ASTNode</code>)
+        * @return <code>true</code> if the lists have the same number of elements
+        *    and match pair-wise according to <code>ASTNode.subtreeMatch</code> 
+        * @see ASTNode#subtreeMatch(ASTMatcher matcher, Object other)
+        */
+       public final boolean safeSubtreeListMatch(List list1, List list2) {
+               int size1 = list1.size();
+               int size2 = list2.size();
+               if (size1 != size2) {
+                       return false;
+               }
+               for (Iterator it1 = list1.iterator(), it2 = list2.iterator(); it1.hasNext();) {
+                       ASTNode n1 = (ASTNode) it1.next();
+                       ASTNode n2 = (ASTNode) it2.next();
+                       if (!n1.subtreeMatch(this, n2)) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       /**
+        * Returns whether the given nodes match according to
+        * <code>AST.subtreeMatch</code>. Returns <code>false</code> if one or
+        * the other of the nodes are <code>null</code>. Returns <code>true</code>
+        * if both nodes are <code>null</code>.
+        * <p>
+        * Note that this is a convenience method, useful for writing recursive
+        * subtree matchers.
+        * </p>
+        * 
+        * @param node1 the first AST node, or <code>null</code>; must be an
+        *    instance of <code>ASTNode</code>
+        * @param node2 the second AST node, or <code>null</code>; must be an
+        *    instance of <code>ASTNode</code>
+        * @return <code>true</code> if the nodes match according
+        *    to <code>AST.subtreeMatch</code> or both are <code>null</code>, and 
+        *    <code>false</code> otherwise
+        * @see ASTNode#subtreeMatch(ASTMatcher, Object)
+        */
+       public final boolean safeSubtreeMatch(Object node1, Object node2) {
+               if (node1 == null && node2 == null) {
+                       return true;
+               }
+               if (node1 == null || node2 == null) {
+                       return false;
+               }
+               // N.B. call subtreeMatch even node1==node2!=null
+               return ((ASTNode) node1).subtreeMatch(this, node2);
+       }
+
+       /**
+        * Returns whether the given objects are equal according to
+        * <code>equals</code>. Returns <code>false</code> if either
+        * node is <code>null</code>.
+        * 
+        * @param o1 the first object, or <code>null</code>
+        * @param o2 the second object, or <code>null</code>
+        * @return <code>true</code> if the nodes are equal according to
+        *    <code>equals</code> or both <code>null</code>, and 
+        *    <code>false</code> otherwise
+        */
+       public static boolean safeEquals(Object o1, Object o2) {
+               if (o1 == o2) {
+                       return true;
+               }
+               if (o1 == null || o2 == null) {
+                       return false;
+               }
+               return o1.equals(o2);
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(AnnotationTypeDeclaration node, Object other) {
+               if (!(other instanceof AnnotationTypeDeclaration)) {
+                       return false;
+               }
+               AnnotationTypeDeclaration o = (AnnotationTypeDeclaration) other;
+               // node type added in JLS3 - ignore old JLS2-style modifiers
+               return (safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+                               && safeSubtreeListMatch(node.modifiers(), o.modifiers())
+                               && safeSubtreeMatch(node.getName(), o.getName())
+                               && safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(AnnotationTypeMemberDeclaration node, Object other) {
+               if (!(other instanceof AnnotationTypeMemberDeclaration)) {
+                       return false;
+               }
+               AnnotationTypeMemberDeclaration o = (AnnotationTypeMemberDeclaration) other;
+               // node type added in JLS3 - ignore old JLS2-style modifiers
+               return (safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+                               && safeSubtreeListMatch(node.modifiers(), o.modifiers())
+                               && safeSubtreeMatch(node.getType(), o.getType())
+                               && safeSubtreeMatch(node.getName(), o.getName())
+                               && safeSubtreeMatch(node.getDefault(), o.getDefault()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(AnonymousClassDeclaration node, Object other) {
+               if (!(other instanceof AnonymousClassDeclaration)) {
+                       return false;
+               }
+               AnonymousClassDeclaration o = (AnonymousClassDeclaration) other;
+               return safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ArrayAccess node, Object other) {
+               if (!(other instanceof ArrayAccess)) {
+                       return false;
+               }
+               ArrayAccess o = (ArrayAccess) other;
+               return (
+                       safeSubtreeMatch(node.getArray(), o.getArray())
+                               && safeSubtreeMatch(node.getIndex(), o.getIndex()));
+       }
+
+       /**
+        * Returns whether the given node and the other object object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ArrayCreation node, Object other) {
+               if (!(other instanceof ArrayCreation)) {
+                       return false;
+               }
+               ArrayCreation o = (ArrayCreation) other;
+               return (
+                       safeSubtreeMatch(node.getType(), o.getType())
+                               && safeSubtreeListMatch(node.dimensions(), o.dimensions())
+                               && safeSubtreeMatch(node.getInitializer(), o.getInitializer()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ArrayInitializer node, Object other) {
+               if (!(other instanceof ArrayInitializer)) {
+                       return false;
+               }
+               ArrayInitializer o = (ArrayInitializer) other;
+               return safeSubtreeListMatch(node.expressions(), o.expressions());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ArrayType node, Object other) {
+               if (!(other instanceof ArrayType)) {
+                       return false;
+               }
+               ArrayType o = (ArrayType) other;
+               return safeSubtreeMatch(node.getComponentType(), o.getComponentType());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(AssertStatement node, Object other) {
+               if (!(other instanceof AssertStatement)) {
+                       return false;
+               }
+               AssertStatement o = (AssertStatement) other;
+               return (
+                       safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeMatch(node.getMessage(), o.getMessage()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(Assignment node, Object other) {
+               if (!(other instanceof Assignment)) {
+                       return false;
+               }
+               Assignment o = (Assignment) other;
+               return (
+                       node.getOperator().equals(o.getOperator())
+                               && safeSubtreeMatch(node.getLeftHandSide(), o.getLeftHandSide())
+                               && safeSubtreeMatch(node.getRightHandSide(), o.getRightHandSide()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(Block node, Object other) {
+               if (!(other instanceof Block)) {
+                       return false;
+               }
+               Block o = (Block) other;
+               return safeSubtreeListMatch(node.statements(), o.statements());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type. Subclasses may override
+        * this method as needed.
+        * </p>
+        * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+        * not considered part of main structure of the AST. This method will
+        * only be called if a client goes out of their way to visit this
+        * kind of node explicitly.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.0
+        */
+       public boolean match(BlockComment node, Object other) {
+               if (!(other instanceof BlockComment)) {
+                       return false;
+               }
+               return true;
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(BooleanLiteral node, Object other) {
+               if (!(other instanceof BooleanLiteral)) {
+                       return false;
+               }
+               BooleanLiteral o = (BooleanLiteral) other;
+               return node.booleanValue() == o.booleanValue();
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(BreakStatement node, Object other) {
+               if (!(other instanceof BreakStatement)) {
+                       return false;
+               }
+               BreakStatement o = (BreakStatement) other;
+               return safeSubtreeMatch(node.getLabel(), o.getLabel());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(CastExpression node, Object other) {
+               if (!(other instanceof CastExpression)) {
+                       return false;
+               }
+               CastExpression o = (CastExpression) other;
+               return (
+                       safeSubtreeMatch(node.getType(), o.getType())
+                               && safeSubtreeMatch(node.getExpression(), o.getExpression()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(CatchClause node, Object other) {
+               if (!(other instanceof CatchClause)) {
+                       return false;
+               }
+               CatchClause o = (CatchClause) other;
+               return (
+                       safeSubtreeMatch(node.getException(), o.getException())
+                               && safeSubtreeMatch(node.getBody(), o.getBody()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(CharacterLiteral node, Object other) {
+               if (!(other instanceof CharacterLiteral)) {
+                       return false;
+               }
+               CharacterLiteral o = (CharacterLiteral) other;
+               return safeEquals(node.getEscapedValue(), o.getEscapedValue());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ClassInstanceCreation node, Object other) {
+               if (!(other instanceof ClassInstanceCreation)) {
+                       return false;
+               }
+               ClassInstanceCreation o = (ClassInstanceCreation) other;
+               int level = node.getAST().apiLevel;
+               if (level == AST.JLS2_INTERNAL) {
+                       if (!safeSubtreeMatch(node.internalGetName(), o.internalGetName())) {
+                               return false;
+                       }
+               }
+               if (level >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+                               return false;
+                       }
+                       if (!safeSubtreeMatch(node.getType(), o.getType())) {
+                               return false;
+                       }
+               }
+               return 
+                       safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeListMatch(node.arguments(), o.arguments())
+                               && safeSubtreeMatch(
+                                       node.getAnonymousClassDeclaration(),
+                                       o.getAnonymousClassDeclaration());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(CompilationUnit node, Object other) {
+               if (!(other instanceof CompilationUnit)) {
+                       return false;
+               }
+               CompilationUnit o = (CompilationUnit) other;
+               return (
+                       safeSubtreeMatch(node.getPackage(), o.getPackage())
+                               && safeSubtreeListMatch(node.imports(), o.imports())
+                               && safeSubtreeListMatch(node.types(), o.types()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ConditionalExpression node, Object other) {
+               if (!(other instanceof ConditionalExpression)) {
+                       return false;
+               }
+               ConditionalExpression o = (ConditionalExpression) other;
+               return (
+                       safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeMatch(node.getThenExpression(), o.getThenExpression())
+                               && safeSubtreeMatch(node.getElseExpression(), o.getElseExpression()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ConstructorInvocation node, Object other) {
+               if (!(other instanceof ConstructorInvocation)) {
+                       return false;
+               }
+               ConstructorInvocation o = (ConstructorInvocation) other;
+               if (node.getAST().apiLevel >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+                               return false;
+                       }
+               }
+               return safeSubtreeListMatch(node.arguments(), o.arguments());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ContinueStatement node, Object other) {
+               if (!(other instanceof ContinueStatement)) {
+                       return false;
+               }
+               ContinueStatement o = (ContinueStatement) other;
+               return safeSubtreeMatch(node.getLabel(), o.getLabel());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(DoStatement node, Object other) {
+               if (!(other instanceof DoStatement)) {
+                       return false;
+               }
+               DoStatement o = (DoStatement) other;
+               return (
+                       safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeMatch(node.getBody(), o.getBody()));
+       }
+       
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(EmptyStatement node, Object other) {
+               if (!(other instanceof EmptyStatement)) {
+                       return false;
+               }
+               return true;
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(EnhancedForStatement node, Object other) {
+               if (!(other instanceof EnhancedForStatement)) {
+                       return false;
+               }
+               EnhancedForStatement o = (EnhancedForStatement) other;
+               return (
+                       safeSubtreeMatch(node.getParameter(), o.getParameter())
+                               && safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeMatch(node.getBody(), o.getBody()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(EnumConstantDeclaration node, Object other) {
+               if (!(other instanceof EnumConstantDeclaration)) {
+                       return false;
+               }
+               EnumConstantDeclaration o = (EnumConstantDeclaration) other;
+               return (
+                       safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+                               && safeSubtreeListMatch(node.modifiers(), o.modifiers())
+                               && safeSubtreeMatch(node.getName(), o.getName())
+                               && safeSubtreeListMatch(node.arguments(), o.arguments())
+                               && safeSubtreeMatch(
+                                       node.getAnonymousClassDeclaration(),
+                                       o.getAnonymousClassDeclaration()));
+       }
+       
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(EnumDeclaration node, Object other) {
+               if (!(other instanceof EnumDeclaration)) {
+                       return false;
+               }
+               EnumDeclaration o = (EnumDeclaration) other;
+               return (
+                       safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+                               && safeSubtreeListMatch(node.modifiers(), o.modifiers())
+                               && safeSubtreeMatch(node.getName(), o.getName())
+                               && safeSubtreeListMatch(node.superInterfaceTypes(), o.superInterfaceTypes())
+                               && safeSubtreeListMatch(node.enumConstants(), o.enumConstants())
+                               && safeSubtreeListMatch(
+                                       node.bodyDeclarations(),
+                                       o.bodyDeclarations()));
+       }
+       
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ExpressionStatement node, Object other) {
+               if (!(other instanceof ExpressionStatement)) {
+                       return false;
+               }
+               ExpressionStatement o = (ExpressionStatement) other;
+               return safeSubtreeMatch(node.getExpression(), o.getExpression());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(FieldAccess node, Object other) {
+               if (!(other instanceof FieldAccess)) {
+                       return false;
+               }
+               FieldAccess o = (FieldAccess) other;
+               return (
+                       safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeMatch(node.getName(), o.getName()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(FieldDeclaration node, Object other) {
+               if (!(other instanceof FieldDeclaration)) {
+                       return false;
+               }
+               FieldDeclaration o = (FieldDeclaration) other;
+               int level = node.getAST().apiLevel;
+               if (level == AST.JLS2_INTERNAL) {
+                       if (node.getModifiers() != o.getModifiers()) {
+                               return false;
+                       }
+               }
+               if (level >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+                               return false;
+                       }
+               }
+               return 
+                       safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+                       && safeSubtreeMatch(node.getType(), o.getType())
+                       && safeSubtreeListMatch(node.fragments(), o.fragments());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ForStatement node, Object other) {
+               if (!(other instanceof ForStatement)) {
+                       return false;
+               }
+               ForStatement o = (ForStatement) other;
+               return (
+                       safeSubtreeListMatch(node.initializers(), o.initializers())
+                               && safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeListMatch(node.updaters(), o.updaters())
+                               && safeSubtreeMatch(node.getBody(), o.getBody()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(IfStatement node, Object other) {
+               if (!(other instanceof IfStatement)) {
+                       return false;
+               }
+               IfStatement o = (IfStatement) other;
+               return (
+                       safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeMatch(node.getThenStatement(), o.getThenStatement())
+                               && safeSubtreeMatch(node.getElseStatement(), o.getElseStatement()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ImportDeclaration node, Object other) {
+               if (!(other instanceof ImportDeclaration)) {
+                       return false;
+               }
+               ImportDeclaration o = (ImportDeclaration) other;
+               if (node.getAST().apiLevel >= AST.JLS3) {
+                       if (node.isStatic() != o.isStatic()) {
+                               return false;
+                       }
+               }
+               return (
+                       safeSubtreeMatch(node.getName(), o.getName())
+                               && node.isOnDemand() == o.isOnDemand());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(InfixExpression node, Object other) {
+               if (!(other instanceof InfixExpression)) {
+                       return false;
+               }
+               InfixExpression o = (InfixExpression) other;
+               // be careful not to trigger lazy creation of extended operand lists
+               if (node.hasExtendedOperands() && o.hasExtendedOperands()) {
+                       if (!safeSubtreeListMatch(node.extendedOperands(), o.extendedOperands())) {
+                               return false;
+                       }
+               }
+               if (node.hasExtendedOperands() != o.hasExtendedOperands()) {
+                       return false;
+               }
+               return (
+                       node.getOperator().equals(o.getOperator())
+                               && safeSubtreeMatch(node.getLeftOperand(), o.getLeftOperand())
+                               && safeSubtreeMatch(node.getRightOperand(), o.getRightOperand()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(InstanceofExpression node, Object other) {
+               if (!(other instanceof InstanceofExpression)) {
+                       return false;
+               }
+               InstanceofExpression o = (InstanceofExpression) other;
+               return (
+                               safeSubtreeMatch(node.getLeftOperand(), o.getLeftOperand())
+                               && safeSubtreeMatch(node.getRightOperand(), o.getRightOperand()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(Initializer node, Object other) {
+               if (!(other instanceof Initializer)) {
+                       return false;
+               }
+               Initializer o = (Initializer) other;
+               int level = node.getAST().apiLevel;
+               if (level == AST.JLS2_INTERNAL) {
+                       if (node.getModifiers() != o.getModifiers()) {
+                               return false;
+                       }
+               }
+               if (level >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+                               return false;
+                       }
+               }
+               return (
+                               safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+                               && safeSubtreeMatch(node.getBody(), o.getBody()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * Unlike other node types, the behavior of the default
+        * implementation is controlled by a constructor-supplied
+        * parameter  {@link #ASTMatcher(boolean) ASTMatcher(boolean)} 
+        * which is <code>false</code> if not specified. 
+        * When this parameter is <code>true</code>, the implementation
+        * tests whether the other object is also a <code>Javadoc</code>
+        * with structurally isomorphic child subtrees; the comment string 
+        * (<code>Javadoc.getComment()</code>) is ignored.
+        * Conversely, when the parameter is <code>false</code>, the
+        * implementation tests whether the other object is also a
+        * <code>Javadoc</code> with exactly the same comment string; 
+        * the tag elements ({@link Javadoc#tags() Javadoc.tags} are
+        * ignored. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @see #ASTMatcher()
+        * @see #ASTMatcher(boolean)
+        */
+       public boolean match(Javadoc node, Object other) {
+               if (!(other instanceof Javadoc)) {
+                       return false;
+               }
+               Javadoc o = (Javadoc) other;
+               if (this.matchDocTags) {
+                       return safeSubtreeListMatch(node.tags(), o.tags());
+               } else {
+                       return compareDeprecatedComment(node, o);
+               }
+       }
+
+       /**
+        * Return whether the deprecated comment strings of the given java doc are equals.
+        * <p>
+        * Note the only purpose of this method is to hide deprecated warnings.
+        * @deprecated mark deprecated to hide deprecated usage
+        */
+       private boolean compareDeprecatedComment(Javadoc first, Javadoc second) {
+               if (first.getAST().apiLevel == AST.JLS2_INTERNAL) {
+                       return safeEquals(first.getComment(), second.getComment());
+               } else {
+                       return true;
+               }
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(LabeledStatement node, Object other) {
+               if (!(other instanceof LabeledStatement)) {
+                       return false;
+               }
+               LabeledStatement o = (LabeledStatement) other;
+               return (
+                       safeSubtreeMatch(node.getLabel(), o.getLabel())
+                               && safeSubtreeMatch(node.getBody(), o.getBody()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type. Subclasses may override
+        * this method as needed.
+        * </p>
+        * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+        * not considered part of main structure of the AST. This method will
+        * only be called if a client goes out of their way to visit this
+        * kind of node explicitly.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.0
+        */
+       public boolean match(LineComment node, Object other) {
+               if (!(other instanceof LineComment)) {
+                       return false;
+               }
+               return true;
+       }
+       
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(MarkerAnnotation node, Object other) {
+               if (!(other instanceof MarkerAnnotation)) {
+                       return false;
+               }
+               MarkerAnnotation o = (MarkerAnnotation) other;
+               return safeSubtreeMatch(node.getTypeName(), o.getTypeName());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.0
+        */
+       public boolean match(MemberRef node, Object other) {
+               if (!(other instanceof MemberRef)) {
+                       return false;
+               }
+               MemberRef o = (MemberRef) other;
+               return (
+                               safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+                               && safeSubtreeMatch(node.getName(), o.getName()));
+       }
+       
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(MemberValuePair node, Object other) {
+               if (!(other instanceof MemberValuePair)) {
+                       return false;
+               }
+               MemberValuePair o = (MemberValuePair) other;
+               return (safeSubtreeMatch(node.getName(), o.getName())
+                               && safeSubtreeMatch(node.getValue(), o.getValue()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.0
+        */
+       public boolean match(MethodRef node, Object other) {
+               if (!(other instanceof MethodRef)) {
+                       return false;
+               }
+               MethodRef o = (MethodRef) other;
+               return (
+                               safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+                               && safeSubtreeMatch(node.getName(), o.getName())
+                       && safeSubtreeListMatch(node.parameters(), o.parameters()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.0
+        */
+       public boolean match(MethodRefParameter node, Object other) {
+               if (!(other instanceof MethodRefParameter)) {
+                       return false;
+               }
+               MethodRefParameter o = (MethodRefParameter) other;
+               int level = node.getAST().apiLevel;
+               if (level >= AST.JLS3) {
+                       if (node.isVarargs() != o.isVarargs()) {
+                               return false;
+                       }
+               }
+               return (
+                               safeSubtreeMatch(node.getType(), o.getType())
+                               && safeSubtreeMatch(node.getName(), o.getName()));
+       }
+       
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * <p>
+        * Note that extra array dimensions are compared since they are an
+        * important part of the method declaration.
+        * </p>
+        * <p>
+        * Note that the method return types are compared even for constructor
+        * declarations.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(MethodDeclaration node, Object other) {
+               if (!(other instanceof MethodDeclaration)) {
+                       return false;
+               }
+               MethodDeclaration o = (MethodDeclaration) other;
+               int level = node.getAST().apiLevel;
+               if (level == AST.JLS2_INTERNAL) {
+                       if (node.getModifiers() != o.getModifiers()) {
+                               return false;
+                       }
+                       if (!safeSubtreeMatch(node.internalGetReturnType(), o.internalGetReturnType())) {
+                               return false;
+                       }
+               }
+               if (level >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+                               return false;
+                       }
+                       if (!safeSubtreeMatch(node.getReturnType2(), o.getReturnType2())) {
+                               return false;
+                       }
+                       // n.b. compare type parameters even for constructors
+                       if (!safeSubtreeListMatch(node.typeParameters(), o.typeParameters())) {
+                               return false;
+                       }
+               }
+               return ((node.isConstructor() == o.isConstructor())
+                               && safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+                               && safeSubtreeMatch(node.getName(), o.getName())
+                               // n.b. compare return type even for constructors
+                               && safeSubtreeListMatch(node.parameters(), o.parameters())
+                               && node.getExtraDimensions() == o.getExtraDimensions()
+                               && safeSubtreeListMatch(node.thrownExceptions(), o.thrownExceptions())
+                               && safeSubtreeMatch(node.getBody(), o.getBody()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(MethodInvocation node, Object other) {
+               if (!(other instanceof MethodInvocation)) {
+                       return false;
+               }
+               MethodInvocation o = (MethodInvocation) other;
+               if (node.getAST().apiLevel >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+                               return false;
+                       }
+               }
+               return (
+                       safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeMatch(node.getName(), o.getName())
+                               && safeSubtreeListMatch(node.arguments(), o.arguments()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(Modifier node, Object other) {
+               if (!(other instanceof Modifier)) {
+                       return false;
+               }
+               Modifier o = (Modifier) other;
+               return (node.getKeyword() == o.getKeyword());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(NormalAnnotation node, Object other) {
+               if (!(other instanceof NormalAnnotation)) {
+                       return false;
+               }
+               NormalAnnotation o = (NormalAnnotation) other;
+               return (safeSubtreeMatch(node.getTypeName(), o.getTypeName())
+                                       && safeSubtreeListMatch(node.values(), o.values()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(NullLiteral node, Object other) {
+               if (!(other instanceof NullLiteral)) {
+                       return false;
+               }
+               return true;
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(NumberLiteral node, Object other) {
+               if (!(other instanceof NumberLiteral)) {
+                       return false;
+               }
+               NumberLiteral o = (NumberLiteral) other;
+               return safeEquals(node.getToken(), o.getToken());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(PackageDeclaration node, Object other) {
+               if (!(other instanceof PackageDeclaration)) {
+                       return false;
+               }
+               PackageDeclaration o = (PackageDeclaration) other;
+               if (node.getAST().apiLevel >= AST.JLS3) {
+                       if (!safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())) {
+                               return false;
+                       }
+                       if (!safeSubtreeListMatch(node.annotations(), o.annotations())) {
+                               return false;
+                       }
+               }
+               return safeSubtreeMatch(node.getName(), o.getName());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(ParameterizedType node, Object other) {
+               if (!(other instanceof ParameterizedType)) {
+                       return false;
+               }
+               ParameterizedType o = (ParameterizedType) other;
+               return safeSubtreeMatch(node.getType(), o.getType())
+                               && safeSubtreeListMatch(node.typeArguments(), o.typeArguments());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ParenthesizedExpression node, Object other) {
+               if (!(other instanceof ParenthesizedExpression)) {
+                       return false;
+               }
+               ParenthesizedExpression o = (ParenthesizedExpression) other;
+               return safeSubtreeMatch(node.getExpression(), o.getExpression());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(PostfixExpression node, Object other) {
+               if (!(other instanceof PostfixExpression)) {
+                       return false;
+               }
+               PostfixExpression o = (PostfixExpression) other;
+               return (
+                       node.getOperator().equals(o.getOperator())
+                               && safeSubtreeMatch(node.getOperand(), o.getOperand()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(PrefixExpression node, Object other) {
+               if (!(other instanceof PrefixExpression)) {
+                       return false;
+               }
+               PrefixExpression o = (PrefixExpression) other;
+               return (
+                       node.getOperator().equals(o.getOperator())
+                               && safeSubtreeMatch(node.getOperand(), o.getOperand()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(PrimitiveType node, Object other) {
+               if (!(other instanceof PrimitiveType)) {
+                       return false;
+               }
+               PrimitiveType o = (PrimitiveType) other;
+               return (node.getPrimitiveTypeCode() == o.getPrimitiveTypeCode());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(QualifiedName node, Object other) {
+               if (!(other instanceof QualifiedName)) {
+                       return false;
+               }
+               QualifiedName o = (QualifiedName) other;
+               return (
+                       safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+                               && safeSubtreeMatch(node.getName(), o.getName()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(QualifiedType node, Object other) {
+               if (!(other instanceof QualifiedType)) {
+                       return false;
+               }
+               QualifiedType o = (QualifiedType) other;
+               return (
+                       safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+                               && safeSubtreeMatch(node.getName(), o.getName()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ReturnStatement node, Object other) {
+               if (!(other instanceof ReturnStatement)) {
+                       return false;
+               }
+               ReturnStatement o = (ReturnStatement) other;
+               return safeSubtreeMatch(node.getExpression(), o.getExpression());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(SimpleName node, Object other) {
+               if (!(other instanceof SimpleName)) {
+                       return false;
+               }
+               SimpleName o = (SimpleName) other;
+               return node.getIdentifier().equals(o.getIdentifier());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(SimpleType node, Object other) {
+               if (!(other instanceof SimpleType)) {
+                       return false;
+               }
+               SimpleType o = (SimpleType) other;
+               return safeSubtreeMatch(node.getName(), o.getName());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(SingleMemberAnnotation node, Object other) {
+               if (!(other instanceof SingleMemberAnnotation)) {
+                       return false;
+               }
+               SingleMemberAnnotation o = (SingleMemberAnnotation) other;
+               return (safeSubtreeMatch(node.getTypeName(), o.getTypeName())
+                               && safeSubtreeMatch(node.getValue(), o.getValue()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * <p>
+        * Note that extra array dimensions and the variable arity flag 
+        * are compared since they are both important parts of the declaration.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(SingleVariableDeclaration node, Object other) {
+               if (!(other instanceof SingleVariableDeclaration)) {
+                       return false;
+               }
+               SingleVariableDeclaration o = (SingleVariableDeclaration) other;
+               int level = node.getAST().apiLevel;
+               if (level == AST.JLS2_INTERNAL) {
+                       if (node.getModifiers() != o.getModifiers()) {
+                               return false;
+                       }
+               }
+               if (level >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+                               return false;
+                       }
+                       if (node.isVarargs() != o.isVarargs()) {
+                               return false;
+                       }
+               }
+               return 
+                   safeSubtreeMatch(node.getType(), o.getType())
+                               && safeSubtreeMatch(node.getName(), o.getName())
+                               && node.getExtraDimensions() == o.getExtraDimensions()
+                               && safeSubtreeMatch(node.getInitializer(), o.getInitializer());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(StringLiteral node, Object other) {
+               if (!(other instanceof StringLiteral)) {
+                       return false;
+               }
+               StringLiteral o = (StringLiteral) other;
+               return safeEquals(node.getEscapedValue(), o.getEscapedValue());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(SuperConstructorInvocation node, Object other) {
+               if (!(other instanceof SuperConstructorInvocation)) {
+                       return false;
+               }
+               SuperConstructorInvocation o = (SuperConstructorInvocation) other;
+               if (node.getAST().apiLevel >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+                               return false;
+                       }
+               }
+               return (
+                       safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeListMatch(node.arguments(), o.arguments()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(SuperFieldAccess node, Object other) {
+               if (!(other instanceof SuperFieldAccess)) {
+                       return false;
+               }
+               SuperFieldAccess o = (SuperFieldAccess) other;
+               return (
+                       safeSubtreeMatch(node.getName(), o.getName())
+                               && safeSubtreeMatch(node.getQualifier(), o.getQualifier()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(SuperMethodInvocation node, Object other) {
+               if (!(other instanceof SuperMethodInvocation)) {
+                       return false;
+               }
+               SuperMethodInvocation o = (SuperMethodInvocation) other;
+               if (node.getAST().apiLevel >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.typeArguments(), o.typeArguments())) {
+                               return false;
+                       }
+               }
+               return (
+                       safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+                               && safeSubtreeMatch(node.getName(), o.getName())
+                               && safeSubtreeListMatch(node.arguments(), o.arguments()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(SwitchCase node, Object other) {
+               if (!(other instanceof SwitchCase)) {
+                       return false;
+               }
+               SwitchCase o = (SwitchCase) other;
+               return safeSubtreeMatch(node.getExpression(), o.getExpression());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(SwitchStatement node, Object other) {
+               if (!(other instanceof SwitchStatement)) {
+                       return false;
+               }
+               SwitchStatement o = (SwitchStatement) other;
+               return (
+                       safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeListMatch(node.statements(), o.statements()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(SynchronizedStatement node, Object other) {
+               if (!(other instanceof SynchronizedStatement)) {
+                       return false;
+               }
+               SynchronizedStatement o = (SynchronizedStatement) other;
+               return (
+                       safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeMatch(node.getBody(), o.getBody()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.0
+        */
+       public boolean match(TagElement node, Object other) {
+               if (!(other instanceof TagElement)) {
+                       return false;
+               }
+               TagElement o = (TagElement) other;
+               return (
+                               safeEquals(node.getTagName(), o.getTagName())
+                               && safeSubtreeListMatch(node.fragments(), o.fragments()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.0
+        */
+       public boolean match(TextElement node, Object other) {
+               if (!(other instanceof TextElement)) {
+                       return false;
+               }
+               TextElement o = (TextElement) other;
+               return safeEquals(node.getText(), o.getText());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ThisExpression node, Object other) {
+               if (!(other instanceof ThisExpression)) {
+                       return false;
+               }
+               ThisExpression o = (ThisExpression) other;
+               return safeSubtreeMatch(node.getQualifier(), o.getQualifier());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(ThrowStatement node, Object other) {
+               if (!(other instanceof ThrowStatement)) {
+                       return false;
+               }
+               ThrowStatement o = (ThrowStatement) other;
+               return safeSubtreeMatch(node.getExpression(), o.getExpression());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(TryStatement node, Object other) {
+               if (!(other instanceof TryStatement)) {
+                       return false;
+               }
+               TryStatement o = (TryStatement) other;
+               return (
+                       safeSubtreeMatch(node.getBody(), o.getBody())
+                               && safeSubtreeListMatch(node.catchClauses(), o.catchClauses())
+                               && safeSubtreeMatch(node.getFinally(), o.getFinally()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(TypeDeclaration node, Object other) {
+               if (!(other instanceof TypeDeclaration)) {
+                       return false;
+               }
+               TypeDeclaration o = (TypeDeclaration) other;
+               int level = node.getAST().apiLevel;
+               if (level == AST.JLS2_INTERNAL) {
+                       if (node.getModifiers() != o.getModifiers()) {
+                               return false;
+                       }
+                       if (!safeSubtreeMatch(node.internalGetSuperclass(), o.internalGetSuperclass())) {
+                               return false;
+                       }
+                       if (!safeSubtreeListMatch(node.internalSuperInterfaces(), o.internalSuperInterfaces())) {
+                               return false;
+                       }
+               }
+               if (level >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+                               return false;
+                       }
+                       if (!safeSubtreeListMatch(node.typeParameters(), o.typeParameters())) {
+                               return false;
+                       }
+                       if (!safeSubtreeMatch(node.getSuperclassType(), o.getSuperclassType())) {
+                               return false;
+                       }
+                       if (!safeSubtreeListMatch(node.superInterfaceTypes(), o.superInterfaceTypes())) {
+                               return false;
+                       }
+               }
+               return (
+                               (node.isInterface() == o.isInterface())
+                               && safeSubtreeMatch(node.getJavadoc(), o.getJavadoc())
+                               && safeSubtreeMatch(node.getName(), o.getName())
+                               && safeSubtreeListMatch(node.bodyDeclarations(), o.bodyDeclarations()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(TypeDeclarationStatement node, Object other) {
+               if (!(other instanceof TypeDeclarationStatement)) {
+                       return false;
+               }
+               TypeDeclarationStatement o = (TypeDeclarationStatement) other;
+               return safeSubtreeMatch(node.getDeclaration(), o.getDeclaration());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(TypeLiteral node, Object other) {
+               if (!(other instanceof TypeLiteral)) {
+                       return false;
+               }
+               TypeLiteral o = (TypeLiteral) other;
+               return safeSubtreeMatch(node.getType(), o.getType());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(TypeParameter node, Object other) {
+               if (!(other instanceof TypeParameter)) {
+                       return false;
+               }
+               TypeParameter o = (TypeParameter) other;
+               return safeSubtreeMatch(node.getName(), o.getName())
+                               && safeSubtreeListMatch(node.typeBounds(), o.typeBounds());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(VariableDeclarationExpression node, Object other) {
+               if (!(other instanceof VariableDeclarationExpression)) {
+                       return false;
+               }
+               VariableDeclarationExpression o = (VariableDeclarationExpression) other;
+               int level = node.getAST().apiLevel;
+               if (level == AST.JLS2_INTERNAL) {
+                       if (node.getModifiers() != o.getModifiers()) {
+                               return false;
+                       }
+               }
+               if (level >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+                               return false;
+                       }
+               }
+               return safeSubtreeMatch(node.getType(), o.getType())
+                       && safeSubtreeListMatch(node.fragments(), o.fragments());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * <p>
+        * Note that extra array dimensions are compared since they are an
+        * important part of the type of the variable.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(VariableDeclarationFragment node, Object other) {
+               if (!(other instanceof VariableDeclarationFragment)) {
+                       return false;
+               }
+               VariableDeclarationFragment o = (VariableDeclarationFragment) other;
+               return safeSubtreeMatch(node.getName(), o.getName())
+                       && node.getExtraDimensions() == o.getExtraDimensions()
+                       && safeSubtreeMatch(node.getInitializer(), o.getInitializer());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(VariableDeclarationStatement node, Object other) {
+               if (!(other instanceof VariableDeclarationStatement)) {
+                       return false;
+               }
+               VariableDeclarationStatement o = (VariableDeclarationStatement) other;
+               int level = node.getAST().apiLevel;
+               if (level == AST.JLS2_INTERNAL) {
+                       if (node.getModifiers() != o.getModifiers()) {
+                               return false;
+                       }
+               }
+               if (level >= AST.JLS3) {
+                       if (!safeSubtreeListMatch(node.modifiers(), o.modifiers())) {
+                               return false;
+                       }
+               }
+               return safeSubtreeMatch(node.getType(), o.getType())
+                       && safeSubtreeListMatch(node.fragments(), o.fragments());
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        */
+       public boolean match(WhileStatement node, Object other) {
+               if (!(other instanceof WhileStatement)) {
+                       return false;
+               }
+               WhileStatement o = (WhileStatement) other;
+               return (
+                       safeSubtreeMatch(node.getExpression(), o.getExpression())
+                               && safeSubtreeMatch(node.getBody(), o.getBody()));
+       }
+
+       /**
+        * Returns whether the given node and the other object match.
+        * <p>
+        * The default implementation provided by this class tests whether the
+        * other object is a node of the same type with structurally isomorphic
+        * child subtrees. Subclasses may override this method as needed.
+        * </p>
+        * 
+        * @param node the node
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        *   <code>false</code> if they do not match or the other object has a
+        *   different node type or is <code>null</code>
+        * @since 3.1
+        */
+       public boolean match(WildcardType node, Object other) {
+               if (!(other instanceof WildcardType)) {
+                       return false;
+               }
+               WildcardType o = (WildcardType) other;
+               return node.isUpperBound() == o.isUpperBound()
+               && safeSubtreeMatch(node.getBound(), o.getBound());
+       }
+       
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTNode.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTNode.java
new file mode 100644 (file)
index 0000000..a8f2347
--- /dev/null
@@ -0,0 +1,2742 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.core.dom.NaiveASTFlattener;
+
+/**
+ * Abstract superclass of all Abstract Syntax Tree (AST) node types.
+ * <p>
+ * An AST node represents a Java source code construct, such
+ * as a name, type, expression, statement, or declaration.
+ * </p>
+ * <p>
+ * Each AST node belongs to a unique AST instance, called the owning AST.
+ * The children of an AST node always have the same owner as their parent node.
+ * If a node from one AST is to be added to a different AST, the subtree must
+ * be cloned first to ensure that the added nodes have the correct owning AST.
+ * </p>
+ * <p>
+ * When an AST node is part of an AST, it has a unique parent node.
+ * Clients can navigate upwards, from child to parent, as well as downwards,
+ * from parent to child. Newly created nodes are unparented. When an 
+ * unparented node is set as a child of a node (using a 
+ * <code>set<i>CHILD</i></code> method), its parent link is set automatically
+ * and the parent link of the former child is set to <code>null</code>.
+ * For nodes with properties that include a list of children (for example,
+ * <code>Block</code> whose <code>statements</code> property is a list
+ * of statements), adding or removing an element to/for the list property
+ * automatically updates the parent links. These lists support the 
+ * <code>List.set</code> method; however, the constraint that the same
+ * node cannot appear more than once means that this method cannot be used
+ * to swap elements without first removing the node.
+ * </p>
+ * <p>
+ * ASTs must not contain cycles. All operations that could create a cycle
+ * detect this possibility and fail.
+ * </p>
+ * <p>
+ * ASTs do not contain "holes" (missing subtrees). If a node is required to
+ * have a certain property, a syntactically plausible initial value is
+ * always supplied. 
+ * </p>
+ * <p>
+ * The hierarchy of AST node types has some convenient groupings marked
+ * by abstract superclasses:
+ * <ul>
+ * <li>expressions - <code>Expression</code></li>
+ * <li>names - <code>Name</code> (a sub-kind of expression)</li>
+ * <li>statements - <code>Statement</code></li>
+ * <li>types - <code>Type</code></li>
+ * <li>type body declarations - <code>BodyDeclaration</code></li>
+ * </ul>
+ * </p>
+ * <p>
+ * Abstract syntax trees may be hand constructed by clients, using the
+ * <code>new<i>TYPE</i></code> factory methods (see <code>AST</code>) to
+ * create new nodes, and the various <code>set<i>CHILD</i></code> methods
+ * to connect them together.
+ * </p>
+ * <p>
+ * The class {@link ASTParser} parses a string
+ * containing a Java source code and returns an abstract syntax tree
+ * for it. The resulting nodes carry source ranges relating the node back to
+ * the original source characters. The source range covers the construct
+ * as a whole.
+ * </p>
+ * <p>
+ * Each AST node carries bit flags, which may convey additional information about
+ * the node. For instance, the parser uses a flag to indicate a syntax error.
+ * Newly created nodes have no flags set.
+ * </p>
+ * <p>
+ * Each AST node is capable of carrying an open-ended collection of
+ * client-defined properties. Newly created nodes have none. 
+ * <code>getProperty</code> and <code>setProperty</code> are used to access
+ * these properties.
+ * </p>
+ * <p>
+ * AST nodes are thread-safe for readers provided there are no active writers.
+ * If one thread is modifying an AST, including creating new nodes or cloning
+ * existing ones, it is <b>not</b> safe for another thread to read, visit,
+ * write, create, or clone <em>any</em> of the nodes on the same AST.
+ * When synchronization is required, consider using the common AST
+ * object that owns the node; that is, use  
+ * <code>synchronize (node.getAST()) {...}</code>.
+ * </p>
+ * <p>
+ * ASTs also support the visitor pattern; see the class <code>ASTVisitor</code>
+ * for details.
+ * </p>
+ * <p>
+ * Compilation units created by <code>ASTParser</code> from a
+ * source document can be serialized after arbitrary modifications
+ * with minimal loss of original formatting. See 
+ * {@link CompilationUnit#recordModifications()} for details.
+ * See also {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite} for
+ * an alternative way to describe and serialize changes to a
+ * read-only AST.
+ * </p>
+ * 
+ * @see ASTParser
+ * @see ASTVisitor
+ * @since 2.0
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public abstract class ASTNode {
+       /*
+        * INSTRUCTIONS FOR ADDING NEW CONCRETE AST NODE TYPES
+        * 
+        * There are several things that need to be changed when a
+        * new concrete AST node type (call it "FooBar"):
+        * 
+        * 1. Create the FooBar AST node type class.
+        * The most effective way to do this is to copy a similar
+        * existing concrete node class to get a template that
+     * includes all the framework methods that must be implemented.
+        * 
+        * 2. Add node type constant ASTNode.FOO_BAR.
+        * Node constants are numbered consecutively. Add the
+        * constant after the existing ones.
+        * 
+        * 3. Add entry to ASTNode.nodeClassForType(int).
+        * 
+        * 4. Add AST.newFooBar() factory method.
+        * 
+        * 5. Add ASTVisitor.visit(FooBar) and endVisit(FooBar) methods.
+        * 
+        * 6. Add ASTMatcher.match(FooBar,Object) method.
+        * 
+        * 7. Ensure that SimpleName.isDeclaration() covers FooBar
+        * nodes if required.
+        * 
+        * 8. Add NaiveASTFlattener.visit(FooBar) method to illustrate
+        * how these nodes should be serialized.
+        * 
+        * 9. Update the AST test suites.
+        * 
+        * The next steps are to update AST.parse* to start generating
+        * the new type of nodes, and ASTRewrite to serialize them back out.
+        */
+       
+       /**
+        * Node type constant indicating a node of type 
+        * <code>AnonymousClassDeclaration</code>.
+        * @see AnonymousClassDeclaration
+        */
+       public static final int ANONYMOUS_CLASS_DECLARATION = 1;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ArrayAccess</code>.
+        * @see ArrayAccess
+        */
+       public static final int ARRAY_ACCESS = 2;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ArrayCreation</code>.
+        * @see ArrayCreation
+        */
+       public static final int ARRAY_CREATION = 3;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ArrayInitializer</code>.
+        * @see ArrayInitializer
+        */
+       public static final int ARRAY_INITIALIZER = 4;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ArrayType</code>.
+        * @see ArrayType
+        */
+       public static final int ARRAY_TYPE = 5;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>AssertStatement</code>.
+        * @see AssertStatement
+        */
+       public static final int ASSERT_STATEMENT = 6;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>Assignment</code>.
+        * @see Assignment
+        */
+       public static final int ASSIGNMENT = 7;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>Block</code>.
+        * @see Block
+        */
+       public static final int BLOCK = 8;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>BooleanLiteral</code>.
+        * @see BooleanLiteral
+        */
+       public static final int BOOLEAN_LITERAL = 9;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>BreakStatement</code>.
+        * @see BreakStatement
+        */
+       public static final int BREAK_STATEMENT = 10;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>CastExpression</code>.
+        * @see CastExpression
+        */
+       public static final int CAST_EXPRESSION = 11;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>CatchClause</code>.
+        * @see CatchClause
+        */
+       public static final int CATCH_CLAUSE = 12;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>CharacterLiteral</code>.
+        * @see CharacterLiteral
+        */
+       public static final int CHARACTER_LITERAL = 13;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ClassInstanceCreation</code>.
+        * @see ClassInstanceCreation
+        */
+       public static final int CLASS_INSTANCE_CREATION = 14;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>CompilationUnit</code>.
+        * @see CompilationUnit
+        */
+       public static final int COMPILATION_UNIT = 15;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ConditionalExpression</code>.
+        * @see ConditionalExpression
+        */
+       public static final int CONDITIONAL_EXPRESSION = 16;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ConstructorInvocation</code>.
+        * @see ConstructorInvocation
+        */
+       public static final int CONSTRUCTOR_INVOCATION = 17;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ContinueStatement</code>.
+        * @see ContinueStatement
+        */
+       public static final int CONTINUE_STATEMENT = 18;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>DoStatement</code>.
+        * @see DoStatement
+        */
+       public static final int DO_STATEMENT = 19;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>EmptyStatement</code>.
+        * @see EmptyStatement
+        */
+       public static final int EMPTY_STATEMENT = 20;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ExpressionStatement</code>.
+        * @see ExpressionStatement
+        */
+       public static final int EXPRESSION_STATEMENT = 21;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>FieldAccess</code>.
+        * @see FieldAccess
+        */
+       public static final int FIELD_ACCESS = 22;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>FieldDeclaration</code>.
+        * @see FieldDeclaration
+        */
+       public static final int FIELD_DECLARATION = 23;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ForStatement</code>.
+        * @see ForStatement
+        */
+       public static final int FOR_STATEMENT = 24;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>IfStatement</code>.
+        * @see IfStatement
+        */
+       public static final int IF_STATEMENT = 25;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ImportDeclaration</code>.
+        * @see ImportDeclaration
+        */
+       public static final int IMPORT_DECLARATION = 26;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>InfixExpression</code>.
+        * @see InfixExpression
+        */
+       public static final int INFIX_EXPRESSION = 27;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>Initializer</code>.
+        * @see Initializer
+        */
+       public static final int INITIALIZER = 28;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>Javadoc</code>.
+        * @see Javadoc
+        */
+       public static final int JAVADOC = 29;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>LabeledStatement</code>.
+        * @see LabeledStatement
+        */
+       public static final int LABELED_STATEMENT = 30;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>MethodDeclaration</code>.
+        * @see MethodDeclaration
+        */
+       public static final int METHOD_DECLARATION = 31;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>MethodInvocation</code>.
+        * @see MethodInvocation
+        */
+       public static final int METHOD_INVOCATION = 32;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>NullLiteral</code>.
+        * @see NullLiteral
+        */
+       public static final int NULL_LITERAL = 33;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>NumberLiteral</code>.
+        * @see NumberLiteral
+        */
+       public static final int NUMBER_LITERAL = 34;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>PackageDeclaration</code>.
+        * @see PackageDeclaration
+        */
+       public static final int PACKAGE_DECLARATION = 35;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ParenthesizedExpression</code>.
+        * @see ParenthesizedExpression
+        */
+       public static final int PARENTHESIZED_EXPRESSION = 36;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>PostfixExpression</code>.
+        * @see PostfixExpression
+        */
+       public static final int POSTFIX_EXPRESSION = 37;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>PrefixExpression</code>.
+        * @see PrefixExpression
+        */
+       public static final int PREFIX_EXPRESSION = 38;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>PrimitiveType</code>.
+        * @see PrimitiveType
+        */
+       public static final int PRIMITIVE_TYPE = 39;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>QualifiedName</code>.
+        * @see QualifiedName
+        */
+       public static final int QUALIFIED_NAME = 40;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ReturnStatement</code>.
+        * @see ReturnStatement
+        */
+       public static final int RETURN_STATEMENT = 41;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>SimpleName</code>.
+        * @see SimpleName
+        */
+       public static final int SIMPLE_NAME = 42;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>SimpleType</code>.
+        * @see SimpleType
+        */
+       public static final int SIMPLE_TYPE = 43;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>SingleVariableDeclaration</code>.
+        * @see SingleVariableDeclaration
+        */
+       public static final int SINGLE_VARIABLE_DECLARATION = 44;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>StringLiteral</code>.
+        * @see StringLiteral
+        */
+       public static final int STRING_LITERAL = 45;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>SuperConstructorInvocation</code>.
+        * @see SuperConstructorInvocation
+        */
+       public static final int SUPER_CONSTRUCTOR_INVOCATION = 46;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>SuperFieldAccess</code>.
+        * @see SuperFieldAccess
+        */
+       public static final int SUPER_FIELD_ACCESS = 47;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>SuperMethodInvocation</code>.
+        * @see SuperMethodInvocation
+        */
+       public static final int SUPER_METHOD_INVOCATION = 48;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>SwitchCase</code>.
+        * @see SwitchCase
+        */
+       public static final int SWITCH_CASE = 49;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>SwitchStatement</code>.
+        * @see SwitchStatement
+        */
+       public static final int SWITCH_STATEMENT = 50;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>SynchronizedStatement</code>.
+        * @see SynchronizedStatement
+        */
+       public static final int SYNCHRONIZED_STATEMENT = 51;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ThisExpression</code>.
+        * @see ThisExpression
+        */
+       public static final int THIS_EXPRESSION = 52;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ThrowStatement</code>.
+        * @see ThrowStatement
+        */
+       public static final int THROW_STATEMENT = 53;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>TryStatement</code>.
+        * @see TryStatement
+        */
+       public static final int TRY_STATEMENT = 54;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>TypeDeclaration</code>.
+        * @see TypeDeclaration
+        */
+       public static final int TYPE_DECLARATION = 55;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>TypeDeclarationStatement</code>.
+        * @see TypeDeclarationStatement
+        */
+       public static final int TYPE_DECLARATION_STATEMENT = 56;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>TypeLiteral</code>.
+        * @see TypeLiteral
+        */
+       public static final int TYPE_LITERAL = 57;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>VariableDeclarationExpression</code>.
+        * @see VariableDeclarationExpression
+        */
+       public static final int VARIABLE_DECLARATION_EXPRESSION = 58;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>VariableDeclarationFragment</code>.
+        * @see VariableDeclarationFragment
+        */
+       public static final int VARIABLE_DECLARATION_FRAGMENT = 59;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>VariableDeclarationStatement</code>.
+        * @see VariableDeclarationStatement
+        */
+       public static final int VARIABLE_DECLARATION_STATEMENT = 60;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>WhileStatement</code>.
+        * @see WhileStatement
+        */
+       public static final int WHILE_STATEMENT = 61;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>InstanceofExpression</code>.
+        * @see InstanceofExpression
+        */
+       public static final int INSTANCEOF_EXPRESSION = 62;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>LineComment</code>.
+        * @see LineComment
+        * @since 3.0
+        */
+       public static final int LINE_COMMENT = 63;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>BlockComment</code>.
+        * @see BlockComment
+        * @since 3.0
+        */
+       public static final int BLOCK_COMMENT = 64;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>TagElement</code>.
+        * @see TagElement
+        * @since 3.0
+        */
+       public static final int TAG_ELEMENT = 65;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>TextElement</code>.
+        * @see TextElement
+        * @since 3.0
+        */
+       public static final int TEXT_ELEMENT = 66;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>MemberRef</code>.
+        * @see MemberRef
+        * @since 3.0
+        */
+       public static final int MEMBER_REF = 67;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>MethodRef</code>.
+        * @see MethodRef
+        * @since 3.0
+        */
+       public static final int METHOD_REF = 68;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>MethodRefParameter</code>.
+        * @see MethodRefParameter
+        * @since 3.0
+        */
+       public static final int METHOD_REF_PARAMETER = 69;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>EnhancedForStatement</code>.
+        * @see EnhancedForStatement
+        * @since 3.1
+        */
+       public static final int ENHANCED_FOR_STATEMENT = 70;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>EnumDeclaration</code>.
+        * @see EnumDeclaration
+        * @since 3.1
+        */
+       public static final int ENUM_DECLARATION = 71;
+       
+       /**
+        * Node type constant indicating a node of type 
+        * <code>EnumConstantDeclaration</code>.
+        * @see EnumConstantDeclaration
+        * @since 3.1
+        */
+       public static final int ENUM_CONSTANT_DECLARATION = 72;
+       
+       /**
+        * Node type constant indicating a node of type 
+        * <code>TypeParameter</code>.
+        * @see TypeParameter
+        * @since 3.1
+        */
+       public static final int TYPE_PARAMETER = 73;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>ParameterizedType</code>.
+        * @see ParameterizedType
+        * @since 3.1
+        */
+       public static final int PARAMETERIZED_TYPE = 74;
+
+       /**
+        * Node type constant indicating a node of type 
+        * <code>QualifiedType</code>.
+        * @see QualifiedType
+        * @since 3.1
+        */
+       public static final int QUALIFIED_TYPE = 75;
+       
+       /**
+        * Node type constant indicating a node of type 
+        * <code>WildcardType</code>.
+        * @see WildcardType
+        * @since 3.1
+        */
+       public static final int WILDCARD_TYPE = 76;
+       
+       /**
+        * Node type constant indicating a node of type 
+        * <code>NormalAnnotation</code>.
+        * @see NormalAnnotation
+        * @since 3.1
+        */
+       public static final int NORMAL_ANNOTATION = 77;
+       
+       /**
+        * Node type constant indicating a node of type 
+        * <code>MarkerAnnotation</code>.
+        * @see MarkerAnnotation
+        * @since 3.1
+        */
+       public static final int MARKER_ANNOTATION = 78;
+       
+       /**
+        * Node type constant indicating a node of type 
+        * <code>SingleMemberAnnotation</code>.
+        * @see SingleMemberAnnotation
+        * @since 3.1
+        */
+       public static final int SINGLE_MEMBER_ANNOTATION = 79;
+       
+       /**
+        * Node type constant indicating a node of type 
+        * <code>MemberValuePair</code>.
+        * @see MemberValuePair
+        * @since 3.1
+        */
+       public static final int MEMBER_VALUE_PAIR = 80;
+       
+       /**
+        * Node type constant indicating a node of type 
+        * <code>AnnotationTypeDeclaration</code>.
+        * @see AnnotationTypeDeclaration
+        * @since 3.1
+        */
+       public static final int ANNOTATION_TYPE_DECLARATION = 81;
+       
+       /**
+        * Node type constant indicating a node of type 
+        * <code>AnnotationTypeMemberDeclaration</code>.
+        * @see AnnotationTypeMemberDeclaration
+        * @since 3.1
+        */
+       public static final int ANNOTATION_TYPE_MEMBER_DECLARATION = 82;
+       
+       /**
+        * Node type constant indicating a node of type 
+        * <code>Modifier</code>.
+        * @see Modifier
+        * @since 3.1
+        */
+       public static final int MODIFIER = 83;
+       
+       /**
+        * Returns the node class for the corresponding node type.
+        * 
+        * @param nodeType AST node type
+        * @return the corresponding <code>ASTNode</code> subclass
+        * @exception IllegalArgumentException if <code>nodeType</code> is 
+        * not a legal AST node type
+        * @see #getNodeType()
+        * @since 3.0
+        */
+       public static Class nodeClassForType(int nodeType) {
+               switch (nodeType) {
+                       case ANNOTATION_TYPE_DECLARATION :
+                               return AnnotationTypeDeclaration.class;
+                       case ANNOTATION_TYPE_MEMBER_DECLARATION :
+                               return AnnotationTypeMemberDeclaration.class;
+                       case ANONYMOUS_CLASS_DECLARATION :
+                               return AnonymousClassDeclaration.class;
+                       case ARRAY_ACCESS :
+                               return ArrayAccess.class;
+                       case ARRAY_CREATION :
+                               return ArrayCreation.class;
+                       case ARRAY_INITIALIZER :
+                               return ArrayInitializer.class;
+                       case ARRAY_TYPE :
+                               return ArrayType.class;
+                       case ASSERT_STATEMENT :
+                               return AssertStatement.class;
+                       case ASSIGNMENT :
+                               return Assignment.class;
+                       case BLOCK :
+                               return Block.class;
+                       case BLOCK_COMMENT :
+                               return BlockComment.class;
+                       case BOOLEAN_LITERAL :
+                               return BooleanLiteral.class;
+                       case BREAK_STATEMENT :
+                               return BreakStatement.class;
+                       case CAST_EXPRESSION :
+                               return CastExpression.class;
+                       case CATCH_CLAUSE :
+                               return CatchClause.class;
+                       case CHARACTER_LITERAL :
+                               return CharacterLiteral.class;
+                       case CLASS_INSTANCE_CREATION :
+                               return ClassInstanceCreation.class;
+                       case COMPILATION_UNIT :
+                               return CompilationUnit.class;
+                       case CONDITIONAL_EXPRESSION :
+                               return ConditionalExpression.class;
+                       case CONSTRUCTOR_INVOCATION :
+                               return ConstructorInvocation.class;
+                       case CONTINUE_STATEMENT :
+                               return ContinueStatement.class;
+                       case DO_STATEMENT :
+                               return DoStatement.class;
+                       case EMPTY_STATEMENT :
+                               return EmptyStatement.class;
+                       case ENHANCED_FOR_STATEMENT :
+                               return EnhancedForStatement.class;
+                       case ENUM_CONSTANT_DECLARATION :
+                               return EnumConstantDeclaration.class;
+                       case ENUM_DECLARATION :
+                               return EnumDeclaration.class;
+                       case EXPRESSION_STATEMENT :
+                               return ExpressionStatement.class;
+                       case FIELD_ACCESS :
+                               return FieldAccess.class;
+                       case FIELD_DECLARATION :
+                               return FieldDeclaration.class;
+                       case FOR_STATEMENT :
+                               return ForStatement.class;
+                       case IF_STATEMENT :
+                               return IfStatement.class;
+                       case IMPORT_DECLARATION :
+                               return ImportDeclaration.class;
+                       case INFIX_EXPRESSION :
+                               return InfixExpression.class;
+                       case INITIALIZER :
+                               return Initializer.class;
+                       case INSTANCEOF_EXPRESSION :
+                               return InstanceofExpression.class;
+                       case JAVADOC :
+                               return Javadoc.class;
+                       case LABELED_STATEMENT :
+                               return LabeledStatement.class;
+                       case LINE_COMMENT :
+                               return LineComment.class;
+                       case MARKER_ANNOTATION :
+                               return MarkerAnnotation.class;
+                       case MEMBER_REF :
+                               return MemberRef.class;
+                       case MEMBER_VALUE_PAIR :
+                               return MemberValuePair.class;
+                       case METHOD_DECLARATION :
+                               return MethodDeclaration.class;
+                       case METHOD_INVOCATION :
+                               return MethodInvocation.class;
+                       case METHOD_REF :
+                               return MethodRef.class;
+                       case METHOD_REF_PARAMETER :
+                               return MethodRefParameter.class;
+                       case MODIFIER :
+                               return Modifier.class;
+                       case NORMAL_ANNOTATION :
+                               return NormalAnnotation.class;
+                       case NULL_LITERAL :
+                               return NullLiteral.class;
+                       case NUMBER_LITERAL :
+                               return NumberLiteral.class;
+                       case PACKAGE_DECLARATION :
+                               return PackageDeclaration.class;
+                       case PARAMETERIZED_TYPE :
+                               return ParameterizedType.class;
+                       case PARENTHESIZED_EXPRESSION :
+                               return ParenthesizedExpression.class;
+                       case POSTFIX_EXPRESSION :
+                               return PostfixExpression.class;
+                       case PREFIX_EXPRESSION :
+                               return PrefixExpression.class;
+                       case PRIMITIVE_TYPE :
+                               return PrimitiveType.class;
+                       case QUALIFIED_NAME :
+                               return QualifiedName.class;
+                       case QUALIFIED_TYPE :
+                               return QualifiedType.class;
+                       case RETURN_STATEMENT :
+                               return ReturnStatement.class;
+                       case SIMPLE_NAME :
+                               return SimpleName.class;
+                       case SIMPLE_TYPE :
+                               return SimpleType.class;
+                       case SINGLE_MEMBER_ANNOTATION :
+                               return SingleMemberAnnotation.class;
+                       case SINGLE_VARIABLE_DECLARATION :
+                               return SingleVariableDeclaration.class;
+                       case STRING_LITERAL :
+                               return StringLiteral.class;
+                       case SUPER_CONSTRUCTOR_INVOCATION :
+                               return SuperConstructorInvocation.class;
+                       case SUPER_FIELD_ACCESS :
+                               return SuperFieldAccess.class;
+                       case SUPER_METHOD_INVOCATION :
+                               return SuperMethodInvocation.class;
+                       case SWITCH_CASE:
+                               return SwitchCase.class;
+                       case SWITCH_STATEMENT :
+                               return SwitchStatement.class;
+                       case SYNCHRONIZED_STATEMENT :
+                               return SynchronizedStatement.class;
+                       case TAG_ELEMENT :
+                               return TagElement.class;
+                       case TEXT_ELEMENT :
+                               return TextElement.class;
+                       case THIS_EXPRESSION :
+                               return ThisExpression.class;
+                       case THROW_STATEMENT :
+                               return ThrowStatement.class;
+                       case TRY_STATEMENT :
+                               return TryStatement.class;
+                       case TYPE_DECLARATION :
+                               return TypeDeclaration.class;
+                       case TYPE_DECLARATION_STATEMENT :
+                               return TypeDeclarationStatement.class;
+                       case TYPE_LITERAL :
+                               return TypeLiteral.class;
+                       case TYPE_PARAMETER :
+                               return TypeParameter.class;
+                       case VARIABLE_DECLARATION_EXPRESSION :
+                               return VariableDeclarationExpression.class;
+                       case VARIABLE_DECLARATION_FRAGMENT :
+                               return VariableDeclarationFragment.class;
+                       case VARIABLE_DECLARATION_STATEMENT :
+                               return VariableDeclarationStatement.class;
+                       case WHILE_STATEMENT :
+                               return WhileStatement.class;
+                       case WILDCARD_TYPE :
+                               return WildcardType.class;
+               }
+               throw new IllegalArgumentException();
+       }
+       
+       /**
+        * Owning AST.
+     * <p>
+     * N.B. This ia a private field, but declared as package-visible
+     * for more efficient access from inner classes.
+     * </p>
+        */
+       final AST ast;
+       
+       /**
+        * Parent AST node, or <code>null</code> if this node is a root.
+        * Initially <code>null</code>.
+        */
+       private ASTNode parent = null;
+       
+       /**
+        * An unmodifiable empty map (used to implement <code>properties()</code>).
+        */
+       private static final Map UNMODIFIABLE_EMPTY_MAP
+               = Collections.unmodifiableMap(new HashMap(1));
+       
+       /**
+        * Primary field used in representing node properties efficiently.
+        * If <code>null</code>, this node has no properties.
+        * If a <code>String</code>, this is the name of this node's sole property,
+        * and <code>property2</code> contains its value.
+        * If a <code>HashMap</code>, this is the table of property name-value
+        * mappings; <code>property2</code>, if non-null is its unmodifiable
+        * equivalent.
+        * Initially <code>null</code>.
+        * 
+        * @see #property2
+        */
+       private Object property1 = null;
+       
+       /**
+        * Auxillary field used in representing node properties efficiently.
+        * 
+        * @see #property1
+        */
+       private Object property2 = null;
+       
+       /**
+        * A character index into the original source string, 
+        * or <code>-1</code> if no source position information is available
+        * for this node; <code>-1</code> by default.
+        */
+       private int startPosition = -1;
+
+       /**
+        * A character length, or <code>0</code> if no source position
+        * information is recorded for this node; <code>0</code> by default.
+        */
+       private int length = 0;
+       
+       /**
+        * Flag constant (bit mask, value 1) indicating that there is something
+        * not quite right with this AST node.
+        * <p>
+        * The standard parser (<code>ASTParser</code>) sets this
+        * flag on a node to indicate a syntax error detected in the vicinity.
+        * </p>
+        */
+       public static final int MALFORMED = 1;
+
+       /**
+        * Flag constant (bit mask, value 2) indicating that this is a node
+        * that was created by the parser (as opposed to one created by another
+        * party).
+        * <p>
+        * The standard parser (<code>ASTParser</code>) sets this
+        * flag on the nodes it creates.
+        * </p>
+        * @since 3.0
+        */
+       public static final int ORIGINAL = 2;
+
+       /**
+        * Flag constant (bit mask, value 4) indicating that this node
+        * is unmodifiable. When a node is marked unmodifiable, the
+        * following operations result in a runtime exception:
+        * <ul>
+        * <li>Change a simple property of this node.</li>
+        * <li>Add or remove a child node from this node.</li>
+        * <li>Parent (or reparent) this node.</li>
+        * </ul>
+        * <p>
+        * The standard parser (<code>ASTParser</code>) does not set
+        * this flag on the nodes it creates. However, clients may set
+        * this flag on a node to prevent further modification of the
+        * its structural properties.
+        * </p>
+        * @since 3.0
+        */
+       public static final int PROTECT = 4;
+
+       /**
+        * Flag constant (bit mask, value 8) indicating that this node
+        * or a part of this node is recovered from source that contains
+        * a syntax error detected in the vicinity.
+        * <p>
+        * The standard parser (<code>ASTParser</code>) sets this
+        * flag on a node to indicate a recovered node.
+        * </p>
+        * @since 3.2
+        */
+       public static final int RECOVERED = 8;
+       
+       /**
+        * int containing the node type in the top 16 bits and
+        * flags in the bottom 16 bits; none set by default.
+     * <p>
+     * N.B. This is a private field, but declared as package-visible
+     * for more efficient access from inner classes.
+     * </p>
+        * 
+        * @see #MALFORMED
+        */
+       int typeAndFlags = 0;
+               
+       /**
+        * Property of parent in which this node is a child, or <code>null</code>
+        * if this node is a root. Initially <code>null</code>.
+        * 
+        * @see #getLocationInParent
+        * @since 3.0
+        */
+       private StructuralPropertyDescriptor location = null;
+       
+       /** Internal convenience constant indicating that there is definite risk of cycles.
+        * @since 3.0
+        */ 
+       static final boolean CYCLE_RISK = true;
+       
+       /** Internal convenience constant indicating that there is no risk of cycles.
+        * @since 3.0
+        */ 
+       static final boolean NO_CYCLE_RISK = false;
+       
+       /** Internal convenience constant indicating that a structural property is mandatory.
+        * @since 3.0
+        */ 
+       static final boolean MANDATORY = true;
+       
+       /** Internal convenience constant indicating that a structural property is optional.
+        * @since 3.0
+        */ 
+       static final boolean OPTIONAL = false;
+       
+       /**
+        * A specialized implementation of a list of ASTNodes. The
+        * implementation is based on an ArrayList.
+        */ 
+       class NodeList extends AbstractList {
+               
+               /**
+                * The underlying list in which the nodes of this list are
+                * stored (element type: <code>ASTNode</code>).
+                * <p>
+                * Be stingy on storage - assume that list will be empty.
+                * </p>
+                * <p>
+                * This field declared default visibility (rather than private)
+                * so that accesses from <code>NodeList.Cursor</code> do not require
+                * a synthetic accessor method.
+                * </p>
+                */
+               ArrayList store = new ArrayList(0);
+               
+               /**
+                * The property descriptor for this list.
+                */
+               ChildListPropertyDescriptor propertyDescriptor;
+               
+               /**
+                * A cursor for iterating over the elements of the list.
+                * Does not lose its position if the list is changed during
+                * the iteration.
+                */
+               class Cursor implements Iterator {
+                       /**
+                        * The position of the cursor between elements. If the value
+                        * is N, then the cursor sits between the element at positions
+                        * N-1 and N. Initially just before the first element of the
+                        * list.
+                        */
+                       private int position = 0;
+                       
+                       /* (non-Javadoc)
+                        * Method declared on <code>Iterator</code>.
+                        */
+                       public boolean hasNext() {
+                               return this.position < NodeList.this.store.size();
+                       }
+                       
+                       /* (non-Javadoc)
+                        * Method declared on <code>Iterator</code>.
+                        */
+                       public Object next() {
+                               Object result = NodeList.this.store.get(this.position);
+                               this.position++;
+                               return result;
+                   }
+                       
+                       /* (non-Javadoc)
+                        * Method declared on <code>Iterator</code>.
+                        */
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+                       
+                       /**
+                        * Adjusts this cursor to accomodate an add/remove at the given
+                        * index.
+                        * 
+                        * @param index the position at which the element was added
+                        *    or removed
+                        * @param delta +1 for add, and -1 for remove
+                        */
+                       void update(int index, int delta) {
+                               if (this.position > index) {
+                                       // the cursor has passed the added or removed element
+                                       this.position += delta;
+                               }
+                       }
+               }
+
+               /**
+                * A list of currently active cursors (element type:
+                * <code>Cursor</code>), or <code>null</code> if there are no
+                * active cursors.
+                * <p>
+                * It is important for storage considerations to maintain the
+                * null-means-empty invariant; otherwise, every NodeList instance
+                * will waste a lot of space. A cursor is needed only for the duration
+                * of a visit to the child nodes. Under normal circumstances, only a 
+                * single cursor is needed; multiple cursors are only required if there
+                * are multiple visits going on at the same time.
+                * </p>
+                */
+               private List cursors = null;
+
+               /**
+                * Creates a new empty list of nodes owned by this node.
+                * This node will be the common parent of all nodes added to 
+                * this list.
+                * 
+                * @param property the property descriptor
+                * @since 3.0
+                */
+               NodeList(ChildListPropertyDescriptor property) {
+                       super();
+                       this.propertyDescriptor = property;
+               }
+       
+               /* (non-javadoc)
+                * @see java.util.AbstractCollection#size()
+                */
+               public int size() {
+                       return this.store.size();
+               }
+       
+               /* (non-javadoc)
+                * @see AbstractList#get(int)
+                */
+               public Object get(int index) {
+                       return this.store.get(index);
+               }
+       
+               /* (non-javadoc)
+                * @see List#set(int, java.lang.Object)
+                */
+               public Object set(int index, Object element) {
+                   if (element == null) {
+                       throw new IllegalArgumentException();
+                   }
+                       if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
+                               // this node is protected => cannot gain or lose children
+                               throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+                       }
+                       // delink old child from parent, and link new child to parent
+                       ASTNode newChild = (ASTNode) element;
+                       ASTNode oldChild = (ASTNode) this.store.get(index);
+                       if (oldChild == newChild) {
+                               return oldChild;
+                       }
+                       if ((oldChild.typeAndFlags & PROTECT) != 0) {
+                               // old child is protected => cannot be unparented
+                               throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+                       }
+                       ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
+                       ASTNode.this.ast.preReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
+                       
+                       Object result = this.store.set(index, newChild);
+                       // n.b. setParent will call ast.modifying()
+                       oldChild.setParent(null, null);
+                       newChild.setParent(ASTNode.this, this.propertyDescriptor);
+                       ASTNode.this.ast.postReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor);
+                       return result;
+               }
+               
+               /* (non-javadoc)
+                * @see List#add(int, java.lang.Object)
+                */
+               public void add(int index, Object element) {
+                   if (element == null) {
+                       throw new IllegalArgumentException();
+                   }
+                       if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
+                               // this node is protected => cannot gain or lose children
+                               throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+                       }
+                       // link new child to parent
+                       ASTNode newChild = (ASTNode) element;
+                       ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType);
+                       ASTNode.this.ast.preAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
+                       
+                       
+                       this.store.add(index, element);
+                       updateCursors(index, +1);
+                       // n.b. setParent will call ast.modifying()
+                       newChild.setParent(ASTNode.this, this.propertyDescriptor);
+                       ASTNode.this.ast.postAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor);
+               }
+               
+               /* (non-javadoc)
+                * @see List#remove(int)
+                */
+               public Object remove(int index) {
+                       if ((ASTNode.this.typeAndFlags & PROTECT) != 0) {
+                               // this node is protected => cannot gain or lose children
+                               throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+                       }
+                       // delink old child from parent
+                       ASTNode oldChild = (ASTNode) this.store.get(index);
+                       if ((oldChild.typeAndFlags & PROTECT) != 0) {
+                               // old child is protected => cannot be unparented
+                               throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+                       }
+                       
+                       ASTNode.this.ast.preRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
+                       // n.b. setParent will call ast.modifying()
+                       oldChild.setParent(null, null);
+                       Object result = this.store.remove(index);
+                       updateCursors(index, -1);
+                       ASTNode.this.ast.postRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor);
+                       return result;
+
+               }
+               
+               /**
+                * Allocate a cursor to use for a visit. The client must call
+                * <code>releaseCursor</code> when done.
+                * <p>
+                * This method is internally synchronized on this NodeList.
+                * It is thread-safe to create a cursor.
+                * </p>
+                * 
+                * @return a new cursor positioned before the first element 
+                *    of the list
+                */
+               Cursor newCursor() {
+                       synchronized (this) {
+                               // serialize cursor management on this NodeList
+                               if (this.cursors == null) {
+                                       // convert null to empty list
+                                       this.cursors = new ArrayList(1);
+                               }
+                               Cursor result = new Cursor();
+                               this.cursors.add(result);
+                               return result;
+                       }
+               }
+               
+               /**
+                * Releases the given cursor at the end of a visit.
+                * <p>
+                * This method is internally synchronized on this NodeList.
+                * It is thread-safe to release a cursor.
+                * </p>
+                * 
+                * @param cursor the cursor
+                */
+               void releaseCursor(Cursor cursor) {
+                       synchronized (this) {
+                               // serialize cursor management on this NodeList
+                               this.cursors.remove(cursor);
+                               if (this.cursors.isEmpty()) {
+                                       // important: convert empty list back to null
+                                       // otherwise the node will hang on to needless junk
+                                       this.cursors = null;
+                               }
+                       }
+               }
+
+               /**
+                * Adjusts all cursors to accomodate an add/remove at the given
+                * index.
+                * <p>
+                * This method is only used when the list is being modified.
+                * The AST is not thread-safe if any of the clients are modifying it.
+                * </p>
+                * 
+                * @param index the position at which the element was added
+                *    or removed
+                * @param delta +1 for add, and -1 for remove
+                */
+               private void updateCursors(int index, int delta) {
+                       if (this.cursors == null) {
+                               // there are no cursors to worry about
+                               return;
+                       }
+                       for (Iterator it = this.cursors.iterator(); it.hasNext(); ) {
+                               Cursor c = (Cursor) it.next();
+                               c.update(index, delta);
+                       }
+               }
+               
+               /**
+                * Returns an estimate of the memory footprint of this node list 
+                * instance in bytes.
+            * <ul>
+            * <li>1 object header for the NodeList instance</li>
+            * <li>5 4-byte fields of the NodeList instance</li>
+            * <li>0 for cursors since null unless walk in progress</li>
+            * <li>1 object header for the ArrayList instance</li>
+            * <li>2 4-byte fields of the ArrayList instance</li>
+            * <li>1 object header for an Object[] instance</li>
+            * <li>4 bytes in array for each element</li>
+            * </ul>
+                * 
+                * @return the size of this node list in bytes
+                */
+               int memSize() {
+                       int result = HEADERS + 5 * 4;
+                       result += HEADERS + 2 * 4;
+                       result += HEADERS + 4 * size();
+                       return result;
+               }
+
+               /**
+                * Returns an estimate of the memory footprint in bytes of this node
+                * list and all its subtrees.
+                * 
+                * @return the size of this list of subtrees in bytes
+                */
+               int listSize() {
+                       int result = memSize();
+                       for (Iterator it = iterator(); it.hasNext(); ) {
+                               ASTNode child = (ASTNode) it.next();
+                               result += child.treeSize();
+                       }
+                       return result;
+               }
+       }
+
+       /**
+        * Creates a new AST node owned by the given AST. Once established,
+        * the relationship between an AST node and its owning AST does not change
+        * over the lifetime of the node. The new node has no parent node,
+        * and no properties.
+        * <p>
+        * N.B. This constructor is package-private; all subclasses my be 
+        * declared in the same package; clients are unable to declare 
+        * additional subclasses.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ASTNode(AST ast) {
+               if (ast == null) {
+                       throw new IllegalArgumentException();
+               }
+               
+               this.ast = ast;
+               setNodeType(getNodeType0());
+               setFlags(ast.getDefaultNodeFlag());
+               // setFlags calls modifying();
+       }
+       
+       /**
+        * Returns this node's AST.
+        * <p>
+        * Note that the relationship between an AST node and its owing AST does
+        * not change over the lifetime of a node.
+        * </p>
+        * 
+        * @return the AST that owns this node
+        */ 
+       public final AST getAST() {
+               return this.ast;
+       }
+       
+       /**
+        * Returns this node's parent node, or <code>null</code> if this is the
+        * root node.
+        * <p>
+        * Note that the relationship between an AST node and its parent node
+        * may change over the lifetime of a node.
+        * </p>
+        * 
+        * @return the parent of this node, or <code>null</code> if none
+        */ 
+       public final ASTNode getParent() {
+               return this.parent;
+       }
+               
+       /**
+        * Returns the location of this node within its parent,
+        * or <code>null</code> if this is a root node.
+        * <p>
+        * <pre>
+        * ASTNode node = ...;
+        * ASTNode parent = node.getParent();
+        * StructuralPropertyDescriptor location = node.getLocationInParent();
+        * assert (parent != null) == (location != null);
+        * if ((location != null) && location.isChildProperty())
+        *    assert parent.getStructuralProperty(location) == node;
+        * if ((location != null) && location.isChildListProperty())
+        *    assert ((List) parent.getStructuralProperty(location)).contains(node);
+        * </pre>
+        * </p>
+        * <p>
+        * Note that the relationship between an AST node and its parent node
+        * may change over the lifetime of a node.
+        * </p>
+        * 
+        * @return the location of this node in its parent, 
+        * or <code>null</code> if this node has no parent
+        * @since 3.0
+        */ 
+       public final StructuralPropertyDescriptor getLocationInParent() {
+               return this.location;
+       }
+               
+       /**
+        * Returns the root node at or above this node; returns this node if 
+        * it is a root.
+        * 
+        * @return the root node at or above this node
+        */ 
+       public final ASTNode getRoot() {
+               ASTNode candidate = this;
+               while (true) {
+                       ASTNode p = candidate.getParent();
+                       if (p == null) {
+                               // candidate has no parent - that's the guy
+                               return candidate;
+                       }
+                       candidate = p;
+               }
+       }
+       
+       /**
+        * Returns the value of the given structural property for this node. The value
+        * returned depends on the kind of property:
+        * <ul>
+        * <li>{@link SimplePropertyDescriptor} - the value of the given simple property,
+        * or <code>null</code> if none; primitive values are "boxed"</li>
+        * <li>{@link ChildPropertyDescriptor} - the child node (type <code>ASTNode</code>),
+        * or <code>null</code> if none</li>
+        * <li>{@link ChildListPropertyDescriptor} - the list (element type: {@link ASTNode})</li>
+        * </ul>
+        * 
+        * @param property the property
+        * @return the value, or <code>null</code> if none
+        * @exception RuntimeException if this node does not have the given property
+        * @since 3.0
+        */
+       public final Object getStructuralProperty(StructuralPropertyDescriptor property) {
+               if (property instanceof SimplePropertyDescriptor) {
+                       SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
+                       if (p.getValueType() == int.class) {
+                               int result = internalGetSetIntProperty(p, true, 0);
+                               return new Integer(result);
+                       } else if (p.getValueType() == boolean.class) {
+                               boolean result = internalGetSetBooleanProperty(p, true, false);
+                               return Boolean.valueOf(result);
+                       } else {
+                               return internalGetSetObjectProperty(p, true, null);
+                       }
+               }
+               if (property instanceof ChildPropertyDescriptor) {
+                       return internalGetSetChildProperty((ChildPropertyDescriptor) property, true, null);
+               }
+               if (property instanceof ChildListPropertyDescriptor) {
+                       return internalGetChildListProperty((ChildListPropertyDescriptor) property);
+               }
+               throw new IllegalArgumentException();
+       }
+       
+       /**
+        * Sets the value of the given structural property for this node. The value
+        * passed depends on the kind of property:
+        * <ul>
+        * <li>{@link SimplePropertyDescriptor} - the new value of the given simple property,
+        * or <code>null</code> if none; primitive values are "boxed"</li>
+        * <li>{@link ChildPropertyDescriptor} - the new child node (type <code>ASTNode</code>),
+        * or <code>null</code> if none</li>
+        * <li>{@link ChildListPropertyDescriptor} - not allowed</li>
+        * </ul>
+        * 
+        * @param property the property
+        * @param value the property value
+        * @exception RuntimeException if this node does not have the
+        * given property, or if the given property cannot be set
+        * @since 3.0
+        */
+       public final void setStructuralProperty(StructuralPropertyDescriptor property, Object value) {
+               if (property instanceof SimplePropertyDescriptor) {
+                       SimplePropertyDescriptor p = (SimplePropertyDescriptor) property;
+                       if (p.getValueType() == int.class) {
+                               int arg = ((Integer) value).intValue();
+                               internalGetSetIntProperty(p, false, arg);
+                               return;
+                       } else if (p.getValueType() == boolean.class) {
+                               boolean arg = ((Boolean) value).booleanValue();
+                               internalGetSetBooleanProperty(p, false, arg);
+                               return;
+                       } else {
+                               if (value == null && p.isMandatory()) {
+                                       throw new IllegalArgumentException();
+                               }
+                               internalGetSetObjectProperty(p, false, value);
+                               return;
+                       }
+               }
+               if (property instanceof ChildPropertyDescriptor) {
+                       ChildPropertyDescriptor p = (ChildPropertyDescriptor) property;
+                       ASTNode child = (ASTNode) value;
+                       if (child == null && p.isMandatory()) {
+                               throw new IllegalArgumentException();
+                       }
+                       internalGetSetChildProperty(p, false, child);
+                       return;
+               }
+               if (property instanceof ChildListPropertyDescriptor) {
+                       throw new IllegalArgumentException("Cannot set the list of child list property");  //$NON-NLS-1$
+               }
+       }
+
+       /**
+        * Sets the value of the given int-valued property for this node.
+        * The default implementation of this method throws an exception explaining
+        * that this node does not have such a property. This method should be
+        * extended in subclasses that have at leasy one simple property whose value
+        * type is int.
+        * 
+        * @param property the property
+        * @param get <code>true</code> for a get operation, and 
+        * <code>false</code> for a set operation
+        * @param value the new property value; ignored for get operations
+        * @return the value; always returns
+        * <code>0</code> for set operations
+        * @exception RuntimeException if this node does not have the 
+        * given property, or if the given value cannot be set as specified
+        * @since 3.0
+        */
+       int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+               throw new RuntimeException("Node does not have this property");  //$NON-NLS-1$
+       }
+       
+       /**
+        * Sets the value of the given boolean-valued property for this node.
+        * The default implementation of this method throws an exception explaining
+        * that this node does not have such a property. This method should be
+        * extended in subclasses that have at leasy one simple property whose value
+        * type is boolean.
+        * 
+        * @param property the property
+        * @param get <code>true</code> for a get operation, and 
+        * <code>false</code> for a set operation
+        * @param value the new property value; ignored for get operations
+        * @return the value; always returns
+        * <code>false</code> for set operations
+        * @exception RuntimeException if this node does not have the 
+        * given property, or if the given value cannot be set as specified
+        * @since 3.0
+        */
+       boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+               throw new RuntimeException("Node does not have this property");  //$NON-NLS-1$
+       }
+       
+       /**
+        * Sets the value of the given property for this node.
+        * The default implementation of this method throws an exception explaining
+        * that this node does not have such a property. This method should be
+        * extended in subclasses that have at leasy one simple property whose value
+        * type is a reference type.
+        * 
+        * @param property the property
+        * @param get <code>true</code> for a get operation, and 
+        * <code>false</code> for a set operation
+        * @param value the new property value, or <code>null</code> if none;
+        * ignored for get operations
+        * @return the value, or <code>null</code> if none; always returns
+        * <code>null</code> for set operations
+        * @exception RuntimeException if this node does not have the 
+        * given property, or if the given value cannot be set as specified
+        * @since 3.0
+        */
+       Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               throw new RuntimeException("Node does not have this property");  //$NON-NLS-1$
+       }
+
+       /**
+        * Sets the child value of the given property for this node.
+        * The default implementation of this method throws an exception explaining
+        * that this node does not have such a property. This method should be
+        * extended in subclasses that have at leasy one child property.
+        * 
+        * @param property the property
+        * @param get <code>true</code> for a get operation, and 
+        * <code>false</code> for a set operation
+        * @param child the new child value, or <code>null</code> if none;
+        * always <code>null</code> for get operations
+        * @return the child, or <code>null</code> if none; always returns
+        * <code>null</code> for set operations
+        * @exception RuntimeException if this node does not have the
+        * given property, or if the given child cannot be set as specified
+        * @since 3.0
+        */
+       ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               throw new RuntimeException("Node does not have this property");  //$NON-NLS-1$
+       }
+       
+       /**
+        * Returns the list value of the given property for this node.
+        * The default implementation of this method throws an exception explaining
+        * that this noed does not have such a property. This method should be
+        * extended in subclasses that have at leasy one child list property.
+        * 
+        * @param property the property
+        * @return the list (element type: {@link ASTNode})
+        * @exception RuntimeException if the given node does not have the
+        * given property
+        * @since 3.0
+        */
+       List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               throw new RuntimeException("Node does not have this property");  //$NON-NLS-1$
+       }
+       
+       /**
+        * Returns a list of structural property descriptors for nodes of the
+        * same type as this node. Clients must not modify the result.
+        * <p>
+        * Note that property descriptors are a meta-level mechanism
+        * for manipulating ASTNodes in a generic way. They are
+        * unrelated to <code>get/setProperty</code>.
+        * </p>
+        * 
+        * @return a list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor})
+        * @since 3.0
+        */
+       public final List structuralPropertiesForType() {
+               return internalStructuralPropertiesForType(this.ast.apiLevel);
+       }
+       
+       /**
+        * Returns a list of property descriptors for this node type.
+        * Clients must not modify the result. This abstract method
+        * must be implemented in each concrete AST node type.
+        * <p>
+        * N.B. This method is package-private, so that the implementations
+        * of this method in each of the concrete AST node types do not
+        * clutter up the API doc.
+        * </p>
+        * 
+        * @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
+        */
+       abstract List internalStructuralPropertiesForType(int apiLevel);
+       
+       /**
+        * Internal helper method that starts the building a list of
+        * property descriptors for the given node type.
+        * 
+        * @param nodeClass the class for a concrete node type
+        * @param propertyList empty list
+        */
+       static void createPropertyList(Class nodeClass, List propertyList) {
+               // stuff nodeClass at head of list for future ref
+               propertyList.add(nodeClass);
+       }
+       
+       /**
+        * Internal helper method that adding a property descriptor.
+        * 
+        * @param property the structural property descriptor
+        * @param propertyList list beginning with the AST node class
+        * followed by accumulated structural property descriptors
+        */
+       static void addProperty(StructuralPropertyDescriptor property, List propertyList) {
+               Class nodeClass = (Class) propertyList.get(0);
+               if (property.getNodeClass() != nodeClass) {
+                       // easily made cut-and-paste mistake
+                       throw new RuntimeException("Structural property descriptor has wrong node class!");  //$NON-NLS-1$
+               }
+               propertyList.add(property);
+       }
+               
+       /**
+        * Internal helper method that completes the building of
+        * a node type's structural property descriptor list.
+        * 
+        * @param propertyList list beginning with the AST node class
+        * followed by accumulated structural property descriptors
+        * @return unmodifiable list of structural property descriptors
+        * (element type: <code>StructuralPropertyDescriptor</code>)
+        */
+       static List reapPropertyList(List propertyList) {
+               propertyList.remove(0); // remove nodeClass
+               // compact
+               ArrayList a = new ArrayList(propertyList.size());
+               a.addAll(propertyList); 
+               return Collections.unmodifiableList(a);
+       }
+       
+       /**
+     * Checks that this AST operation is not used when
+     * building JLS2 level ASTs.
+
+     * @exception UnsupportedOperationException
+        * @since 3.0
+     */
+       final void unsupportedIn2() {
+         if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+               throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$
+         }
+       }
+
+       /**
+     * Checks that this AST operation is only used when
+     * building JLS2 level ASTs.
+
+     * @exception UnsupportedOperationException
+        * @since 3.0
+     */
+       final void supportedOnlyIn2() {
+         if (this.ast.apiLevel != AST.JLS2_INTERNAL) {
+               throw new UnsupportedOperationException("Operation only supported in JLS2 AST"); //$NON-NLS-1$
+         }
+       }
+
+       /**
+        * Sets or clears this node's parent node and location.
+        * <p>
+        * Note that this method is package-private. The pointer from a node
+        * to its parent is set implicitly as a side effect of inserting or
+        * removing the node as a child of another node. This method calls
+        * <code>ast.modifying()</code>.
+        * </p>
+        * 
+        * @param parent the new parent of this node, or <code>null</code> if none
+        * @param property the location of this node in its parent, 
+        * or <code>null</code> if <code>parent</code> is <code>null</code>
+        * @see #getLocationInParent
+        * @see #getParent
+        * @since 3.0
+        */ 
+       final void setParent(ASTNode parent, StructuralPropertyDescriptor property) {
+               this.ast.modifying();
+               this.parent = parent;
+               this.location = property;
+       }
+       
+       /**
+        * Removes this node from its parent. Has no effect if this node
+        * is unparented. If this node appears as an element of a child list
+        * property of its parent, then this node is removed from the
+        * list using <code>List.remove</code>.
+        * If this node appears as the value of a child property of its
+        * parent, then this node is detached from its parent 
+        * by passing <code>null</code> to the appropriate setter method;
+        * this operation fails if this node is in a mandatory property.
+        * 
+        * @since 3.0
+        */ 
+       public final void delete() {
+               StructuralPropertyDescriptor p = getLocationInParent();
+               if (p == null) {
+                       // node is unparented
+                       return;
+               }
+               if (p.isChildProperty()) {
+                       getParent().setStructuralProperty(this.location, null);
+                       return;
+               }
+               if (p.isChildListProperty()) {
+                       List l = (List) getParent().getStructuralProperty(this.location);
+                       l.remove(this);
+               }
+       }
+
+       /**
+        * Checks whether the given new child node is a node 
+        * in a different AST from its parent-to-be, whether it is
+        * already has a parent, whether adding it to its
+        * parent-to-be would create a cycle, and whether the child is of
+        * the right type. The parent-to-be is the enclosing instance.
+        * 
+        * @param node the parent-to-be node
+        * @param newChild the new child of the parent
+        * @param cycleCheck <code>true</code> if cycles are possible and need 
+        *   to be checked, <code>false</code> if cycles are impossible and do 
+        *   not need to be checked
+        * @param nodeType a type constraint on child nodes, or <code>null</code>
+        *   if no special check is required
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the child is null</li>
+        * <li>the node belongs to a different AST</li>
+        * <li>the child has the incorrect node type</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       static void checkNewChild(ASTNode node, ASTNode newChild,
+                       boolean cycleCheck, Class nodeType) {
+               if (newChild.ast != node.ast) {
+                       // new child is from a different AST
+                       throw new IllegalArgumentException();
+               }               
+               if (newChild.getParent() != null) {
+                       // new child currently has a different parent
+                       throw new IllegalArgumentException();
+               }
+               if (cycleCheck && newChild == node.getRoot()) {
+                       // inserting new child would create a cycle
+                       throw new IllegalArgumentException();
+               }
+               Class childClass = newChild.getClass();
+               if (nodeType != null && !nodeType.isAssignableFrom(childClass)) {
+                       // new child is not of the right type
+                       throw new ClassCastException();
+               }
+               if ((newChild.typeAndFlags & PROTECT) != 0) {
+                       // new child node is protected => cannot be parented
+                       throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+               }
+       }
+
+       /**
+     * Prelude portion of the "3 step program" for replacing the
+        * old child of this node with another node.
+     * Here is the code pattern found in all AST node subclasses:
+     * <pre>
+     * ASTNode oldChild = this.foo;
+     * preReplaceChild(oldChild, newFoo, FOO_PROPERTY);
+     * this.foo = newFoo;
+     * postReplaceChild(oldChild, newFoo, FOO_PROPERTY);
+     * </pre>
+     * The first part (preReplaceChild) does all the precondition checks,
+     * reports pre-delete events, and changes parent links.
+        * The old child is delinked from its parent (making it a root node),
+        * and the new child node is linked to its parent. The new child node
+        * must be a root node in the same AST as its new parent, and must not
+        * be an ancestor of this node. All three nodes must be
+     * modifiable (not PROTECTED). The replace operation must fail
+     * atomically; so it is crucial that all precondition checks
+     * be done before any linking and delinking happens.
+     * The final part (postReplaceChild )reports post-add events.
+        * <p>
+        * This method calls <code>ast.modifying()</code> for the nodes affected.
+        * </p>
+        * 
+        * @param oldChild the old child of this node, or <code>null</code> if
+        *   there was no old child to replace
+        * @param newChild the new child of this node, or <code>null</code> if
+        *   there is no replacement child
+        * @param property the property descriptor of this node describing
+     * the relationship between node and child
+        * @exception RuntimeException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * <li>any of the nodes involved are unmodifiable</li>
+        * </ul>
+        * @since 3.0
+        */ 
+       final void preReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
+               if ((this.typeAndFlags & PROTECT) != 0) {
+                       // this node is protected => cannot gain or lose children
+                       throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+               }
+               if (newChild != null) {
+                       checkNewChild(this, newChild, property.cycleRisk, null);
+               }
+               // delink old child from parent
+               if (oldChild != null) {
+                       if ((oldChild.typeAndFlags & PROTECT) != 0) {
+                               // old child node is protected => cannot be unparented
+                               throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+                       }
+                       if (newChild != null) {
+                               this.ast.preReplaceChildEvent(this, oldChild, newChild, property);
+                       } else {
+                               this.ast.preRemoveChildEvent(this, oldChild, property);
+                       }
+                       oldChild.setParent(null, null);
+               } else {
+                       if(newChild != null) {
+                               this.ast.preAddChildEvent(this, newChild, property);
+                       }
+               }
+               // link new child to parent
+               if (newChild != null) {
+                       newChild.setParent(this, property);
+                       // cannot notify postAddChildEvent until parent is linked to child too
+               }
+       }
+
+       /**
+     * Postlude portion of the "3 step program" for replacing the
+        * old child of this node with another node.
+     * See {@link #preReplaceChild(ASTNode, ASTNode, ChildPropertyDescriptor)}
+     * for details.
+        * @since 3.0
+        */ 
+       final void postReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) {
+               // link new child to parent
+               if (newChild != null) {
+                       if (oldChild != null) {
+                               this.ast.postReplaceChildEvent(this, oldChild, newChild, property);
+                       } else {
+                               this.ast.postAddChildEvent(this, newChild, property);
+                       }
+               } else {
+                       this.ast.postRemoveChildEvent(this, oldChild, property);
+               }
+       }
+       
+       /**
+     * Prelude portion of the "3 step program" for changing the
+        * value of a simple property of this node.
+     * Here is the code pattern found in all AST node subclasses:
+     * <pre>
+     * preValueChange(FOO_PROPERTY);
+     * this.foo = newFoo;
+     * postValueChange(FOO_PROPERTY);
+     * </pre>
+     * The first part (preValueChange) does the precondition check
+     * to make sure the node is modifiable (not PROTECTED).
+     * The change operation must fail atomically; so it is crucial
+     * that the precondition checks are done before the field is
+     * hammered. The final part (postValueChange)reports post-change
+     * events.
+        * <p>
+        * This method calls <code>ast.modifying()</code> for the node affected.
+        * </p>
+        * 
+        * @param property the property descriptor of this node 
+        * @exception RuntimeException if:
+        * <ul>
+        * <li>this node is unmodifiable</li>
+        * </ul>
+        * @since 3.0
+        */ 
+       final void preValueChange(SimplePropertyDescriptor property) {
+               if ((this.typeAndFlags & PROTECT) != 0) {
+                       // this node is protected => cannot change valure of properties
+                       throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+               }
+               this.ast.preValueChangeEvent(this, property);
+               this.ast.modifying();
+       }
+
+       /**
+     * Postlude portion of the "3 step program" for replacing the
+        * old child of this node with another node.
+     * See {@link #preValueChange(SimplePropertyDescriptor)} for details.
+        * @since 3.0
+        */ 
+       final void postValueChange(SimplePropertyDescriptor property) {
+               this.ast.postValueChangeEvent(this, property);
+       }
+       
+       /**
+     * Ensures that this node is modifiable (that is, not marked PROTECTED).
+     * If successful, calls ast.modifying().
+     * @exception RuntimeException is not modifiable
+     */
+       final void checkModifiable() {
+               if ((this.typeAndFlags & PROTECT) != 0) {
+                       throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$
+               }
+               this.ast.modifying();
+       }
+       
+       /**
+     * Begin lazy initialization of this node.
+     * Here is the code pattern found in all AST
+     * node subclasses:
+     * <pre>
+     * if (this.foo == null) {
+        *    // lazy init must be thread-safe for readers
+     *    synchronized (this) {
+     *       if (this.foo == null) {
+     *          preLazyInit();
+     *          this.foo = ...; // code to create new node
+     *          postLazyInit(this.foo, FOO_PROPERTY);
+     *       }
+     *    }
+     * }
+     * </pre>
+     * @since 3.0
+     */
+       final void preLazyInit() {
+               // IMPORTANT: this method is called by readers
+               // ASTNode.this is locked at this point
+               this.ast.disableEvents();
+               // will turn events back on in postLasyInit
+       }
+       
+       /**
+     * End lazy initialization of this node.
+     * 
+        * @param newChild the new child of this node, or <code>null</code> if
+        *   there is no replacement child
+        * @param property the property descriptor of this node describing
+     * the relationship between node and child
+     * @since 3.0
+     */
+       final void postLazyInit(ASTNode newChild, ChildPropertyDescriptor property) {
+               // IMPORTANT: this method is called by readers
+               // ASTNode.this is locked at this point
+               // newChild is brand new (so no chance of concurrent access)
+               newChild.setParent(this, property);
+               // turn events back on (they were turned off in corresponding preLazyInit)
+               this.ast.reenableEvents();
+       }
+
+       /**
+        * Returns the named property of this node, or <code>null</code> if none.
+        * 
+        * @param propertyName the property name
+        * @return the property value, or <code>null</code> if none
+        * @see #setProperty(String,Object)
+        */
+       public final Object getProperty(String propertyName) {
+               if (propertyName == null) {
+                       throw new IllegalArgumentException();
+               }
+               if (this.property1 == null) {
+                       // node has no properties at all
+                       return null;
+               }
+               if (this.property1 instanceof String) {
+                       // node has only a single property
+                       if (propertyName.equals(this.property1)) {
+                               return this.property2;
+                       } else {
+                               return null;
+                       }
+               }
+               // otherwise node has table of properties
+               Map m = (Map) this.property1;
+               return m.get(propertyName);
+       }
+       
+       /**
+        * Sets the named property of this node to the given value,
+        * or to <code>null</code> to clear it.
+        * <p>
+        * Clients should employ property names that are sufficiently unique
+        * to avoid inadvertent conflicts with other clients that might also be
+        * setting properties on the same node.
+        * </p>
+        * <p>
+        * Note that modifying a property is not considered a modification to the 
+        * AST itself. This is to allow clients to decorate existing nodes with 
+        * their own properties without jeopardizing certain things (like the 
+        * validity of bindings), which rely on the underlying tree remaining static.
+        * </p>
+        * 
+        * @param propertyName the property name
+        * @param data the new property value, or <code>null</code> if none
+        * @see #getProperty(String)
+        */
+       public final void setProperty(String propertyName, Object data) {
+               if (propertyName == null) {
+                       throw new IllegalArgumentException();
+               }
+               // N.B. DO NOT CALL ast.modifying();
+
+               if (this.property1 == null) {
+                       // node has no properties at all
+                       if (data == null) {
+                               // we already know this
+                               return;
+                       }
+                       // node gets its fist property
+                       this.property1 = propertyName;
+                       this.property2 = data;
+                       return;
+               }
+
+               if (this.property1 instanceof String) {
+                       // node has only a single property
+                       if (propertyName.equals(this.property1)) {
+                               // we're in luck
+                               this.property2 = data;
+                               if (data == null) {
+                                       // just deleted last property
+                                       this.property1 = null;
+                                       this.property2 = null;
+                               }
+                               return;
+                       }
+                       if (data == null) {
+                               // we already know this
+                               return;
+                       }
+                       // node already has one property - getting its second
+                       // convert to more flexible representation
+                       HashMap m = new HashMap(2);
+                       m.put(this.property1, this.property2);
+                       m.put(propertyName, data);
+                       this.property1 = m;
+                       this.property2 = null;
+                       return;
+               }
+                       
+               // node has two or more properties
+               HashMap m = (HashMap) this.property1;
+               if (data == null) {
+                       m.remove(propertyName);
+                       // check for just one property left
+                       if (m.size() == 1) {
+                               // convert to more efficient representation
+                               Map.Entry[] entries = (Map.Entry[]) m.entrySet().toArray(new Map.Entry[1]);
+                               this.property1 = entries[0].getKey();
+                               this.property2 = entries[0].getValue();
+                       }
+                       return;
+               } else {
+                       m.put(propertyName, data);
+                       // still has two or more properties
+                       return;
+               }
+       }
+
+       /**
+        * Returns an unmodifiable table of the properties of this node with 
+        * non-<code>null</code> values.
+        * 
+        * @return the table of property values keyed by property name
+        *   (key type: <code>String</code>; value type: <code>Object</code>)
+        */
+       public final Map properties() {
+               if (this.property1 == null) {
+                       // node has no properties at all
+                       return UNMODIFIABLE_EMPTY_MAP;
+               } 
+               if (this.property1 instanceof String) {
+                       // node has a single property
+                       return Collections.singletonMap(this.property1, this.property2);
+               }
+               
+               // node has two or more properties
+               if (this.property2 == null) {
+                       this.property2 = Collections.unmodifiableMap((Map) this.property1);
+               }
+               // property2 is unmodifiable wrapper for map in property1
+               return (Map) this.property2;
+       }
+       
+       /**
+        * Returns the flags associated with this node.
+        * <p>
+        * No flags are associated with newly created nodes.
+        * </p>
+        * <p>
+        * The flags are the bitwise-or of individual flags.
+        * The following flags are currently defined:
+        * <ul>
+        * <li>{@link #MALFORMED} - indicates node is syntactically 
+        *   malformed</li>
+        * <li>{@link #ORIGINAL} - indicates original node
+        * created by ASTParser</li>
+        * <li>{@link #PROTECT} - indicates node is protected
+        * from further modification</li>
+        * <li>{@link #RECOVERED} - indicates node or a part of this node
+        *  is recovered from source that contains a syntax error</li>
+        * </ul>
+        * Other bit positions are reserved for future use.
+        * </p>
+        * 
+        * @return the bitwise-or of individual flags
+        * @see #setFlags(int)
+        */
+       public final int getFlags() {
+               return this.typeAndFlags & 0xFFFF;
+       }
+       
+       /**
+        * Sets the flags associated with this node to the given value.
+        * <p>
+        * The flags are the bitwise-or of individual flags.
+        * The following flags are currently defined:
+        * <ul>
+        * <li>{@link #MALFORMED} - indicates node is syntactically 
+        *   malformed</li>
+        * <li>{@link #ORIGINAL} - indicates original node
+        * created by ASTParser</li>
+        * <li>{@link #PROTECT} - indicates node is protected
+        * from further modification</li>
+        * <li>{@link #RECOVERED} - indicates node or a part of this node
+        *  is recovered from source that contains a syntax error</li>
+        * </ul>
+        * Other bit positions are reserved for future use.
+        * </p>
+        * <p>
+        * Note that the flags are <em>not</em> considered a structural
+        * property of the node, and can be changed even if the
+        * node is marked as protected.
+        * </p>
+        * 
+        * @param flags the bitwise-or of individual flags
+        * @see #getFlags()
+        */
+       public final void setFlags(int flags) {
+               this.ast.modifying();
+               int old = this.typeAndFlags & 0xFFFF0000;
+               this.typeAndFlags = old | (flags & 0xFFFF);
+       }
+
+       /**
+        * Returns an integer value identifying the type of this concrete AST node.
+        * The values are small positive integers, suitable for use in switch statements.
+        * <p>
+        * For each concrete node type there is a unique node type constant (name
+        * and value). The unique node type constant for a concrete node type such as 
+        * <code>CastExpression</code> is <code>ASTNode.CAST_EXPRESSION</code>.
+        * </p>
+        * 
+        * @return one of the node type constants
+        */
+       public final int getNodeType() {
+               return this.typeAndFlags >>> 16;
+       }
+       
+       /**
+        * Sets the integer value identifying the type of this concrete AST node.
+        * The values are small positive integers, suitable for use in switch statements.
+        * 
+        * @param nodeType one of the node type constants
+        */
+       private void setNodeType(int nodeType) {
+               int old = this.typeAndFlags & 0xFFFF0000;
+               this.typeAndFlags = old | (nodeType << 16);
+       }
+       
+       /**
+        * Returns an integer value identifying the type of this concrete AST node.
+        * <p>
+        * This internal method is implemented in each of the
+        * concrete node subclasses.
+        * </p>
+        * 
+        * @return one of the node type constants
+        */
+       abstract int getNodeType0();
+       
+       /**
+        * The <code>ASTNode</code> implementation of this <code>Object</code>
+        * method uses object identity (==). Use <code>subtreeMatch</code> to
+        * compare two subtrees for equality.
+        * 
+        * @param obj {@inheritDoc}
+        * @return {@inheritDoc}
+        * @see #subtreeMatch(ASTMatcher matcher, Object other)
+        */
+       public final boolean equals(Object obj) {
+               return this == obj; // equivalent to Object.equals
+       }
+       
+       /*
+        * (non-Javadoc)
+        * This makes it consistent with the fact that a equals methods has been provided.
+        * @see java.lang.Object#hashCode()
+        */
+       public final int hashCode() {
+               return super.hashCode();
+       }
+
+       /**
+        * Returns whether the subtree rooted at the given node matches the
+        * given other object as decided by the given matcher.
+        * 
+        * @param matcher the matcher
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        * <code>false</code> if they do not match
+        */
+       public final boolean subtreeMatch(ASTMatcher matcher, Object other) {
+               return subtreeMatch0(matcher, other);
+       }
+       
+       /**
+        * Returns whether the subtree rooted at the given node matches the
+        * given other object as decided by the given matcher.
+        * <p>
+        * This internal method is implemented in each of the
+        * concrete node subclasses.
+        * </p>
+        * 
+        * @param matcher the matcher
+        * @param other the other object, or <code>null</code>
+        * @return <code>true</code> if the subtree matches, or 
+        * <code>false</code> if they do not match
+        */
+       abstract boolean subtreeMatch0(ASTMatcher matcher, Object other);
+       
+       /**
+        * Returns a deep copy of the subtree of AST nodes rooted at the
+        * given node. The resulting nodes are owned by the given AST,
+        * which may be different from the ASTs of the given node. 
+        * Even if the given node has a parent, the result node will be unparented.
+        * <p>
+        * Source range information on the original nodes is automatically copied to the new
+        * nodes. Client properties (<code>properties</code>) are not carried over.
+        * </p>
+        * <p>
+        * The node's <code>AST</code> and the target <code>AST</code> must support
+     * the same API level.
+        * </p>
+        * 
+        * @param target the AST that is to own the nodes in the result
+        * @param node the node to copy, or <code>null</code> if none
+        * @return the copied node, or <code>null</code> if <code>node</code>
+        *    is <code>null</code>
+        */
+       public static ASTNode copySubtree(AST target, ASTNode node) {
+               if (node == null) {
+                       return null;
+               }
+               if (target == null) {
+                       throw new IllegalArgumentException();
+               }
+               if (target.apiLevel() != node.getAST().apiLevel()) {
+                       throw new UnsupportedOperationException();
+               }
+               ASTNode newNode = node.clone(target);
+               return newNode;
+       }
+
+       /**
+        * Returns a deep copy of the subtrees of AST nodes rooted at the
+        * given list of nodes. The resulting nodes are owned by the given AST,
+        * which may be different from the ASTs of the nodes in the list. 
+        * Even if the nodes in the list have parents, the nodes in the result
+        * will be unparented.
+        * <p>
+        * Source range information on the original nodes is automatically copied to the new
+        * nodes. Client properties (<code>properties</code>) are not carried over.
+        * </p>
+        * 
+        * @param target the AST that is to own the nodes in the result
+        * @param nodes the list of nodes to copy
+        *    (element type: <code>ASTNode</code>)
+        * @return the list of copied subtrees
+        *    (element type: <code>ASTNode</code>)
+        */
+       public static List copySubtrees(AST target, List nodes) {
+               List result = new ArrayList(nodes.size());
+               for (Iterator it = nodes.iterator(); it.hasNext(); ) {
+                       ASTNode oldNode = (ASTNode) it.next();
+                       ASTNode newNode = oldNode.clone(target);
+                       result.add(newNode);
+               }
+               return result;
+       }
+
+       /**
+        * Returns a deep copy of the subtree of AST nodes rooted at this node.
+        * The resulting nodes are owned by the given AST, which may be different
+        * from the AST of this node. Even if this node has a parent, the 
+        * result node will be unparented.
+        * <p>
+        * This method reports pre- and post-clone events, and dispatches
+        * to <code>clone0(AST)</code> which is reimplemented in node subclasses.
+        * </p>
+        * 
+        * @param target the AST that is to own the nodes in the result
+        * @return the root node of the copies subtree
+        */
+       final ASTNode clone(AST target) {
+               this.ast.preCloneNodeEvent(this);
+               ASTNode c = this.clone0(target);
+               this.ast.postCloneNodeEvent(this, c);
+               return c;
+       }
+
+       /**
+        * Returns a deep copy of the subtree of AST nodes rooted at this node.
+        * The resulting nodes are owned by the given AST, which may be different
+        * from the AST of this node. Even if this node has a parent, the 
+        * result node will be unparented.
+        * <p>
+        * This method must be implemented in subclasses.
+        * </p>
+        * <p>
+        * This method does not report pre- and post-clone events.
+        * All callers should instead call <code>clone(AST)</code>
+        * to ensure that pre- and post-clone events are reported.
+        * </p>
+        * <p>
+        * N.B. This method is package-private, so that the implementations
+        * of this method in each of the concrete AST node types do not
+        * clutter up the API doc. 
+        * </p>
+        * 
+        * @param target the AST that is to own the nodes in the result
+        * @return the root node of the copies subtree
+        */
+       abstract ASTNode clone0(AST target);
+       
+       /**
+        * Accepts the given visitor on a visit of the current node.
+        * 
+        * @param visitor the visitor object
+        * @exception IllegalArgumentException if the visitor is null
+        */
+       public final void accept(ASTVisitor visitor) {
+               if (visitor == null) {
+                       throw new IllegalArgumentException();
+               }
+               // begin with the generic pre-visit
+               visitor.preVisit(this);
+               // dynamic dispatch to internal method for type-specific visit/endVisit
+               accept0(visitor);
+               // end with the generic post-visit
+               visitor.postVisit(this);
+       }
+
+       /**
+        * Accepts the given visitor on a type-specific visit of the current node.
+        * This method must be implemented in all concrete AST node types.
+        * <p>
+        * General template for implementation on each concrete ASTNode class:
+        * <pre>
+        * <code>
+        * boolean visitChildren = visitor.visit(this);
+        * if (visitChildren) {
+        *    // visit children in normal left to right reading order
+        *    acceptChild(visitor, getProperty1());
+        *    acceptChildren(visitor, rawListProperty);
+        *    acceptChild(visitor, getProperty2());
+        * }
+        * visitor.endVisit(this);
+        * </code>
+        * </pre>
+        * Note that the caller (<code>accept</code>) take cares of invoking
+        * <code>visitor.preVisit(this)</code> and <code>visitor.postVisit(this)</code>.
+        * </p>
+        * 
+        * @param visitor the visitor object
+        */
+       abstract void accept0(ASTVisitor visitor);
+
+       /**
+        * Accepts the given visitor on a visit of the current node.
+        * <p>
+        * This method should be used by the concrete implementations of
+        * <code>accept0</code> to traverse optional properties. Equivalent
+        * to <code>child.accept(visitor)</code> if <code>child</code>
+        * is not <code>null</code>.
+        * </p>
+        * 
+        * @param visitor the visitor object
+        * @param child the child AST node to dispatch too, or <code>null</code>
+        *    if none
+        */
+       final void acceptChild(ASTVisitor visitor, ASTNode child) {
+               if (child == null) {
+                       return;
+               }
+               child.accept(visitor);
+       }
+
+       /**
+        * Accepts the given visitor on a visit of the given live list of
+        * child nodes. 
+        * <p>
+        * This method must be used by the concrete implementations of
+        * <code>accept</code> to traverse list-values properties; it
+        * encapsulates the proper handling of on-the-fly changes to the list.
+        * </p>
+        * 
+        * @param visitor the visitor object
+        * @param children the child AST node to dispatch too, or <code>null</code>
+        *    if none
+        */
+       final void acceptChildren(ASTVisitor visitor, ASTNode.NodeList children) {
+               // use a cursor to keep track of where we are up to
+               // (the list may be changing under foot)
+               NodeList.Cursor cursor = children.newCursor();
+               try {
+                       while (cursor.hasNext()) {
+                               ASTNode child = (ASTNode) cursor.next();
+                               child.accept(visitor);
+                       }
+               } finally {
+                       children.releaseCursor(cursor);
+               }
+       }
+
+       /**
+        * Returns the character index into the original source file indicating
+        * where the source fragment corresponding to this node begins.
+        * <p>
+        * The parser supplies useful well-defined source ranges to the nodes it creates.
+        * See {@link ASTParser#setKind(int)} for details
+        * on precisely where source ranges begin and end.
+        * </p>
+        * 
+        * @return the 0-based character index, or <code>-1</code>
+        *    if no source position information is recorded for this node
+        * @see #getLength()
+        * @see ASTParser
+        */
+       public final int getStartPosition() {
+               return this.startPosition;
+       }
+
+       /**
+        * Returns the length in characters of the original source file indicating
+        * where the source fragment corresponding to this node ends.
+        * <p>
+        * The parser supplies useful well-defined source ranges to the nodes it creates.
+        * See {@link ASTParser#setKind(int)} methods for details
+        * on precisely where source ranges begin and end.
+        * </p>
+        * 
+        * @return a (possibly 0) length, or <code>0</code>
+        *    if no source position information is recorded for this node
+        * @see #getStartPosition()
+        * @see ASTParser
+        */
+       public final int getLength() {
+               return this.length;
+       }
+
+       /**
+        * Sets the source range of the original source file where the source
+        * fragment corresponding to this node was found.
+        * <p>
+        * See {@link ASTParser#setKind(int)} for details
+        * on precisely where source ranges are supposed to begin and end.
+        * </p>
+        * 
+        * @param startPosition a 0-based character index, 
+        *    or <code>-1</code> if no source position information is 
+        *    available for this node
+        * @param length a (possibly 0) length, 
+        *    or <code>0</code> if no source position information is recorded 
+        *    for this node
+        * @see #getStartPosition()
+        * @see #getLength()
+        * @see ASTParser
+        */
+       public final void setSourceRange(int startPosition, int length) {
+               if (startPosition >= 0 && length < 0) {
+                       throw new IllegalArgumentException();
+               }
+               if (startPosition < 0 && length != 0) {
+                       throw new IllegalArgumentException();
+               }
+               // source positions are not considered a structural property
+               // but we protect them nevertheless
+               checkModifiable();
+               this.startPosition = startPosition;
+               this.length = length;
+       }
+       
+       /**
+        * Returns a string representation of this node suitable for debugging
+        * purposes only.
+        * 
+        * @return a debug string 
+        */
+       public final String toString() {
+               StringBuffer buffer = new StringBuffer();
+               int p = buffer.length();
+               try {
+                       appendDebugString(buffer);
+               } catch (RuntimeException e) {
+                       // since debugger sometimes call toString methods, problems can easily happen when
+                       // toString is called on an instance that is being initialized
+                       buffer.setLength(p);
+                       buffer.append("!"); //$NON-NLS-1$
+                       buffer.append(standardToString());
+               }
+               return buffer.toString();
+       }
+       
+       /**
+        * Returns the string representation of this node produced by the standard
+        * <code>Object.toString</code> method.
+        * 
+        * @return a debug string 
+        */
+       final String standardToString() {
+               return super.toString();
+       }
+       
+       /**
+        * Appends a debug representation of this node to the given string buffer.
+        * <p>
+        * The <code>ASTNode</code> implementation of this method prints out the entire 
+        * subtree. Subclasses may override to provide a more succinct representation.
+        * </p>
+        * 
+        * @param buffer the string buffer to append to
+        */
+       void appendDebugString(StringBuffer buffer) {
+               // print the subtree by default
+               appendPrintString(buffer);
+       }
+               
+       /**
+        * Appends a standard Java source code representation of this subtree to the given
+        * string buffer.
+        * 
+        * @param buffer the string buffer to append to
+        */
+       final void appendPrintString(StringBuffer buffer) {
+               NaiveASTFlattener printer = new NaiveASTFlattener();
+               this.accept(printer);
+               buffer.append(printer.getResult());
+       }
+       
+       /**
+        * Estimate of size of an object header in bytes.
+        */
+       static final int HEADERS = 12;
+       
+       /**
+        * Approximate base size of an AST node instance in bytes, 
+        * including object header and instance fields.
+        * That is, HEADERS + (# instance vars in ASTNode)*4.
+        */
+       static final int BASE_NODE_SIZE = HEADERS + 7 * 4;
+       
+       /**
+        * Returns an estimate of the memory footprint, in bytes,
+        * of the given string.
+        * 
+        * @param string the string to measure, or <code>null</code>
+        * @return the size of this string object in bytes, or
+        *   0 if the string is <code>null</code>
+     * @since 3.0
+        */
+       static int stringSize(String string) {
+               int size = 0;
+               if (string != null) {
+                       // Strings usually have 4 instance fields, one of which is a char[]
+                       size += HEADERS + 4 * 4;
+                       // char[] has 2 bytes per character
+                       size += HEADERS + 2 * string.length();
+               }
+               return size;
+       }
+       
+       /**
+        * Returns an estimate of the memory footprint in bytes of the entire 
+        * subtree rooted at this node.
+        * 
+        * @return the size of this subtree in bytes
+        */
+       public final int subtreeBytes() {
+               return treeSize();
+       }
+               
+       /**
+        * Returns an estimate of the memory footprint in bytes of the entire 
+        * subtree rooted at this node.
+        * <p>
+        * N.B. This method is package-private, so that the implementations
+        * of this method in each of the concrete AST node types do not
+        * clutter up the API doc.
+        * </p>
+        * 
+        * @return the size of this subtree in bytes
+        */
+       abstract int treeSize();
+
+       /**
+        * Returns an estimate of the memory footprint of this node in bytes.
+        * The estimate does not include the space occupied by child nodes.
+        * 
+        * @return the size of this node in bytes
+        */
+       abstract int memSize();
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTParser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTParser.java
new file mode 100644 (file)
index 0000000..e3d0873
--- /dev/null
@@ -0,0 +1,1159 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import net.sourceforge.phpdt.core.IClassFile;
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.ITypeRoot;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.WorkingCopyOwner;
+import net.sourceforge.phpdt.core.compiler.CategorizedProblem;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.env.IBinaryType;
+import net.sourceforge.phpdt.internal.compiler.parser.RecoveryScanner;
+import net.sourceforge.phpdt.internal.compiler.parser.RecoveryScannerData;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.util.SuffixConstants;
+import net.sourceforge.phpdt.internal.core.*;
+import net.sourceforge.phpdt.internal.core.util.CodeSnippetParsingUtil;
+import net.sourceforge.phpdt.internal.core.util.RecordedParsingInformation;
+import net.sourceforge.phpdt.internal.core.util.Util;
+
+/**
+ * A Java language parser for creating abstract syntax trees (ASTs).
+ * <p>
+ * Example: Create basic AST from source string
+ * <pre>
+ * char[] source = ...;
+ * ASTParser parser = ASTParser.newParser(AST.JLS3);  // handles JDK 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6
+ * parser.setSource(source);
+ * CompilationUnit result = (CompilationUnit) parser.createAST(null);
+ * </pre>
+ * Once a configured parser instance has been used to create an AST,
+ * the settings are automatically reset to their defaults,
+ * ready for the parser instance to be reused.
+ * </p>
+ * <p>
+ * There are a number of configurable features:
+ * <ul>
+ * <li>Source string from {@link #setSource(char[]) char[]},
+ * {@link #setSource(ICompilationUnit) ICompilationUnit},
+ * or {@link #setSource(IClassFile) IClassFile}, and limited
+ * to a specified {@linkplain #setSourceRange(int,int) subrange}.</li>
+ * <li>Whether {@linkplain #setResolveBindings(boolean) bindings} will be created.</li>
+ * <li>Which {@linkplain #setWorkingCopyOwner(WorkingCopyOwner)
+ * working copy owner} to use when resolving bindings.</li>
+ * <li>A hypothetical {@linkplain #setUnitName(String) compilation unit file name}
+ * and {@linkplain #setProject(IJavaProject) Java project}
+ * for locating a raw source string in the Java model (when
+ * resolving bindings)</li>
+ * <li>Which {@linkplain #setCompilerOptions(Map) compiler options}
+ * to use. This is especially important to use if the parsing/scanning of the source code requires a
+ * different version than the default of the workspace. For example, the workspace defaults are 1.4 and
+ * you want to create an AST for a source code that is using 1.5 constructs.</li>
+ * <li>Whether to parse just {@linkplain #setKind(int) an expression, statements,
+ * or body declarations} rather than an entire compilation unit.</li>
+ * <li>Whether to return a {@linkplain #setFocalPosition(int) abridged AST}
+ * focused on the declaration containing a given source position.</li>
+ * </ul>
+ * </p>
+ *
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ASTParser {
+
+       /**
+        * Kind constant used to request that the source be parsed
+     * as a single expression.
+        */
+       public static final int K_EXPRESSION = 0x01;
+
+       /**
+        * Kind constant used to request that the source be parsed
+     * as a sequence of statements.
+        */
+       public static final int K_STATEMENTS = 0x02;
+
+       /**
+        * Kind constant used to request that the source be parsed
+        * as a sequence of class body declarations.
+        */
+       public static final int K_CLASS_BODY_DECLARATIONS = 0x04;
+
+       /**
+        * Kind constant used to request that the source be parsed
+        * as a compilation unit.
+        */
+       public static final int K_COMPILATION_UNIT = 0x08;
+
+       /**
+        * Creates a new object for creating a Java abstract syntax tree
+     * (AST) following the specified set of API rules.
+     *
+        * @param level the API level; one of the LEVEL constants
+     * declared on <code>AST</code>
+        * @return new ASTParser instance
+        */
+       public static ASTParser newParser(int level) {
+               return new ASTParser(level);
+       }
+
+       /**
+        * Level of AST API desired.
+        */
+       private final int apiLevel;
+
+       /**
+        * Kind of parse requested. Defaults to an entire compilation unit.
+        */
+       private int astKind;
+
+       /**
+        * Compiler options. Defaults to JavaCore.getOptions().
+        */
+       private Map compilerOptions;
+
+       /**
+        * Request for bindings. Defaults to <code>false</code>.
+     */
+       private boolean resolveBindings;
+
+       /**
+        * Request for a partial AST. Defaults to <code>false</code>.
+     */
+       private boolean partial = false;
+
+       /**
+        * Request for a statements recovery. Defaults to <code>false</code>.
+     */
+       private boolean statementsRecovery;
+
+       /**
+     * Request for a bindings recovery. Defaults to <code>false</code>.
+     */
+    private boolean bindingsRecovery;
+
+    /**
+        * The focal point for a partial AST request.
+     * Only used when <code>partial</code> is <code>true</code>.
+     */
+       private int focalPointPosition;
+
+    /**
+     * Source string.
+     */
+    private char[] rawSource = null;
+
+    /**
+     * Java model class file or compilation unit supplying the source.
+     */
+    private ITypeRoot typeRoot = null;
+
+    /**
+     * Character-based offset into the source string where parsing is to
+     * begin. Defaults to 0.
+     */
+       private int sourceOffset = 0;
+
+    /**
+     * Character-based length limit, or -1 if unlimited.
+     * All characters in the source string between <code>offset</code>
+     * and <code>offset+length-1</code> inclusive are parsed. Defaults to -1,
+     * which means the rest of the source string.
+     */
+       private int sourceLength = -1;
+
+    /**
+     * Working copy owner. Defaults to primary owner.
+     */
+       private WorkingCopyOwner workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
+
+    /**
+        * Java project used to resolve names, or <code>null</code> if none.
+     * Defaults to none.
+     */
+       private IJavaProject project = null;
+
+    /**
+        * Name of the compilation unit for resolving bindings, or
+        * <code>null</code> if none. Defaults to none.
+     */
+       private String unitName = null;
+
+       /**
+        * Creates a new AST parser for the given API level.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        *
+        * @param level the API level; one of the LEVEL constants
+     * declared on <code>AST</code>
+        */
+       ASTParser(int level) {
+               if ((level != AST.JLS2_INTERNAL)
+                       && (level != AST.JLS3)) {
+                       throw new IllegalArgumentException();
+               }
+               this.apiLevel = level;
+               initializeDefaults();
+       }
+
+       /**
+        * Sets all the setting to their default values.
+        */
+       private void initializeDefaults() {
+               this.astKind = K_COMPILATION_UNIT;
+               this.rawSource = null;
+               this.typeRoot = null;
+               this.resolveBindings = false;
+               this.sourceLength = -1;
+               this.sourceOffset = 0;
+               this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
+               this.unitName = null;
+               this.project = null;
+               this.partial = false;
+               Map options = JavaCore.getOptions();
+               options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
+               this.compilerOptions = options;
+       }
+
+    /**
+     * Requests that the compiler should perform bindings recovery.
+     * When bindings recovery is enabled the compiler returns incomplete bindings.
+     * <p>
+     * Default to <code>false</code>.
+     * </p>
+     * <p>This should be set to true only if bindings are resolved. It has no effect if there is no binding
+     * resolution.</p>
+     *
+     * @param enabled <code>true</code> if incomplete bindings are expected,
+     *   and <code>false</code> if only complete bindings are expected.
+     *
+     * @see IBinding#isRecovered()
+     * @since 3.3
+     */
+    public void setBindingsRecovery(boolean enabled) {
+        this.bindingsRecovery = enabled;
+    }
+       /**
+        * Sets the compiler options to be used when parsing.
+        * <p>
+        * Note that {@link #setSource(IClassFile)},
+        * {@link #setSource(ICompilationUnit)},
+        * and {@link #setProject(IJavaProject)} reset the compiler options
+        * based on the Java project. In other cases, compiler options default
+        * to {@link JavaCore#getOptions()}. In either case, and especially
+        * in the latter, the caller should carefully weight the consequences of
+        * allowing compiler options to be defaulted as opposed to being
+        * explicitly specified for the <code>ASTParser</code> instance.
+        * For instance, there is a compiler option called "Source Compatibility Mode"
+        * which determines which JDK level the source code is expected to meet.
+        * If you specify "1.4", then "assert" is treated as a keyword and disallowed
+        * as an identifier; if you specify "1.3", then "assert" is allowed as an
+        * identifier. So this particular setting has a major bearing on what is
+        * considered syntactically legal. By explicitly specifying the setting,
+        * the client control exactly how the parser works. On the other hand,
+        * allowing default settings means the parsing behaves like other JDT tools.
+        * </p>
+        *
+        * @param options the table of options (key type: <code>String</code>;
+        * value type: <code>String</code>), or <code>null</code>
+        * to set it back to the default
+        */
+       public void setCompilerOptions(Map options) {
+               if (options == null) {
+                       options = JavaCore.getOptions();
+               } else {
+                       // copy client's options so as to not do any side effect on them
+                       options = new HashMap(options);
+               }
+               options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
+               this.compilerOptions = options;
+       }
+
+       /**
+        * Requests that the compiler should provide binding information for
+     * the AST nodes it creates.
+     * <p>
+     * Default to <code>false</code> (no bindings).
+     * </p>
+        * <p>
+        * If <code>setResolveBindings(true)</code>, the various names
+        * and types appearing in the AST can be resolved to "bindings"
+        * by calling the <code>resolveBinding</code> methods. These bindings
+        * draw connections between the different parts of a program, and
+        * generally afford a more powerful vantage point for clients who wish to
+        * analyze a program's structure more deeply. These bindings come at a
+        * considerable cost in both time and space, however, and should not be
+        * requested frivolously. The additional space is not reclaimed until the
+        * AST, all its nodes, and all its bindings become garbage. So it is very
+        * important to not retain any of these objects longer than absolutely
+        * necessary. Bindings are resolved at the time the AST is created. Subsequent
+        * modifications to the AST do not affect the bindings returned by
+        * <code>resolveBinding</code> methods in any way; these methods return the
+        * same binding as before the AST was modified (including modifications
+        * that rearrange subtrees by reparenting nodes).
+        * If <code>setResolveBindings(false)</code> (the default), the analysis
+        * does not go beyond parsing and building the tree, and all
+        * <code>resolveBinding</code> methods return <code>null</code> from the
+        * outset.
+        * </p>
+        * <p>
+        * When bindings are requested, instead of considering compilation units on disk only
+        * one can supply a <code>WorkingCopyOwner</code>. Working copies owned
+        * by this owner take precedence over the underlying compilation units when looking
+        * up names and drawing the connections.
+        * </p>
+        * <p>
+     * Binding information is obtained from the Java model.
+     * This means that the compilation unit must be located relative to the
+     * Java model. This happens automatically when the source code comes from
+     * either {@link #setSource(ICompilationUnit) setSource(ICompilationUnit)}
+     * or {@link #setSource(IClassFile) setSource(IClassFile)}.
+     * When source is supplied by {@link #setSource(char[]) setSource(char[])},
+     * the location must be extablished explicitly by calling
+     * {@link #setProject(IJavaProject)} and  {@link #setUnitName(String)}.
+        * Note that the compiler options that affect doc comment checking may also
+        * affect whether any bindings are resolved for nodes within doc comments.
+        * </p>
+        *
+        * @param bindings <code>true</code> if bindings are wanted,
+        *   and <code>false</code> if bindings are not of interest
+        */
+       public void setResolveBindings(boolean bindings) {
+         this.resolveBindings = bindings;
+       }
+
+       /**
+     * Requests an abridged abstract syntax tree.
+     * By default, complete ASTs are returned.
+     * <p>
+     * When <code>true</code> the resulting AST does not have nodes for
+     * the entire compilation unit. Rather, the AST is only fleshed out
+     * for the node that include the given source position. This kind of limited
+     * AST is sufficient for certain purposes but totally unsuitable for others.
+     * In places where it can be used, the limited AST offers the advantage of
+     * being smaller and faster to construct.
+        * </p>
+        * <p>
+        * The AST will include nodes for all of the compilation unit's
+        * package, import, and top-level type declarations. It will also always contain
+        * nodes for all the body declarations for those top-level types, as well
+        * as body declarations for any member types. However, some of the body
+        * declarations may be abridged. In particular, the statements ordinarily
+        * found in the body of a method declaration node will not be included
+        * (the block will be empty) unless the source position falls somewhere
+        * within the source range of that method declaration node. The same is true
+        * for initializer declarations; the statements ordinarily found in the body
+        * of initializer node will not be included unless the source position falls
+        * somewhere within the source range of that initializer declaration node.
+        * Field declarations are never abridged. Note that the AST for the body of
+        * that one unabridged method (or initializer) is 100% complete; it has all
+        * its statements, including any local or anonymous type declarations
+        * embedded within them. When the the given position is not located within
+        * the source range of any body declaration of a top-level type, the AST
+        * returned will be a skeleton that includes nodes for all and only the major
+        * declarations; this kind of AST is still quite useful because it contains
+        * all the constructs that introduce names visible to the world outside the
+        * compilation unit.
+        * </p>
+        *
+        * @param position a position into the corresponding body declaration
+        */
+       public void setFocalPosition(int position) {
+               this.partial = true;
+               this.focalPointPosition = position;
+       }
+
+       /**
+        * Sets the kind of constructs to be parsed from the source.
+     * Defaults to an entire compilation unit.
+        * <p>
+        * When the parse is successful the result returned includes the ASTs for the
+        * requested source:
+        * <ul>
+        * <li>{@link #K_COMPILATION_UNIT K_COMPILATION_UNIT}: The result node
+        * is a {@link CompilationUnit}.</li>
+        * <li>{@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
+        * is a {@link TypeDeclaration} whose
+        * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
+        * are the new trees. Other aspects of the type declaration are unspecified.</li>
+        * <li>{@link #K_STATEMENTS K_STATEMENTS}: The result node is a
+        * {@link Block Block} whose {@link Block#statements() statements}
+        * are the new trees. Other aspects of the block are unspecified.</li>
+        * <li>{@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
+        * {@link Expression Expression}. Other aspects of the expression are unspecified.</li>
+        * </ul>
+        * The resulting AST node is rooted under (possibly contrived)
+        * {@link CompilationUnit CompilationUnit} node, to allow the
+        * client to retrieve the following pieces of information
+        * available there:
+        * <ul>
+        * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
+        * numbers start at 1 and only cover the subrange scanned
+        * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
+        * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
+        * and {@linkplain CompilationUnit#getProblems() detailed problem reports}.
+        * Character positions are relative to the start of
+        * <code>source</code>; line positions are for the subrange scanned.</li>
+        * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
+        * for the subrange scanned.</li>
+        * </ul>
+        * The contrived nodes do not have source positions. Other aspects of the
+        * {@link CompilationUnit CompilationUnit} node are unspecified, including
+        * the exact arrangment of intervening nodes.
+        * </p>
+        * <p>
+        * Lexical or syntax errors detected while parsing can result in
+        * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
+        * In more severe failure cases where the parser is unable to
+        * recognize the input, this method returns
+        * a {@link CompilationUnit CompilationUnit} node with at least the
+        * compiler messages.
+        * </p>
+        * <p>Each node in the subtree (other than the contrived nodes)
+        * carries source range(s) information relating back
+        * to positions in the given source (the given source itself
+        * is not remembered with the AST).
+        * The source range usually begins at the first character of the first token
+        * corresponding to the node; leading whitespace and comments are <b>not</b>
+        * included. The source range usually extends through the last character of
+        * the last token corresponding to the node; trailing whitespace and
+        * comments are <b>not</b> included. There are a handful of exceptions
+        * (including the various body declarations); the
+        * specification for these node type spells out the details.
+        * Source ranges nest properly: the source range for a child is always
+        * within the source range of its parent, and the source ranges of sibling
+        * nodes never overlap.
+        * </p>
+        * <p>
+        * Binding information is only computed when <code>kind</code> is
+     * <code>K_COMPILATION_UNIT</code>.
+        * </p>
+        *
+        * @param kind the kind of construct to parse: one of
+        * {@link #K_COMPILATION_UNIT},
+        * {@link #K_CLASS_BODY_DECLARATIONS},
+        * {@link #K_EXPRESSION},
+        * {@link #K_STATEMENTS}
+        */
+       public void setKind(int kind) {
+           if ((kind != K_COMPILATION_UNIT)
+                   && (kind != K_CLASS_BODY_DECLARATIONS)
+                   && (kind != K_EXPRESSION)
+                   && (kind != K_STATEMENTS)) {
+               throw new IllegalArgumentException();
+           }
+               this.astKind = kind;
+       }
+
+       /**
+     * Sets the source code to be parsed.
+     *
+        * @param source the source string to be parsed,
+     * or <code>null</code> if none
+     */
+       public void setSource(char[] source) {
+               this.rawSource = source;
+               // clear the type root
+               this.typeRoot = null;
+       }
+
+       /**
+     * Sets the source code to be parsed.
+     * This method automatically sets the project (and compiler
+     * options) based on the given compilation unit, in a manner
+     * equivalent to <code>setProject(source.getJavaProject())</code>
+     *
+        * @param source the Java model compilation unit whose source code
+     * is to be parsed, or <code>null</code> if none
+      */
+       public void setSource(ICompilationUnit source) {
+               setSource((ITypeRoot)source);
+       }
+
+       /**
+     * Sets the source code to be parsed.
+     * <p>This method automatically sets the project (and compiler
+     * options) based on the given compilation unit, in a manner
+     * equivalent to <code>setProject(source.getJavaProject())</code>.</p>
+     * <p>If the given class file has  no source attachment, the creation of the
+     * ast will fail with an IllegalStateException.</p>
+     *
+        * @param source the Java model class file whose corresponding source code
+     * is to be parsed, or <code>null</code> if none
+     */
+       public void setSource(IClassFile source) {
+               setSource((ITypeRoot)source);
+       }
+
+       /**
+        * Sets the source code to be parsed.
+        * <p>This method automatically sets the project (and compiler
+        * options) based on the given compilation unit of class file, in a manner
+        * equivalent to <code>setProject(source.getJavaProject())</code>.</p>
+        * <p>If the source is a class file without source attachment, the creation of the
+        * ast will fail with an IllegalStateException.</p>
+        *
+        * @param source the Java model compilation unit or class file whose corresponding source code
+        * is to be parsed, or <code>null</code> if none
+        * @since 3.3
+        */
+       public void setSource(ITypeRoot source) {
+               this.typeRoot = source;
+               // clear the raw source
+               this.rawSource = null;
+               if (source != null) {
+                       this.project = source.getJavaProject();
+                       Map options = this.project.getOptions(true);
+                       options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
+                       this.compilerOptions = options;
+               }
+       }
+
+       /**
+     * Sets the subrange of the source code to be parsed.
+     * By default, the entire source string will be parsed
+     * (<code>offset</code> 0 and <code>length</code> -1).
+     *
+     * @param offset the index of the first character to parse
+     * @param length the number of characters to parse, or -1 if
+     * the remainder of the source string is
+     */
+       public void setSourceRange(int offset, int length) {
+               if (offset < 0 || length < -1) {
+                       throw new IllegalArgumentException();
+               }
+               this.sourceOffset = offset;
+               this.sourceLength = length;
+       }
+
+       /**
+        * Requests that the compiler should perform statements recovery.
+        * When statements recovery is enabled the compiler tries to create statement nodes
+        * from code containing syntax errors
+     * <p>
+     * Default to <code>false</code>.
+     * </p>
+        *
+        * @param enabled <code>true</code> if statements containing syntax errors are wanted,
+        *   and <code>false</code> if these statements aren't wanted.
+        *
+        * @since 3.2
+        */
+       public void setStatementsRecovery(boolean enabled) {
+               this.statementsRecovery = enabled;
+       }
+
+    /**
+     * Sets the working copy owner using when resolving bindings, where
+     * <code>null</code> means the primary owner. Defaults to the primary owner.
+     *
+        * @param owner the owner of working copies that take precedence over underlying
+        *   compilation units, or <code>null</code> if the primary owner should be used
+     */
+       public void setWorkingCopyOwner(WorkingCopyOwner owner) {
+           if (owner == null) {
+                       this.workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
+               } else {
+                       this.workingCopyOwner = owner;
+               }
+       }
+
+       /**
+     * Sets the name of the compilation unit that would hypothetically contains
+     * the source string. This is used in conjunction with {@link #setSource(char[])}
+     * and {@link #setProject(IJavaProject) } to locate the compilation unit relative to a Java project.
+     * Defaults to none (<code>null</code>).
+        * <p>
+        * The name of the compilation unit must be supplied for resolving bindings.
+        * This name should be suffixed by a dot ('.') followed by one of the
+        * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}
+        * and match the name of the main (public) class or interface declared in the source.</p>
+        *
+        * <p>This name must represent the full path of the unit inside the given project. For example, if the source
+        * declares a public class named "Foo" in a project "P", the name of the compilation unit must be
+        * "/P/Foo.java". If the source declares a public class name "Bar" in a package "p1.p2" in a project "P",
+        * the name of the compilation unit must be "/P/p1/p2/Bar.java".</p>
+     *
+        * @param unitName the name of the compilation unit that would contain the source
+        *    string, or <code>null</code> if none
+     */
+       public void setUnitName(String unitName) {
+               this.unitName = unitName;
+       }
+
+       /**
+        * Sets the Java project used when resolving bindings.
+        * This method automatically sets the compiler
+        * options based on the given project:
+        * <pre>
+        * setCompilerOptions(project.getOptions(true));
+        * </pre>
+        * See {@link #setCompilerOptions(Map)} for a discussion of
+        * the pros and cons of using these options vs specifying
+        * compiler options explicitly.
+        * This setting is used in conjunction with <code>setSource(char[])</code>.
+        * For the purposes of resolving bindings, types declared in the
+        * source string will hide types by the same name available
+        * through the classpath of the given project.
+        * Defaults to none (<code>null</code>).
+        *
+        * @param project the Java project used to resolve names, or
+        *    <code>null</code> if none
+        */
+       public void setProject(IJavaProject project) {
+               this.project = project;
+               if (project != null) {
+                       Map options = project.getOptions(true);
+                       options.remove(JavaCore.COMPILER_TASK_TAGS); // no need to parse task tags
+                       this.compilerOptions = options;
+               }
+       }
+
+       /**
+     * Creates an abstract syntax tree.
+     * <p>
+     * A successful call to this method returns all settings to their
+     * default values so the object is ready to be reused.
+     * </p>
+     *
+        * @param monitor the progress monitor used to report progress and request cancelation,
+        *   or <code>null</code> if none
+        * @return an AST node whose type depends on the kind of parse
+        *  requested, with a fallback to a <code>CompilationUnit</code>
+        *  in the case of severe parsing errors
+        * @exception IllegalStateException if the settings provided
+        * are insufficient, contradictory, or otherwise unsupported
+     */
+       public ASTNode createAST(IProgressMonitor monitor) {
+          ASTNode result = null;
+          if (monitor != null) monitor.beginTask("", 1); //$NON-NLS-1$
+               try {
+                       if (this.rawSource == null && this.typeRoot == null) {
+                         throw new IllegalStateException("source not specified"); //$NON-NLS-1$
+                  }
+                       result = internalCreateAST(monitor);
+               } finally {
+                  // re-init defaults to allow reuse (and avoid leaking)
+                  initializeDefaults();
+                  if (monitor != null) monitor.done();
+               }
+          return result;
+       }
+
+       /**
+     * Creates ASTs for a batch of compilation units.
+     * When bindings are being resolved, processing a
+     * batch of compilation units is more efficient because much
+     * of the work involved in resolving bindings can be shared.
+     * <p>
+     * When bindings are being resolved, all compilation units must
+     * come from the same Java project, which must be set beforehand
+     * with <code>setProject</code>.
+     * The compilation units are processed one at a time in no
+     * specified order. For each of the compilation units in turn,
+        * <ul>
+        * <li><code>ASTParser.createAST</code> is called to parse it
+        * and create a corresponding AST. The calls to
+        * <code>ASTParser.createAST</code> all employ the same settings.</li>
+        * <li><code>ASTRequestor.acceptAST</code> is called passing
+        * the compilation unit and the corresponding AST to
+        * <code>requestor</code>.
+        * </li>
+        * </ul>
+     * Note only ASTs from the given compilation units are reported
+     * to the requestor. If additional compilation units are required to
+     * resolve the original ones, the corresponding ASTs are <b>not</b>
+     * reported to the requestor.
+     * </p>
+        * <p>
+        * Note also the following parser parameters are used, regardless of what
+        * may have been specified:
+        * <ul>
+        * <li>The {@linkplain #setKind(int) parser kind} is <code>K_COMPILATION_UNIT</code></li>
+        * <li>The {@linkplain #setSourceRange(int,int) source range} is <code>(0, -1)</code></li>
+        * <li>The {@linkplain #setFocalPosition(int) focal position} is not set</li>
+        * </ul>
+        * </p>
+     * <p>
+     * The <code>bindingKeys</code> parameter specifies bindings keys
+     * ({@link IBinding#getKey()}) that are to be looked up. These keys may
+     * be for elements either inside or outside the set of compilation
+     * units being processed. When bindings are being resolved,
+     * the keys and corresponding bindings (or <code>null</code> if none) are
+     * passed to <code>ASTRequestor.acceptBinding</code>. Note that binding keys
+     * for elements outside the set of compilation units being processed are looked up
+     * after all <code>ASTRequestor.acceptAST</code> callbacks have been made.
+     * Binding keys for elements inside the set of compilation units being processed
+     * are looked up and reported right after the corresponding
+     * <code>ASTRequestor.acceptAST</code> callback has been made.
+     * No <code>ASTRequestor.acceptBinding</code> callbacks are made unless
+     * bindings are being resolved.
+     * </p>
+     * <p>
+     * A successful call to this method returns all settings to their
+     * default values so the object is ready to be reused.
+     * </p>
+     *
+     * @param compilationUnits the compilation units to create ASTs for
+     * @param bindingKeys the binding keys to create bindings for
+     * @param requestor the AST requestor that collects abtract syntax trees and bindings
+        * @param monitor the progress monitor used to report progress and request cancelation,
+        *   or <code>null</code> if none
+        * @exception IllegalStateException if the settings provided
+        * are insufficient, contradictory, or otherwise unsupported
+        * @since 3.1
+     */
+       public void createASTs(ICompilationUnit[] compilationUnits, String[] bindingKeys, ASTRequestor requestor, IProgressMonitor monitor) {
+               try {
+                       int flags = 0;
+                       if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
+                       if (this.resolveBindings) {
+                               if (this.project == null)
+                                       throw new IllegalStateException("project not specified"); //$NON-NLS-1$
+                               if (this.bindingsRecovery) flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
+                               CompilationUnitResolver.resolve(compilationUnits, bindingKeys, requestor, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner, flags, monitor);
+                       } else {
+                               CompilationUnitResolver.parse(compilationUnits, requestor, this.apiLevel, this.compilerOptions, flags, monitor);
+                       }
+               } finally {
+                       // re-init defaults to allow reuse (and avoid leaking)
+                       initializeDefaults();
+               }
+       }
+
+       /**
+     * Creates bindings for a batch of Java elements. These elements are either
+     * enclosed in {@link ICompilationUnit}s or in {@link IClassFile}s.
+     * <p>
+     * All enclosing compilation units and class files must
+     * come from the same Java project, which must be set beforehand
+     * with <code>setProject</code>.
+     * </p>
+     * <p>
+     * All elements must exist. If one doesn't exist, an <code>IllegalStateException</code>
+     * is thrown.
+     * </p>
+     * <p>
+     * The returned array has the same size as the given elements array. At a given position
+     * it contains the binding of the corresponding Java element, or <code>null</code>
+     * if no binding could be created.
+     * </p>
+        * <p>
+        * Note also the following parser parameters are used, regardless of what
+        * may have been specified:
+        * <ul>
+        * <li>The {@linkplain #setResolveBindings(boolean) binding resolution flag} is <code>true</code></li>
+        * <li>The {@linkplain #setKind(int) parser kind} is <code>K_COMPILATION_UNIT</code></li>
+        * <li>The {@linkplain #setSourceRange(int,int) source range} is <code>(0, -1)</code></li>
+        * <li>The {@linkplain #setFocalPosition(int) focal position} is not set</li>
+        * </ul>
+        * </p>
+     * <p>
+     * A successful call to this method returns all settings to their
+     * default values so the object is ready to be reused.
+     * </p>
+     *
+     * @param elements the Java elements to create bindings for
+     * @return the bindings for the given Java elements, possibly containing <code>null</code>s
+     *              if some bindings could not be created
+        * @exception IllegalStateException if the settings provided
+        * are insufficient, contradictory, or otherwise unsupported
+        * @since 3.1
+     */
+       public IBinding[] createBindings(IJavaElement[] elements, IProgressMonitor monitor) {
+               try {
+                       if (this.project == null)
+                               throw new IllegalStateException("project not specified"); //$NON-NLS-1$
+                       int flags = 0;
+                       if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
+                       if (this.bindingsRecovery)  flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
+                       return CompilationUnitResolver.resolve(elements, this.apiLevel, this.compilerOptions, this.project, this.workingCopyOwner, flags, monitor);
+               } finally {
+                       // re-init defaults to allow reuse (and avoid leaking)
+                       initializeDefaults();
+               }
+       }
+
+       private ASTNode internalCreateAST(IProgressMonitor monitor) {
+               boolean needToResolveBindings = this.resolveBindings;
+               switch(this.astKind) {
+                       case K_CLASS_BODY_DECLARATIONS :
+                       case K_EXPRESSION :
+                       case K_STATEMENTS :
+                               if (this.rawSource != null) {
+                                       if (this.sourceOffset + this.sourceLength > this.rawSource.length) {
+                                           throw new IllegalStateException();
+                                       }
+                                       return internalCreateASTForKind();
+                               }
+                               break;
+                       case K_COMPILATION_UNIT :
+                               CompilationUnitDeclaration compilationUnitDeclaration = null;
+                               try {
+                                       NodeSearcher searcher = null;
+                                       net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit sourceUnit = null;
+                                       WorkingCopyOwner wcOwner = this.workingCopyOwner;
+                                       if (this.typeRoot instanceof ICompilationUnit) {
+                                                       /*
+                                                        * this.compilationUnitSource is an instance of org.eclipse.jdt.internal.core.CompilationUnit that implements
+                                                        * both org.eclipse.jdt.core.ICompilationUnit and org.eclipse.jdt.internal.compiler.env.ICompilationUnit
+                                                        */
+                                                       sourceUnit = (net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit) this.typeRoot;
+                                                       /*
+                                                        * use a BasicCompilation that caches the source instead of using the compilationUnitSource directly
+                                                        * (if it is a working copy, the source can change between the parse and the AST convertion)
+                                                        * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75632)
+                                                        */
+                                                       sourceUnit = new BasicCompilationUnit(sourceUnit.getContents(), sourceUnit.getPackageName(), new String(sourceUnit.getFileName()), this.project);
+                                                       wcOwner = ((ICompilationUnit) this.typeRoot).getOwner();
+                                       } else if (this.typeRoot instanceof IClassFile) {
+                                               try {
+                                                       String sourceString = this.typeRoot.getSource();
+                                                       if (sourceString == null) {
+                                                               throw new IllegalStateException();
+                                                       }
+                                                       PackageFragment packageFragment = (PackageFragment) this.typeRoot.getParent();
+                                                       BinaryType type = (BinaryType) this.typeRoot.findPrimaryType();
+                                                       IBinaryType binaryType = (IBinaryType) type.getElementInfo();
+                                                       // file name is used to recreate the Java element, so it has to be the toplevel .class file name
+                                                       char[] fileName = binaryType.getFileName();
+                                                       int firstDollar = CharOperation.indexOf('$', fileName);
+                                                       if (firstDollar != -1) {
+                                                               char[] suffix = SuffixConstants.SUFFIX_class;
+                                                               int suffixLength = suffix.length;
+                                                               char[] newFileName = new char[firstDollar + suffixLength];
+                                                               System.arraycopy(fileName, 0, newFileName, 0, firstDollar);
+                                                               System.arraycopy(suffix, 0, newFileName, firstDollar, suffixLength);
+                                                               fileName = newFileName;
+                                                       }
+                                                       sourceUnit = new BasicCompilationUnit(sourceString.toCharArray(), Util.toCharArrays(packageFragment.names), new String(fileName), this.project);
+                                               } catch(JavaModelException e) {
+                                                       // an error occured accessing the java element
+                                                       StringWriter stringWriter = new StringWriter();
+                                                       PrintWriter writer = null;
+                                                       try {
+                                                               writer = new PrintWriter(stringWriter);
+                                                               e.printStackTrace(writer);
+                                                       } finally {
+                                                               if (writer != null) writer.close();
+                                                       }
+                                                       throw new IllegalStateException(String.valueOf(stringWriter.getBuffer()));
+                                               }
+                                       } else if (this.rawSource != null) {
+                                               needToResolveBindings = this.resolveBindings && this.unitName != null && this.project != null && this.compilerOptions != null;
+                                               sourceUnit = new BasicCompilationUnit(this.rawSource, null, this.unitName == null ? "" : this.unitName, this.project); //$NON-NLS-1$
+                                       } else {
+                                               throw new IllegalStateException();
+                                       }
+                                       if (this.partial) {
+                                               searcher = new NodeSearcher(this.focalPointPosition);
+                                       }
+                                       int flags = 0;
+                                       if (this.statementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
+                                       if (needToResolveBindings) {
+                                               if (this.bindingsRecovery) flags |= ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
+                                               try {
+                                                       // parse and resolve
+                                                       compilationUnitDeclaration =
+                                                               CompilationUnitResolver.resolve(
+                                                                       sourceUnit,
+                                                                       this.project,
+                                                                       searcher,
+                                                                       this.compilerOptions,
+                                                                       this.workingCopyOwner,
+                                                                       flags,
+                                                                       monitor);
+                                               } catch (JavaModelException e) {
+                                                       flags &= ~ICompilationUnit.ENABLE_BINDINGS_RECOVERY;
+                                                       compilationUnitDeclaration = CompilationUnitResolver.parse(
+                                                                       sourceUnit,
+                                                                       searcher,
+                                                                       this.compilerOptions,
+                                                                       flags);
+                                                       needToResolveBindings = false;
+                                               }
+                                       } else {
+                                               compilationUnitDeclaration = CompilationUnitResolver.parse(
+                                                               sourceUnit,
+                                                               searcher,
+                                                               this.compilerOptions,
+                                                               flags);
+                                               needToResolveBindings = false;
+                                       }
+                                       CompilationUnit result = CompilationUnitResolver.convert(
+                                               compilationUnitDeclaration,
+                                               sourceUnit.getContents(),
+                                               this.apiLevel,
+                                               this.compilerOptions,
+                                               needToResolveBindings,
+                                               wcOwner,
+                                               needToResolveBindings ? new DefaultBindingResolver.BindingTables() : null,
+                                               flags,
+                                               monitor);
+                                       result.setTypeRoot(this.typeRoot);
+                                       return result;
+                               } finally {
+                                       if (compilationUnitDeclaration != null && this.resolveBindings) {
+                                               compilationUnitDeclaration.cleanUp();
+                                       }
+                               }
+               }
+               throw new IllegalStateException();
+       }
+
+       /**
+        * Parses the given source between the bounds specified by the given offset (inclusive)
+        * and the given length and creates and returns a corresponding abstract syntax tree.
+        * <p>
+        * When the parse is successful the result returned includes the ASTs for the
+        * requested source:
+        * <ul>
+        * <li>{@link #K_CLASS_BODY_DECLARATIONS K_CLASS_BODY_DECLARATIONS}: The result node
+        * is a {@link TypeDeclaration TypeDeclaration} whose
+        * {@link TypeDeclaration#bodyDeclarations() bodyDeclarations}
+        * are the new trees. Other aspects of the type declaration are unspecified.</li>
+        * <li>{@link #K_STATEMENTS K_STATEMENTS}: The result node is a
+        * {@link Block Block} whose {@link Block#statements() statements}
+        * are the new trees. Other aspects of the block are unspecified.</li>
+        * <li>{@link #K_EXPRESSION K_EXPRESSION}: The result node is a subclass of
+        * {@link Expression Expression}. Other aspects of the expression are unspecified.</li>
+        * </ul>
+        * The resulting AST node is rooted under an contrived
+        * {@link CompilationUnit CompilationUnit} node, to allow the
+        * client to retrieve the following pieces of information
+        * available there:
+        * <ul>
+        * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
+        * numbers start at 1 and only cover the subrange scanned
+        * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
+        * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
+        * and {@linkplain CompilationUnit#getProblems() detailed problem reports}.
+        * Character positions are relative to the start of
+        * <code>source</code>; line positions are for the subrange scanned.</li>
+        * <li>{@linkplain CompilationUnit#getCommentList() Comment list}
+        * for the subrange scanned.</li>
+        * </ul>
+        * The contrived nodes do not have source positions. Other aspects of the
+        * {@link CompilationUnit CompilationUnit} node are unspecified, including
+        * the exact arrangment of intervening nodes.
+        * </p>
+        * <p>
+        * Lexical or syntax errors detected while parsing can result in
+        * a result node being marked as {@link ASTNode#MALFORMED MALFORMED}.
+        * In more severe failure cases where the parser is unable to
+        * recognize the input, this method returns
+        * a {@link CompilationUnit CompilationUnit} node with at least the
+        * compiler messages.
+        * </p>
+        * <p>Each node in the subtree (other than the contrived nodes)
+        * carries source range(s) information relating back
+        * to positions in the given source (the given source itself
+        * is not remembered with the AST).
+        * The source range usually begins at the first character of the first token
+        * corresponding to the node; leading whitespace and comments are <b>not</b>
+        * included. The source range usually extends through the last character of
+        * the last token corresponding to the node; trailing whitespace and
+        * comments are <b>not</b> included. There are a handful of exceptions
+        * (including the various body declarations); the
+        * specification for these node type spells out the details.
+        * Source ranges nest properly: the source range for a child is always
+        * within the source range of its parent, and the source ranges of sibling
+        * nodes never overlap.
+        * </p>
+        * <p>
+        * This method does not compute binding information; all <code>resolveBinding</code>
+        * methods applied to nodes of the resulting AST return <code>null</code>.
+        * </p>
+        *
+        * @return an AST node whose type depends on the kind of parse
+        *  requested, with a fallback to a <code>CompilationUnit</code>
+        *  in the case of severe parsing errors
+        * @see ASTNode#getStartPosition()
+        * @see ASTNode#getLength()
+        */
+       private ASTNode internalCreateASTForKind() {
+               final ASTConverter converter = new ASTConverter(this.compilerOptions, false, null);
+               converter.compilationUnitSource = this.rawSource;
+               converter.compilationUnitSourceLength = this.rawSource.length;
+               converter.scanner.setSource(this.rawSource);
+
+               AST ast = AST.newAST(this.apiLevel);
+               ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+               ast.setBindingResolver(new BindingResolver());
+               if (this.statementsRecovery) {
+                       ast.setFlag(ICompilationUnit.ENABLE_STATEMENTS_RECOVERY);
+               }
+               converter.setAST(ast);
+               CodeSnippetParsingUtil codeSnippetParsingUtil = new CodeSnippetParsingUtil();
+               CompilationUnit compilationUnit = ast.newCompilationUnit();
+               if (this.sourceLength == -1) {
+                       this.sourceLength = this.rawSource.length;
+               }
+               switch(this.astKind) {
+                       case K_STATEMENTS :
+                               ConstructorDeclaration constructorDeclaration = codeSnippetParsingUtil.parseStatements(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true, this.statementsRecovery);
+                               RecoveryScannerData data = constructorDeclaration.compilationResult.recoveryScannerData;
+                               if(data != null) {
+                                       Scanner scanner = converter.scanner;
+                                       converter.scanner = new RecoveryScanner(scanner, data.removeUnused());
+                                       converter.docParser.scanner = converter.scanner;
+                                       converter.scanner.setSource(scanner.source);
+                               }
+                               RecordedParsingInformation recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
+                               int[][] comments = recordedParsingInformation.commentPositions;
+                               if (comments != null) {
+                                       converter.buildCommentsTable(compilationUnit, comments);
+                               }
+                               compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
+                               Block block = ast.newBlock();
+                               block.setSourceRange(this.sourceOffset, this.sourceOffset + this.sourceLength);
+                               net.sourceforge.phpdt.internal.compiler.ast.Statement[] statements = constructorDeclaration.statements;
+                               if (statements != null) {
+                                       int statementsLength = statements.length;
+                                       for (int i = 0; i < statementsLength; i++) {
+                                               if (statements[i] instanceof net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration) {
+                                                       converter.checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
+                                               } else {
+                                                       Statement statement = converter.convert(statements[i]);
+                                                       if (statement != null) {
+                                                               block.statements().add(statement);
+                                                       }
+                                               }
+                                       }
+                               }
+                               rootNodeToCompilationUnit(ast, compilationUnit, block, recordedParsingInformation, data);
+                               ast.setDefaultNodeFlag(0);
+                               ast.setOriginalModificationCount(ast.modificationCount());
+                               return block;
+                       case K_EXPRESSION :
+                               net.sourceforge.phpdt.internal.compiler.ast.Expression expression = codeSnippetParsingUtil.parseExpression(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true);
+                               recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
+                               comments = recordedParsingInformation.commentPositions;
+                               if (comments != null) {
+                                       converter.buildCommentsTable(compilationUnit, comments);
+                               }
+                               compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
+                               if (expression != null) {
+                                       Expression expression2 = converter.convert(expression);
+                                       rootNodeToCompilationUnit(expression2.getAST(), compilationUnit, expression2, codeSnippetParsingUtil.recordedParsingInformation, null);
+                                       ast.setDefaultNodeFlag(0);
+                                       ast.setOriginalModificationCount(ast.modificationCount());
+                                       return expression2;
+                               } else {
+                                       CategorizedProblem[] problems = recordedParsingInformation.problems;
+                                       if (problems != null) {
+                                               compilationUnit.setProblems(problems);
+                                       }
+                                       ast.setDefaultNodeFlag(0);
+                                       ast.setOriginalModificationCount(ast.modificationCount());
+                                       return compilationUnit;
+                               }
+                       case K_CLASS_BODY_DECLARATIONS :
+                               final net.sourceforge.phpdt.internal.compiler.ast.ASTNode[] nodes = codeSnippetParsingUtil.parseClassBodyDeclarations(this.rawSource, this.sourceOffset, this.sourceLength, this.compilerOptions, true);
+                               recordedParsingInformation = codeSnippetParsingUtil.recordedParsingInformation;
+                               comments = recordedParsingInformation.commentPositions;
+                               if (comments != null) {
+                                       converter.buildCommentsTable(compilationUnit, comments);
+                               }
+                               compilationUnit.setLineEndTable(recordedParsingInformation.lineEnds);
+                               if (nodes != null) {
+                                       TypeDeclaration typeDeclaration = converter.convert(nodes);
+                                       typeDeclaration.setSourceRange(this.sourceOffset, this.sourceOffset + this.sourceLength);
+                                       rootNodeToCompilationUnit(typeDeclaration.getAST(), compilationUnit, typeDeclaration, codeSnippetParsingUtil.recordedParsingInformation, null);
+                                       ast.setDefaultNodeFlag(0);
+                                       ast.setOriginalModificationCount(ast.modificationCount());
+                                       return typeDeclaration;
+                               } else {
+                                       CategorizedProblem[] problems = recordedParsingInformation.problems;
+                                       if (problems != null) {
+                                               compilationUnit.setProblems(problems);
+                                       }
+                                       ast.setDefaultNodeFlag(0);
+                                       ast.setOriginalModificationCount(ast.modificationCount());
+                                       return compilationUnit;
+                               }
+               }
+               throw new IllegalStateException();
+       }
+
+       private void propagateErrors(ASTNode astNode, CategorizedProblem[] problems, RecoveryScannerData data) {
+               astNode.accept(new ASTSyntaxErrorPropagator(problems));
+               if (data != null) {
+                       astNode.accept(new ASTRecoveryPropagator(problems, data));
+               }
+       }
+
+       private void rootNodeToCompilationUnit(AST ast, CompilationUnit compilationUnit, ASTNode node, RecordedParsingInformation recordedParsingInformation, RecoveryScannerData data) {
+               final int problemsCount = recordedParsingInformation.problemsCount;
+               switch(node.getNodeType()) {
+                       case ASTNode.BLOCK :
+                               {
+                                       Block block = (Block) node;
+                                       if (problemsCount != 0) {
+                                               // propagate and record problems
+                                               final CategorizedProblem[] problems = recordedParsingInformation.problems;
+                                               propagateErrors(block, problems, data);
+                                               compilationUnit.setProblems(problems);
+                                       }
+                                       TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
+                                       Initializer initializer = ast.newInitializer();
+                                       initializer.setBody(block);
+                                       typeDeclaration.bodyDeclarations().add(initializer);
+                                       compilationUnit.types().add(typeDeclaration);
+                               }
+                               break;
+                       case ASTNode.TYPE_DECLARATION :
+                               {
+                                       TypeDeclaration typeDeclaration = (TypeDeclaration) node;
+                                       if (problemsCount != 0) {
+                                               // propagate and record problems
+                                               final CategorizedProblem[] problems = recordedParsingInformation.problems;
+                                               propagateErrors(typeDeclaration, problems, data);
+                                               compilationUnit.setProblems(problems);
+                                       }
+                                       compilationUnit.types().add(typeDeclaration);
+                               }
+                               break;
+                       default :
+                               if (node instanceof Expression) {
+                                       Expression expression = (Expression) node;
+                                       if (problemsCount != 0) {
+                                               // propagate and record problems
+                                               final CategorizedProblem[] problems = recordedParsingInformation.problems;
+                                               propagateErrors(expression, problems, data);
+                                               compilationUnit.setProblems(problems);
+                                       }
+                                       ExpressionStatement expressionStatement = ast.newExpressionStatement(expression);
+                                       Block block = ast.newBlock();
+                                       block.statements().add(expressionStatement);
+                                       Initializer initializer = ast.newInitializer();
+                                       initializer.setBody(block);
+                                       TypeDeclaration typeDeclaration = ast.newTypeDeclaration();
+                                       typeDeclaration.bodyDeclarations().add(initializer);
+                                       compilationUnit.types().add(typeDeclaration);
+                               }
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTRecoveryPropagator.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTRecoveryPropagator.java
new file mode 100644 (file)
index 0000000..7cf7595
--- /dev/null
@@ -0,0 +1,449 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
+import org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData;
+import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToIntArray;
+
+/**
+ * Internal AST visitor for propagating syntax errors.
+ */
+class ASTRecoveryPropagator extends DefaultASTVisitor {
+       private static final int NOTHING = -1;
+       HashtableOfObjectToIntArray endingTokens = new HashtableOfObjectToIntArray();
+       {
+               this.endingTokens.put(AnonymousClassDeclaration.class, new int[]{TerminalTokens.TokenNameRBRACE});
+               this.endingTokens.put(ArrayAccess.class, new int[]{TerminalTokens.TokenNameRBRACKET});
+               this.endingTokens.put(ArrayCreation.class, new int[]{NOTHING, TerminalTokens.TokenNameRBRACKET});
+               this.endingTokens.put(ArrayInitializer.class, new int[]{TerminalTokens.TokenNameRBRACE});
+               this.endingTokens.put(ArrayType.class, new int[]{TerminalTokens.TokenNameRBRACKET});
+               this.endingTokens.put(AssertStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(Block.class, new int[]{TerminalTokens.TokenNameRBRACE});
+               this.endingTokens.put(BooleanLiteral.class, new int[]{TerminalTokens.TokenNamefalse, TerminalTokens.TokenNametrue});
+               this.endingTokens.put(BreakStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(CharacterLiteral.class, new int[]{TerminalTokens.TokenNameCharacterLiteral});
+               this.endingTokens.put(ClassInstanceCreation.class, new int[]{TerminalTokens.TokenNameRBRACE, TerminalTokens.TokenNameRPAREN});
+               this.endingTokens.put(ConstructorInvocation.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(ContinueStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(DoStatement.class, new int[]{TerminalTokens.TokenNameRPAREN});
+               this.endingTokens.put(EmptyStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(ExpressionStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(FieldDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(ImportDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(Initializer.class, new int[]{TerminalTokens.TokenNameRBRACE});
+               this.endingTokens.put(MethodDeclaration.class, new int[]{NOTHING, TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(MethodInvocation.class, new int[]{TerminalTokens.TokenNameRPAREN});
+               this.endingTokens.put(NullLiteral.class, new int[]{TerminalTokens.TokenNamenull});
+               this.endingTokens.put(NumberLiteral.class, new int[]{TerminalTokens.TokenNameIntegerLiteral, TerminalTokens.TokenNameLongLiteral, TerminalTokens.TokenNameFloatingPointLiteral, TerminalTokens.TokenNameDoubleLiteral});
+               this.endingTokens.put(PackageDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(ParenthesizedExpression.class, new int[]{TerminalTokens.TokenNameRPAREN});
+               this.endingTokens.put(PostfixExpression.class, new int[]{TerminalTokens.TokenNamePLUS_PLUS, TerminalTokens.TokenNameMINUS_MINUS});
+               this.endingTokens.put(PrimitiveType.class, new int[]{TerminalTokens.TokenNamebyte, TerminalTokens.TokenNameshort, TerminalTokens.TokenNamechar, TerminalTokens.TokenNameint, TerminalTokens.TokenNamelong, TerminalTokens.TokenNamefloat, TerminalTokens.TokenNameboolean, TerminalTokens.TokenNamedouble, TerminalTokens.TokenNamevoid});
+               this.endingTokens.put(ReturnStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(SimpleName.class, new int[]{TerminalTokens.TokenNameIdentifier});
+               this.endingTokens.put(SingleVariableDeclaration.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(StringLiteral.class, new int[]{TerminalTokens.TokenNameStringLiteral});
+               this.endingTokens.put(SuperConstructorInvocation.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(SuperMethodInvocation.class, new int[]{TerminalTokens.TokenNameRPAREN});
+               this.endingTokens.put(SwitchCase.class, new int[]{TerminalTokens.TokenNameCOLON});
+               this.endingTokens.put(SwitchStatement.class, new int[]{TerminalTokens.TokenNameRBRACE});
+               this.endingTokens.put(SynchronizedStatement.class, new int[]{TerminalTokens.TokenNameRBRACE});
+               this.endingTokens.put(ThisExpression.class, new int[]{TerminalTokens.TokenNamethis});
+               this.endingTokens.put(ThrowStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+               this.endingTokens.put(TypeDeclaration.class, new int[]{TerminalTokens.TokenNameRBRACE});
+               this.endingTokens.put(TypeLiteral.class, new int[]{TerminalTokens.TokenNameclass});
+               this.endingTokens.put(VariableDeclarationStatement.class, new int[]{TerminalTokens.TokenNameSEMICOLON});
+       }
+
+       private CategorizedProblem[] problems;
+       private boolean[] usedOrIrrelevantProblems;
+       
+       private RecoveryScannerData data;
+       private int blockDepth = 0;
+       private int lastEnd;
+       
+       private int[] insertedTokensKind;
+       private int[] insertedTokensPosition;
+       private boolean[] insertedTokensFlagged;
+       
+       private boolean[] removedTokensFlagged;
+       private boolean[] replacedTokensFlagged;
+       
+       private Vector stack = new Vector();
+       
+       /**
+        * @noreference This method is not intended to be referenced by clients.
+        */
+       ASTRecoveryPropagator(CategorizedProblem[] problems, RecoveryScannerData data) {
+               // visit Javadoc.tags() as well
+               this.problems = problems;
+               this.usedOrIrrelevantProblems = new boolean[problems.length];
+               
+               this.data = data;
+               
+               if(this.data != null) {
+                       
+                       int length = 0;
+                       for (int i = 0; i < data.insertedTokensPtr + 1; i++) {
+                               length += data.insertedTokens[i].length;
+                       }
+                       this.insertedTokensKind = new int[length];
+                       this.insertedTokensPosition = new int[length];
+                       this.insertedTokensFlagged = new boolean[length];
+                       int tokenCount = 0;
+                       for (int i = 0; i < data.insertedTokensPtr + 1; i++) {
+                               for (int j = 0; j < data.insertedTokens[i].length; j++) {
+                                       this.insertedTokensKind[tokenCount] = data.insertedTokens[i][j];
+                                       this.insertedTokensPosition[tokenCount] = data.insertedTokensPosition[i];
+                                       tokenCount++;
+                               }
+                       }
+                       
+                       if(data.removedTokensPtr != -1) {
+                               this.removedTokensFlagged = new boolean[data.removedTokensPtr + 1];
+                       }
+                       if(data.replacedTokensPtr != -1) {
+                               this.replacedTokensFlagged = new boolean[data.replacedTokensPtr + 1];
+                       }
+               }
+       }
+
+       public void endVisit(Block node) {
+               this.blockDepth--;
+               if(this.blockDepth <= 0) {
+                       flagNodeWithInsertedTokens();
+               }
+               super.endVisit(node);
+       }
+
+       
+
+       public boolean visit(Block node) {
+               boolean visitChildren = super.visit(node);
+               this.blockDepth++;
+               return visitChildren;
+       }
+       
+       protected boolean visitNode(ASTNode node) {
+               if(this.blockDepth > 0) {
+                       int start = node.getStartPosition();
+                       int end = start + node.getLength() - 1;
+                       
+                       // continue to visit the node only if it contains tokens modifications
+                       
+                       if(this.insertedTokensFlagged != null) {
+                               for (int i = 0; i < this.insertedTokensFlagged.length; i++) {
+                                       if(this.insertedTokensPosition[i] >= start &&
+                                                       this.insertedTokensPosition[i] <= end) {
+                                               return true;
+                                       }
+                               }
+                       }
+                       
+                       if(this.removedTokensFlagged != null) {
+                               for (int i = 0; i <= this.data.removedTokensPtr; i++) {
+                                       if(this.data.removedTokensStart[i] >= start &&
+                                                       this.data.removedTokensEnd[i] <= end) {
+                                               return true;
+                                       }
+                               }
+                       }
+                       
+                       if(this.replacedTokensFlagged != null) {
+                               for (int i = 0; i <= this.data.replacedTokensPtr; i++) {
+                                       if(this.data.replacedTokensStart[i] >= start &&
+                                                       this.data.replacedTokensEnd[i] <= end) {
+                                               return true;
+                                       }
+                               }
+                       }
+                       
+                       return false;
+               }
+               return true;
+       }
+
+       protected void endVisitNode(ASTNode node) {
+               int start = node.getStartPosition();
+               int end = start + node.getLength() - 1;
+               
+               // is inside diet part of the ast
+               if(this.blockDepth < 1) {
+                       switch (node.getNodeType()) {
+                               case ASTNode.ANNOTATION_TYPE_DECLARATION:
+                               case ASTNode.COMPILATION_UNIT:
+                               case ASTNode.ENUM_DECLARATION:
+                               case ASTNode.FIELD_DECLARATION:
+                               case ASTNode.IMPORT_DECLARATION:
+                               case ASTNode.INITIALIZER:
+                               case ASTNode.METHOD_DECLARATION:
+                               case ASTNode.PACKAGE_DECLARATION:
+                               case ASTNode.TYPE_DECLARATION:
+                               case ASTNode.MARKER_ANNOTATION:
+                               case ASTNode.NORMAL_ANNOTATION:
+                               case ASTNode.SINGLE_MEMBER_ANNOTATION:
+                               case ASTNode.BLOCK:
+                                       if(this.markIncludedProblems(start, end)) {
+                                               node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+                                       }
+                                       break;
+                       }
+               } else {                        
+                       this.markIncludedProblems(start, end);
+                       
+                       if(this.insertedTokensFlagged != null) {
+                               if(this.lastEnd != end) {
+                                       flagNodeWithInsertedTokens();
+                               }
+                               this.stack.add(node);
+                       }
+
+                       if(this.removedTokensFlagged != null) {
+                               for (int i = 0; i <= this.data.removedTokensPtr; i++) {
+                                       if(!this.removedTokensFlagged[i] &&
+                                                       this.data.removedTokensStart[i] >= start &&
+                                                       this.data.removedTokensEnd[i] <= end) {
+                                               node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+                                               this.removedTokensFlagged[i] = true;
+                                       }
+                               }
+                       }
+                       
+                       if(this.replacedTokensFlagged != null) {
+                               for (int i = 0; i <= this.data.replacedTokensPtr; i++) {
+                                       if(!this.replacedTokensFlagged[i] &&
+                                                       this.data.replacedTokensStart[i] >= start &&
+                                                       this.data.replacedTokensEnd[i] <= end) {
+                                               node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+                                               this.replacedTokensFlagged[i] = true;
+                                       }
+                               }
+                       }
+               }
+               this.lastEnd = end;
+       }
+       
+       private void flagNodeWithInsertedTokens() {
+               if(this.insertedTokensKind != null && this.insertedTokensKind.length > 0) {
+                       int s = this.stack.size();
+                       for (int i = s - 1; i > -1; i--) {
+                               flagNodesWithInsertedTokensAtEnd((ASTNode)this.stack.get(i));
+                       }
+                       for (int i = 0; i < s; i++) {
+                               flagNodesWithInsertedTokensInside((ASTNode)this.stack.get(i));
+                       }
+                       this.stack = new Vector();
+               }
+       }
+       
+       private boolean flagNodesWithInsertedTokensAtEnd(ASTNode node) {
+               int[] expectedEndingToken = this.endingTokens.get(node.getClass());
+               if (expectedEndingToken != null) {
+                       int start = node.getStartPosition();
+                       int end = start + node.getLength() - 1;
+                       
+                       boolean flagParent = false;
+                       done : for (int i = this.insertedTokensKind.length - 1; i > -1 ; i--) {
+                               if(!this.insertedTokensFlagged[i] &&
+                                               this.insertedTokensPosition[i] == end){
+                                       this.insertedTokensFlagged[i] = true;
+                                       for (int j = 0; j < expectedEndingToken.length; j++) {
+                                               if(expectedEndingToken[j] == this.insertedTokensKind[i]) {
+                                                       node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+                                                       break done;
+                                               }
+                                       }
+                                       flagParent = true;
+                               }
+                       }
+                       
+                       if(flagParent) {
+                               ASTNode parent = node.getParent();
+                               while (parent != null) {
+                                       parent.setFlags(node.getFlags() | ASTNode.RECOVERED);
+                                       if((parent.getStartPosition() + parent.getLength() - 1) != end) {
+                                               parent = null;
+                                       } else {
+                                               parent = parent.getParent();
+                                       }
+                               }
+                       }
+               }
+               return true;
+       }
+       
+       private boolean flagNodesWithInsertedTokensInside(ASTNode node) {
+               int start = node.getStartPosition();
+               int end = start + node.getLength() - 1;
+               for (int i = 0; i < this.insertedTokensKind.length; i++) {
+                       if(!this.insertedTokensFlagged[i] &&
+                                       start <= this.insertedTokensPosition[i] &&
+                                       this.insertedTokensPosition[i] < end){
+                               node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+                               this.insertedTokensFlagged[i] = true;
+                       }
+               }
+               return true;
+       }
+       
+       private boolean markIncludedProblems(int start, int end) {
+               boolean foundProblems = false;
+               next: for (int i = 0, max = this.problems.length; i < max; i++) {
+                       CategorizedProblem problem = this.problems[i];
+                       
+                       if(this.usedOrIrrelevantProblems[i]) continue next;
+                       
+                       switch(problem.getID()) {
+                               case IProblem.ParsingErrorOnKeywordNoSuggestion :
+                               case IProblem.ParsingErrorOnKeyword :
+                               case IProblem.ParsingError :
+                               case IProblem.ParsingErrorNoSuggestion :
+                               case IProblem.ParsingErrorInsertTokenBefore :
+                               case IProblem.ParsingErrorInsertTokenAfter :
+                               case IProblem.ParsingErrorDeleteToken :
+                               case IProblem.ParsingErrorDeleteTokens :
+                               case IProblem.ParsingErrorMergeTokens :
+                               case IProblem.ParsingErrorInvalidToken :
+                               case IProblem.ParsingErrorMisplacedConstruct :
+                               case IProblem.ParsingErrorReplaceTokens :
+                               case IProblem.ParsingErrorNoSuggestionForTokens :
+                               case IProblem.ParsingErrorUnexpectedEOF :
+                               case IProblem.ParsingErrorInsertToComplete :
+                               case IProblem.ParsingErrorInsertToCompleteScope :
+                               case IProblem.ParsingErrorInsertToCompletePhrase :
+                               case IProblem.EndOfSource :
+                               case IProblem.InvalidHexa :
+                               case IProblem.InvalidOctal :
+                               case IProblem.InvalidCharacterConstant :
+                               case IProblem.InvalidEscape :
+                               case IProblem.InvalidInput :
+                               case IProblem.InvalidUnicodeEscape :
+                               case IProblem.InvalidFloat :
+                               case IProblem.NullSourceString :
+                               case IProblem.UnterminatedString :
+                               case IProblem.UnterminatedComment :
+                               case IProblem.InvalidDigit :
+                                       break;
+                               default:
+                                       this.usedOrIrrelevantProblems[i] = true;
+                                       continue next;
+                                       
+                       }
+                       
+                       int problemStart = problem.getSourceStart();
+                       int problemEnd = problem.getSourceEnd();
+                       if ((start <= problemStart) && (problemStart <= end) ||
+                                       (start <= problemEnd) && (problemEnd <= end)) {
+                               this.usedOrIrrelevantProblems[i] = true;
+                               foundProblems = true;
+                       }
+               }
+               return foundProblems;
+       }
+
+       public void endVisit(ExpressionStatement node) {
+               endVisitNode(node);
+               if ((node.getFlags() & ASTNode.RECOVERED) == 0) return; 
+               Expression expression = node.getExpression();
+               if (expression.getNodeType() == ASTNode.ASSIGNMENT) {
+                       Assignment assignment = (Assignment) expression;
+                       Expression rightHandSide = assignment.getRightHandSide();
+                       if (rightHandSide.getNodeType() == ASTNode.SIMPLE_NAME) {
+                               SimpleName simpleName = (SimpleName) rightHandSide;
+                               if (CharOperation.equals(RecoveryScanner.FAKE_IDENTIFIER, simpleName.getIdentifier().toCharArray())) {
+                                       Expression expression2 =  assignment.getLeftHandSide();
+                                       // unparent the expression to add it in the expression stateemnt
+                                       expression2.setParent(null, null);
+                                       expression2.setFlags(expression2.getFlags() | ASTNode.RECOVERED);
+                                       node.setExpression(expression2);
+                               }
+                       }
+               }
+       }
+       
+       public void endVisit(ForStatement node) {
+               endVisitNode(node);
+               List initializers = node.initializers();
+               if (initializers.size() == 1) {
+                       Expression expression = (Expression) initializers.get(0);
+                       if (expression.getNodeType() == ASTNode.VARIABLE_DECLARATION_EXPRESSION) {
+                               VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) expression;
+                               List fragments = variableDeclarationExpression.fragments();
+                               for (int i = 0, max = fragments.size(); i <max; i++) {
+                                       VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(i);
+                                       SimpleName simpleName = fragment.getName();
+                                       if (CharOperation.equals(RecoveryScanner.FAKE_IDENTIFIER, simpleName.getIdentifier().toCharArray())) {
+                                               fragments.remove(fragment);
+                                               variableDeclarationExpression.setFlags(variableDeclarationExpression.getFlags() | ASTNode.RECOVERED);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       public void endVisit(VariableDeclarationStatement node) {
+               endVisitNode(node);
+               List fragments = node.fragments();
+               for (int i = 0, max = fragments.size(); i <max; i++) {
+                       VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(i);
+                       Expression expression = fragment.getInitializer();
+                       if (expression == null) continue;
+                       if ((expression.getFlags() & ASTNode.RECOVERED) == 0) continue;
+                       if (expression.getNodeType() == ASTNode.SIMPLE_NAME) {
+                               SimpleName simpleName = (SimpleName) expression;
+                               if (CharOperation.equals(RecoveryScanner.FAKE_IDENTIFIER, simpleName.getIdentifier().toCharArray())) {
+                                       fragment.setInitializer(null);
+                                       fragment.setFlags(fragment.getFlags() | ASTNode.RECOVERED);
+                               }
+                       }
+               }
+       }
+       
+       public void endVisit(NormalAnnotation node) {
+               endVisitNode(node);
+               // is inside diet part of the ast
+               if(this.blockDepth < 1) {
+                       List values = node.values();
+                       int size = values.size();
+                       if (size > 0) {
+                               MemberValuePair lastMemberValuePair = (MemberValuePair)values.get(size - 1);
+                               
+                               int annotationEnd = node.getStartPosition() + node.getLength();
+                               int lastMemberValuePairEnd = lastMemberValuePair.getStartPosition() + lastMemberValuePair.getLength();
+                               if (annotationEnd == lastMemberValuePairEnd) {
+                                       node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+                               }
+                       }
+               }
+       }
+       
+       public void endVisit(SingleMemberAnnotation node) {
+               endVisitNode(node);
+               // is inside diet part of the ast
+               if(this.blockDepth < 1) {
+                       Expression value = node.getValue();
+                       int annotationEnd = node.getStartPosition() + node.getLength();
+                       int valueEnd = value.getStartPosition() + value.getLength();
+                       if (annotationEnd == valueEnd) {
+                               node.setFlags(node.getFlags() | ASTNode.RECOVERED);
+                       }
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTRequestor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTRequestor.java
new file mode 100644 (file)
index 0000000..7fa2142
--- /dev/null
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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 net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+
+/**
+ * An AST requestor handles ASTs for compilation units passed to
+ * <code>ASTParser.createASTs</code>.
+ * <p>
+ * <code>ASTRequestor.acceptAST</code> is called for each of the
+ * compilation units passed to <code>ASTParser.createASTs</code>.
+ * After all the compilation units have been processed, 
+ * <code>ASTRequestor.acceptBindings</code> is called for each
+ * of the binding keys passed to <code>ASTParser.createASTs</code>.
+ * </p>
+ * <p>
+ * This class is intended to be subclassed by clients.
+ * AST requestors are serially reusable, but neither reentrant nor
+ * thread-safe.
+ * </p>
+ * 
+ * @see ASTParser#createASTs(ICompilationUnit[], String[], ASTRequestor, org.eclipse.core.runtime.IProgressMonitor)
+ * @since 3.1
+ */
+public abstract class ASTRequestor {
+       
+       /**
+        * The compilation unit resolver used to resolve bindings, or
+        * <code>null</code> if none. Note that this field is non-null
+        * only within the dynamic scope of a call to
+        * <code>ASTParser.createASTs</code>.
+        */
+       CompilationUnitResolver compilationUnitResolver = null;
+               
+       /**
+        * Creates a new instance.
+        */
+       protected ASTRequestor() {
+               // do nothing
+       }
+       
+       /**
+        * Accepts an AST corresponding to the compilation unit.
+        * That is, <code>ast</code> is an AST for <code>source</code>.
+        * <p>
+        * The default implementation of this method does nothing.
+        * Clients should override to process the resulting AST.
+        * </p>
+        * 
+        * @param source the compilation unit the ast is coming from
+        * @param ast the requested abtract syntax tree
+        */
+       public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
+               // do nothing
+       }
+       
+       /**
+        * Accepts a binding corresponding to the binding key.
+        * That is, <code>binding</code> is the binding for 
+        * <code>bindingKey</code>; <code>binding</code> is <code>null</code>
+        * if the key cannot be resolved.
+        * <p>
+        * The default implementation of this method does nothing.
+        * Clients should override to process the resulting binding.
+        * </p>
+        * 
+        * @param bindingKey the key of the requested binding
+        * @param binding the requested binding, or <code>null</code> if none
+        */
+       public void acceptBinding(String bindingKey, IBinding binding) {
+               // do nothing
+       }
+
+       /**
+        * Resolves bindings for the given binding keys.
+        * The given binding keys must have been obtained earlier
+        * using {@link IBinding#getKey()}.
+        * <p>
+        * If a binding key cannot be resolved, <code>null</code> is put in the resulting array.
+        * Bindings can only be resolved in the dynamic scope of a <code>ASTParser.createASTs</code>,
+        * and only if <code>ASTParser.resolveBindings(true)</code> was specified.
+        * </p>
+        * <p>
+        * Caveat: During an <code>acceptAST</code> callback, there are implementation 
+        * limitations concerning the look up of binding keys representing local elements.
+        * In some cases, the binding is unavailable, and <code>null</code> will be returned.
+        * This is only an issue during an <code>acceptAST</code> callback, and only
+        * when the binding key represents a local element (e.g., local variable,
+        * local class, method declared in anonymous class). There is no such limitation
+        * outside of <code>acceptAST</code> callbacks, or for top-level types and their
+        * members even within <code>acceptAST</code> callbacks.
+        * </p>
+        * 
+        * @param bindingKeys the binding keys to look up
+        * @return a list of bindings paralleling the <code>bindingKeys</code> parameter,
+        * with <code>null</code> entries for keys that could not be resolved
+        */
+       public final IBinding[] createBindings(String[] bindingKeys) {
+               int length = bindingKeys.length;
+               IBinding[] result = new IBinding[length];
+               for (int i = 0; i < length; i++) {
+                       result[i] = null;
+                       if (this.compilationUnitResolver != null) {
+                               result[i] = this.compilationUnitResolver.createBinding(bindingKeys[i]);
+                       }
+               }
+               return result;
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTSyntaxErrorPropagator.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTSyntaxErrorPropagator.java
new file mode 100644 (file)
index 0000000..1bafc99
--- /dev/null
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 net.sourceforge.phpdt.core.dom;
+
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+
+/**
+ * Internal AST visitor for propagating syntax errors.
+ */
+class ASTSyntaxErrorPropagator extends ASTVisitor {
+
+       private CategorizedProblem[] problems;
+       
+       ASTSyntaxErrorPropagator(CategorizedProblem[] problems) {
+               // visit Javadoc.tags() as well
+               super(true);
+               this.problems = problems;
+       }
+
+       private boolean checkAndTagAsMalformed(ASTNode node) {
+               boolean tagWithErrors = false;
+               search: for (int i = 0, max = this.problems.length; i < max; i++) {
+                       CategorizedProblem problem = this.problems[i];
+                       switch(problem.getID()) {
+                               case IProblem.ParsingErrorOnKeywordNoSuggestion :
+                               case IProblem.ParsingErrorOnKeyword :
+                               case IProblem.ParsingError :
+                               case IProblem.ParsingErrorNoSuggestion :
+                               case IProblem.ParsingErrorInsertTokenBefore :
+                               case IProblem.ParsingErrorInsertTokenAfter :
+                               case IProblem.ParsingErrorDeleteToken :
+                               case IProblem.ParsingErrorDeleteTokens :
+                               case IProblem.ParsingErrorMergeTokens :
+                               case IProblem.ParsingErrorInvalidToken :
+                               case IProblem.ParsingErrorMisplacedConstruct :
+                               case IProblem.ParsingErrorReplaceTokens :
+                               case IProblem.ParsingErrorNoSuggestionForTokens :
+                               case IProblem.ParsingErrorUnexpectedEOF :
+                               case IProblem.ParsingErrorInsertToComplete :
+                               case IProblem.ParsingErrorInsertToCompleteScope :
+                               case IProblem.ParsingErrorInsertToCompletePhrase :
+                               case IProblem.EndOfSource :
+                               case IProblem.InvalidHexa :
+                               case IProblem.InvalidOctal :
+                               case IProblem.InvalidCharacterConstant :
+                               case IProblem.InvalidEscape :
+                               case IProblem.InvalidInput :
+                               case IProblem.InvalidUnicodeEscape :
+                               case IProblem.InvalidFloat :
+                               case IProblem.NullSourceString :
+                               case IProblem.UnterminatedString :
+                               case IProblem.UnterminatedComment :
+                               case IProblem.InvalidDigit :
+                                       break;
+                               default:
+                                       continue search;
+                       }
+                       int position = problem.getSourceStart();
+                       int start = node.getStartPosition();
+                       int end = start + node.getLength();
+                       if ((start <= position) && (position <= end)) {
+                               node.setFlags(node.getFlags() | ASTNode.MALFORMED);
+                               // clear the bits on parent
+                               ASTNode currentNode = node.getParent();
+                               while (currentNode != null) {
+                                       currentNode.setFlags(currentNode.getFlags() & ~ASTNode.MALFORMED);
+                                       currentNode = currentNode.getParent();
+                               }
+                               tagWithErrors = true;
+                       }
+               }
+               return tagWithErrors;
+       }
+
+       /*
+        * Method declared on ASTVisitor.
+        */
+       public boolean visit(FieldDeclaration node) {
+               return checkAndTagAsMalformed(node);            
+       }
+
+       /*
+        * Method declared on ASTVisitor.
+        */
+       public boolean visit(MethodDeclaration node) {
+               return checkAndTagAsMalformed(node);            
+       }
+
+       /*
+        * Method declared on ASTVisitor.
+        */
+       public boolean visit(PackageDeclaration node) {
+               return checkAndTagAsMalformed(node);            
+       }
+
+       /*
+        * Method declared on ASTVisitor.
+        */
+       public boolean visit(ImportDeclaration node) {
+               return checkAndTagAsMalformed(node);            
+       }
+
+       /*
+        * Method declared on ASTVisitor.
+        */
+       public boolean visit(CompilationUnit node) {
+               return checkAndTagAsMalformed(node);            
+       }
+
+       /*
+        * Method declared on ASTVisitor.
+        */
+       public boolean visit(AnnotationTypeDeclaration node) {
+               return checkAndTagAsMalformed(node);            
+       }
+       
+       /*
+        * Method declared on ASTVisitor.
+        */
+       public boolean visit(EnumDeclaration node) {
+               return checkAndTagAsMalformed(node);            
+       }
+       
+       /*
+        * Method declared on ASTVisitor.
+        */
+       public boolean visit(TypeDeclaration node) {
+               return checkAndTagAsMalformed(node);            
+       }
+       
+       /*
+        * Method declared on ASTVisitor.
+        */
+       public boolean visit(Initializer node) {
+               return checkAndTagAsMalformed(node);            
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTVisitor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ASTVisitor.java
new file mode 100644 (file)
index 0000000..217262b
--- /dev/null
@@ -0,0 +1,2573 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * A visitor for abstract syntax trees.
+ * <p>
+ * For each different concrete AST node type <i>T</i> there are
+ * a pair of methods:
+ * <ul>
+ * <li><code>public boolean visit(<i>T</i> node)</code> - Visits
+ * the given node to perform some arbitrary operation. If <code>true</code>
+ * is returned, the given node's child nodes will be visited next; however,
+ * if <code>false</code> is returned, the given node's child nodes will 
+ * not be visited. The default implementation provided by this class does
+ * nothing and returns <code>true</code> (with the exception of 
+ * {@link #visit(Javadoc) ASTVisitor.visit(Javadoc)}).
+ * Subclasses may reimplement this method as needed.</li>
+ * <li><code>public void endVisit(<i>T</i> node)</code> - Visits
+ * the given node to perform some arbitrary operation. When used in the
+ * conventional way, this method is called after all of the given node's
+ * children have been visited (or immediately, if <code>visit</code> returned
+ * <code>false</code>). The default implementation provided by this class does
+ * nothing. Subclasses may reimplement this method as needed.</li>
+ * </ul>
+ * </p>
+ * In addition, there are a pair of methods for visiting AST nodes in the 
+ * abstract, regardless of node type:
+ * <ul>
+ * <li><code>public void preVisit(ASTNode node)</code> - Visits
+ * the given node to perform some arbitrary operation. 
+ * This method is invoked prior to the appropriate type-specific
+ * <code>visit</code> method.
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement this method as needed.</li>
+ * <li><code>public void postVisit(ASTNode node)</code> - Visits
+ * the given node to perform some arbitrary operation. 
+ * This method is invoked after the appropriate type-specific
+ * <code>endVisit</code> method.
+ * The default implementation of this method does nothing.
+ * Subclasses may reimplement this method as needed.</li>
+ * </ul>
+ * <p>
+ * For nodes with list-valued properties, the child nodes within the list
+ * are visited in order. For nodes with multiple properties, the child nodes
+ * are visited in the order that most closely corresponds to the lexical
+ * reading order of the source program. For instance, for a type declaration
+ * node, the child ordering is: name, superclass, superinterfaces, and 
+ * body declarations.
+ * </p>
+ * <p>
+ * While it is possible to modify the tree in the visitor, care is required to
+ * ensure that the consequences are as expected and desirable.
+ * During the course of an ordinary visit starting at a given node, every node
+ * in the subtree is visited exactly twice, first with <code>visit</code> and
+ * then with <code>endVisit</code>. During a traversal of a stationary tree, 
+ * each node is either behind (after <code>endVisit</code>), ahead (before 
+ * <code>visit</code>), or in progress (between <code>visit</code> and
+ * the matching <code>endVisit</code>). Changes to the "behind" region of the
+ * tree are of no consequence to the visit in progress. Changes to the "ahead"
+ * region will be taken in stride. Changes to the "in progress" portion are
+ * the more interesting cases. With a node, the various properties are arranged
+ * in a linear list, with a cursor that separates the properties that have
+ * been visited from the ones that are still to be visited (the cursor
+ * is between the elements, rather than on an element). The cursor moves from
+ * the head to the tail of this list, advancing to the next position just
+ * <i>before</i> <code>visit</code> if called for that child. After the child
+ * subtree has been completely visited, the visit moves on the child 
+ * immediately after the cursor. Removing a child while it is being visited
+ * does not alter the course of the visit. But any children added at positions
+ * after the cursor are considered in the "ahead" portion and will be visited.
+ * </p>
+ * <p>
+ * Cases to watch out for:
+ * <ul>
+ * <li>Moving a child node further down the list. This could result in the
+ * child subtree being visited multiple times; these visits are sequential.</li>
+ * <li>Moving a child node up into an ancestor. If the new home for
+ * the node is in the "ahead" portion, the subtree will be visited 
+ * a second time; again, these visits are sequential.</li>
+ * <li>Moving a node down into a child. If the new home for
+ * the node is in the "ahead" portion, the subtree will be visited 
+ * a second time; in this case, the visits will be nested. In some cases,
+ * this can lead to a stack overflow or out of memory condition.</li>
+ * </ul>
+ * <p>Note that {@link LineComment} and {@link BlockComment} nodes are
+ * not normally visited in an AST because they are not considered
+ * part of main structure of the AST. Use 
+ * {@link CompilationUnit#getCommentList()} to find these additional
+ * comments nodes.
+ * </p>
+ * 
+ * @see org.eclipse.jdt.core.dom.ASTNode#accept(ASTVisitor)
+ */
+public abstract class ASTVisitor {
+
+       /**
+        * Indicates whether doc tags should be visited by default.
+        * @since 3.0
+        */
+       private boolean visitDocTags;
+       
+       /**
+        * Creates a new AST visitor instance.
+        * <p>
+        * For backwards compatibility, the visitor does not visit tag
+        * elements below doc comments by default. Use 
+        * {@link #ASTVisitor(boolean) ASTVisitor(true)}
+        * for an visitor that includes doc comments by default.
+        * </p>
+        */
+       public ASTVisitor() {
+               this(false);
+       }
+       
+       /**
+        * Creates a new AST visitor instance. 
+        * 
+        * @param visitDocTags <code>true</code> if doc comment tags are
+        * to be visited by default, and <code>false</code> otherwise
+        * @see Javadoc#tags()
+        * @see #visit(Javadoc)
+        * @since 3.0
+        */
+       public ASTVisitor(boolean visitDocTags) {
+               this.visitDocTags = visitDocTags;
+       }
+       
+       /**
+        * Visits the given AST node prior to the type-specific visit.
+        * (before <code>visit</code>).
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void preVisit(ASTNode node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * Visits the given AST node following the type-specific visit
+        * (after <code>endVisit</code>).
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void postVisit(ASTNode node) {
+               // default implementation: do nothing
+       }
+
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(AnnotationTypeDeclaration node) {
+               return true;
+       }
+
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(AnnotationTypeMemberDeclaration node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(AnonymousClassDeclaration node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ArrayAccess node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ArrayCreation node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ArrayInitializer node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ArrayType node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(AssertStatement node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(Assignment node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(Block node) {
+               return true;
+       }
+       
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+        * not considered part of main structure of the AST. This method will
+        * only be called if a client goes out of their way to visit this
+        * kind of node explicitly.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.0
+        */
+       public boolean visit(BlockComment node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(BooleanLiteral node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(BreakStatement node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(CastExpression node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(CatchClause node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(CharacterLiteral node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ClassInstanceCreation node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(CompilationUnit node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ConditionalExpression node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ConstructorInvocation node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ContinueStatement node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(DoStatement node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(EmptyStatement node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(EnhancedForStatement node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(EnumConstantDeclaration node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(EnumDeclaration node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ExpressionStatement node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(FieldAccess node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(FieldDeclaration node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ForStatement node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(IfStatement node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ImportDeclaration node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(InfixExpression node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(InstanceofExpression node) {
+               return true;
+       }
+
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(Initializer node) {
+               return true;
+       }
+
+       /**
+        * Visits the given AST node.
+        * <p>
+        * Unlike other node types, the boolean returned by the default
+        * implementation is controlled by a constructor-supplied
+        * parameter  {@link #ASTVisitor(boolean) ASTVisitor(boolean)} 
+        * which is <code>false</code> by default.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @see #ASTVisitor()
+        * @see #ASTVisitor(boolean)
+        */
+       public boolean visit(Javadoc node) {
+               // visit tag elements inside doc comments only if requested
+               return this.visitDocTags;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(LabeledStatement node) {
+               return true;
+       }
+       
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+        * not considered part of main structure of the AST. This method will
+        * only be called if a client goes out of their way to visit this
+        * kind of node explicitly.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.0
+        */
+       public boolean visit(LineComment node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(MarkerAnnotation node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.0
+        */
+       public boolean visit(MemberRef node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(MemberValuePair node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.0
+        */
+       public boolean visit(MethodRef node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.0
+        */
+       public boolean visit(MethodRefParameter node) {
+               return true;
+       }
+       
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(MethodDeclaration node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(MethodInvocation node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(Modifier node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(NormalAnnotation node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(NullLiteral node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(NumberLiteral node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(PackageDeclaration node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(ParameterizedType node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ParenthesizedExpression node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(PostfixExpression node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(PrefixExpression node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(PrimitiveType node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(QualifiedName node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(QualifiedType node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ReturnStatement node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(SimpleName node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(SimpleType node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(SingleMemberAnnotation node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(SingleVariableDeclaration node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(StringLiteral node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(SuperConstructorInvocation node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(SuperFieldAccess node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(SuperMethodInvocation node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(SwitchCase node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(SwitchStatement node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(SynchronizedStatement node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.0
+        */
+       public boolean visit(TagElement node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.0
+        */
+       public boolean visit(TextElement node) {
+               return true;
+       }
+
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ThisExpression node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(ThrowStatement node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(TryStatement node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(TypeDeclaration node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(TypeDeclarationStatement node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(TypeLiteral node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(TypeParameter node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(VariableDeclarationExpression node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(VariableDeclarationStatement node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(VariableDeclarationFragment node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        */
+       public boolean visit(WhileStatement node) {
+               return true;
+       }
+       
+       /**
+        * Visits the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing and return true.
+        * Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @return <code>true</code> if the children of this node should be
+        * visited, and <code>false</code> if the children of this node should
+        * be skipped
+        * @since 3.1
+        */
+       public boolean visit(WildcardType node) {
+               return true;
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(AnnotationTypeDeclaration node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(AnnotationTypeMemberDeclaration node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(AnonymousClassDeclaration node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ArrayAccess node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ArrayCreation node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ArrayInitializer node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ArrayType node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(AssertStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(Assignment node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(Block node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+        * not considered part of main structure of the AST. This method will
+        * only be called if a client goes out of their way to visit this
+        * kind of node explicitly.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.0
+        */
+       public void endVisit(BlockComment node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(BooleanLiteral node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(BreakStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(CastExpression node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(CatchClause node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(CharacterLiteral node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ClassInstanceCreation node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(CompilationUnit node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ConditionalExpression node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ConstructorInvocation node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ContinueStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(DoStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(EmptyStatement node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(EnhancedForStatement node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(EnumConstantDeclaration node) {
+               // default implementation: do nothing
+       }       
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(EnumDeclaration node) {
+               // default implementation: do nothing
+       }       
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ExpressionStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(FieldAccess node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(FieldDeclaration node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ForStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(IfStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ImportDeclaration node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(InfixExpression node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(InstanceofExpression node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(Initializer node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(Javadoc node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(LabeledStatement node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * <p>Note: {@link LineComment} and {@link BlockComment} nodes are
+        * not considered part of main structure of the AST. This method will
+        * only be called if a client goes out of their way to visit this
+        * kind of node explicitly.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.0
+        */
+       public void endVisit(LineComment node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(MarkerAnnotation node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.0
+        */
+       public void endVisit(MemberRef node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(MemberValuePair node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.0
+        */
+       public void endVisit(MethodRef node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.0
+        */
+       public void endVisit(MethodRefParameter node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(MethodDeclaration node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(MethodInvocation node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(Modifier node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(NormalAnnotation node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(NullLiteral node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(NumberLiteral node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(PackageDeclaration node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(ParameterizedType node) {
+               // default implementation: do nothing
+       }       
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ParenthesizedExpression node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(PostfixExpression node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(PrefixExpression node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(PrimitiveType node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(QualifiedName node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(QualifiedType node) {
+               // default implementation: do nothing
+       }       
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ReturnStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(SimpleName node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(SimpleType node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(SingleMemberAnnotation node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(SingleVariableDeclaration node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(StringLiteral node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(SuperConstructorInvocation node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(SuperFieldAccess node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(SuperMethodInvocation node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(SwitchCase node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(SwitchStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(SynchronizedStatement node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.0
+        */
+       public void endVisit(TagElement node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.0
+        */
+       public void endVisit(TextElement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ThisExpression node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(ThrowStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(TryStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(TypeDeclaration node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(TypeDeclarationStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(TypeLiteral node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(TypeParameter node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(VariableDeclarationExpression node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(VariableDeclarationStatement node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(VariableDeclarationFragment node) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        */
+       public void endVisit(WhileStatement node) {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * End of visit the given type-specific AST node.
+        * <p>
+        * The default implementation does nothing. Subclasses may reimplement.
+        * </p>
+        * 
+        * @param node the node to visit
+        * @since 3.1
+        */
+       public void endVisit(WildcardType node) {
+               // default implementation: do nothing
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AbstractTypeDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AbstractTypeDeclaration.java
new file mode 100644 (file)
index 0000000..14963ea
--- /dev/null
@@ -0,0 +1,256 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.List;
+
+/**
+ * Abstract subclass for type declaration, enum declaration,
+ * and annotation type declaration AST node types.
+ * <pre>
+ * AbstractTypeDeclaration:
+ *             TypeDeclaration
+ *             EnumDeclaration
+ *             AnnotationTypeDeclaration
+ * </pre>
+ * 
+ * @since 3.0
+ */
+public abstract class AbstractTypeDeclaration extends BodyDeclaration {
+       
+       /**
+        * The type name; lazily initialized; defaults to a unspecified,
+        * legal Java class identifier.
+        * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+        */
+       SimpleName typeName = null;
+
+       /**
+        * The body declarations (element type: <code>BodyDeclaration</code>).
+        * Defaults to an empty list.
+        * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+        */
+       ASTNode.NodeList bodyDeclarations;
+
+       /**
+        * Returns structural property descriptor for the "bodyDeclarations" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        */
+       abstract ChildListPropertyDescriptor internalBodyDeclarationsProperty();
+
+       /**
+        * Returns structural property descriptor for the "bodyDeclarations" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        * @since 3.1
+        */
+       public final ChildListPropertyDescriptor getBodyDeclarationsProperty() {
+               return internalBodyDeclarationsProperty();
+       }
+
+       /**
+        * Returns structural property descriptor for the "name" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        */
+       abstract ChildPropertyDescriptor internalNameProperty();
+       
+       /**
+        * Returns structural property descriptor for the "name" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        * @since 3.1
+        */
+       public final ChildPropertyDescriptor getNameProperty() {
+               return internalNameProperty();
+       }
+       
+       /**
+        * Creates and returns a structural property descriptor for the
+        * "bodyDeclaration" property declared on the given concrete node type.
+        * 
+        * @return the property descriptor
+        */
+       static final ChildListPropertyDescriptor internalBodyDeclarationPropertyFactory(Class nodeClass) {
+               return new ChildListPropertyDescriptor(nodeClass, "bodyDeclarations", BodyDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+       }
+       
+       /**
+        * Creates and returns a structural property descriptor for the
+        * "name" property declared on the given concrete node type.
+        * 
+        * @return the property descriptor
+        */
+       static final ChildPropertyDescriptor internalNamePropertyFactory(Class nodeClass) {
+               return new ChildPropertyDescriptor(nodeClass, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+       }
+       
+       /**
+        * Creates a new AST node for an abstract type declaration owned by the given 
+        * AST.
+        * <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
+        */
+       AbstractTypeDeclaration(AST ast) {
+               super(ast);
+               this.bodyDeclarations = new ASTNode.NodeList(internalBodyDeclarationsProperty());
+       }
+
+       /**
+        * Returns the name of the type declared in this type declaration.
+        * 
+        * @return the type name node
+        * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+        */ 
+       public SimpleName getName() {
+               if (this.typeName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.typeName == null) {
+                                       preLazyInit();
+                                       this.typeName = new SimpleName(this.ast);
+                                       postLazyInit(this.typeName, internalNameProperty());
+                               }
+                       }
+               }
+               return this.typeName;
+       }
+               
+       /**
+        * Sets the name of the type declared in this type declaration to the
+        * given name.
+        * 
+        * @param typeName the new type name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+        */ 
+       public void setName(SimpleName typeName) {
+               if (typeName == null) {
+                       throw new IllegalArgumentException();
+               }
+               ChildPropertyDescriptor p = internalNameProperty();
+               ASTNode oldChild = this.typeName;
+               preReplaceChild(oldChild, typeName, p);
+               this.typeName = typeName;
+               postReplaceChild(oldChild, typeName, p);
+       }
+
+       /**
+        * Returns the live ordered list of body declarations of this type 
+        * declaration.
+        * 
+        * @return the live list of body declarations
+        *    (element type: <code>BodyDeclaration</code>)
+        * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+        */ 
+       public List bodyDeclarations() {
+               return this.bodyDeclarations;
+       }
+       
+       /**
+        * Returns whether this type declaration is a package member (that is,
+        * a top-level type).
+        * <p>
+        * Note that this is a convenience method that simply checks whether
+        * this node's parent is a compilation unit node.
+        * </p>
+        * 
+        * @return <code>true</code> if this type declaration is a child of
+        *   a compilation unit node, and <code>false</code> otherwise
+        * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+        */
+       public boolean isPackageMemberTypeDeclaration() {
+               ASTNode parent = getParent();
+               return (parent instanceof CompilationUnit);
+       }
+
+       /**
+        * Returns whether this type declaration is a type member.
+        * <p>
+        * Note that this is a convenience method that simply checks whether
+        * this node's parent is a type declaration node or an anonymous 
+        * class declaration.
+        * </p>
+        * 
+        * @return <code>true</code> if this type declaration is a child of
+        *   a type declaration node or an anonymous class declaration node,
+        *   and <code>false</code> otherwise
+        * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+        */
+       public boolean isMemberTypeDeclaration() {
+               ASTNode parent = getParent();
+               return (parent instanceof AbstractTypeDeclaration)
+                       || (parent instanceof AnonymousClassDeclaration);
+       }
+
+       /**
+        * Returns whether this type declaration is a local type.
+        * <p>
+        * Note that this is a convenience method that simply checks whether
+        * this node's parent is a type declaration statement node.
+        * </p>
+        * 
+        * @return <code>true</code> if this type declaration is a child of
+        *   a type declaration statement node, and <code>false</code> otherwise
+        * @since 2.0 (originally declared on <code>TypeDeclaration</code>)
+        */
+       public boolean isLocalTypeDeclaration() {
+               ASTNode parent = getParent();
+               return (parent instanceof TypeDeclarationStatement);
+       }
+       
+       /**
+        * Resolves and returns the binding for the type declared in this type
+        * declaration.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        * @since 3.1 Declared in 3.0 on the individual subclasses.
+        */     
+       public final ITypeBinding resolveBinding() {
+               return internalResolveBinding();
+       }
+       
+       /**
+        * Resolves and returns the binding for the type declared in this type
+        * declaration. This method must be implemented by subclasses.
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       abstract ITypeBinding internalResolveBinding();
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 2 * 4;
+       }
+       
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Annotation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Annotation.java
new file mode 100644 (file)
index 0000000..068ff80
--- /dev/null
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Abstract base class of AST nodes that represent annotations.
+ * <p>
+ * <pre>
+ * Annotation:
+ *             NormalAnnotation
+ *             MarkerAnnotation
+ *             SingleMemberAnnotation
+ * </pre>
+ * </p>
+ * @since 3.1
+ */
+public abstract class Annotation extends Expression implements IExtendedModifier {
+       
+       /**
+        * Returns structural property descriptor for the "typeName" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        */
+       abstract ChildPropertyDescriptor internalTypeNameProperty();
+
+       /**
+        * Returns structural property descriptor for the "typeName" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        */
+       public final ChildPropertyDescriptor getTypeNameProperty() {
+               return internalTypeNameProperty();
+       }
+
+       /**
+        * Creates and returns a structural property descriptor for the
+        * "typeName" property declared on the given concrete node type.
+        * 
+        * @return the property descriptor
+        */
+       static final ChildPropertyDescriptor internalTypeNamePropertyFactory(Class nodeClass) {
+               return new ChildPropertyDescriptor(nodeClass, "typeName", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+       }
+       
+       /**
+        * The annotation type name; lazily initialized; defaults to an unspecified,
+        * legal Java identifier.
+        */
+       Name typeName = null;
+
+       /**
+        * Creates a new AST node for an annotation node owned by the 
+        * given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       Annotation(AST ast) {
+               super(ast);
+       }
+       
+       /**
+        * @see IExtendedModifier#isModifier()
+        */ 
+       public boolean isModifier() {
+               return false;
+       }
+       
+       /**
+        * @see IExtendedModifier#isAnnotation()
+        */ 
+       public boolean isAnnotation() {
+               return true;
+       }
+
+       /**
+        * Returns the annotation type name of this annotation.
+        * 
+        * @return the annotation type name
+        */ 
+       public Name getTypeName() {
+               if (this.typeName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.typeName == null) {
+                                       preLazyInit();
+                                       this.typeName = new SimpleName(this.ast);
+                                       postLazyInit(this.typeName, internalTypeNameProperty());
+                               }
+                       }
+               }
+               return this.typeName;
+       }
+       
+       /**
+        * Sets the annotation type name of this annotation.
+        * 
+        * @param typeName the annotation type name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setTypeName(Name typeName) {
+               if (typeName == null) {
+                       throw new IllegalArgumentException();
+               }
+               ChildPropertyDescriptor p = internalTypeNameProperty();
+               ASTNode oldChild = this.typeName;
+               preReplaceChild(oldChild, typeName, p);
+               this.typeName = typeName;
+               postReplaceChild(oldChild, typeName, p);
+       }
+
+       /**
+        * Returns whether this is a normal annotation
+        * ({@link NormalAnnotation}).
+        * 
+        * @return <code>true</code> if this is a normal annotation,
+        *    and <code>false</code> otherwise
+        */ 
+       public boolean isNormalAnnotation() {
+               return (this instanceof NormalAnnotation);
+       }
+
+       /**
+        * Returns whether this is a marker annotation
+        * ({@link MarkerAnnotation}).
+        * 
+        * @return <code>true</code> if this is a marker annotation,
+        *    and <code>false</code> otherwise
+        */ 
+       public boolean isMarkerAnnotation() {
+               return (this instanceof MarkerAnnotation);
+       }
+
+       /**
+        * Returns whether this is a single member annotation.
+        * ({@link SingleMemberAnnotation}).
+        * 
+        * @return <code>true</code> if this is a single member annotation,
+        *    and <code>false</code> otherwise
+        */ 
+       public boolean isSingleMemberAnnotation() {
+               return (this instanceof SingleMemberAnnotation);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 1 * 4;
+       }
+
+       /**
+        * Resolves and returns the resolved annotation for this annotation.
+        * <p>
+        * Note that bindings (which includes resolved annotations) are generally unavailable unless
+        * requested when the AST is being built.
+        * </p>
+        * 
+        * @return the resolved annotation, or <code>null</code> if the annotation cannot be resolved
+        * @since 3.2
+        */     
+       public IAnnotationBinding resolveAnnotationBinding() {
+           return this.ast.getBindingResolver().resolveAnnotation(this);
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnnotationBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnnotationBinding.java
new file mode 100644 (file)
index 0000000..1053734
--- /dev/null
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 BEA Systems, Inc.
+ * 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:
+ *    tyeung@bea.com - initial API and implementation
+ *    IBM Corporation - implemented methods from IBinding
+ *    IBM Corporation - renamed from ResolvedAnnotation to AnnotationBinding
+ *******************************************************************************/
+package net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.IAnnotatable;
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.internal.compiler.lookup.ElementValuePair;
+import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TagBits;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+/**
+ * Internal class
+ */
+class AnnotationBinding implements IAnnotationBinding {
+       static final AnnotationBinding[] NoAnnotations = new AnnotationBinding[0];
+       private net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding binding;
+       private BindingResolver bindingResolver;
+       private String key;
+
+       AnnotationBinding(net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding annotation, BindingResolver resolver) {
+               if (annotation == null)
+                       throw new IllegalStateException();
+               binding = annotation;
+               bindingResolver = resolver;
+       }
+       
+       public IAnnotationBinding[] getAnnotations() {
+               return NoAnnotations;
+       }
+
+       public ITypeBinding getAnnotationType() {
+               ITypeBinding typeBinding = this.bindingResolver.getTypeBinding(this.binding.getAnnotationType());
+               if (typeBinding == null)
+                       return null;
+               return typeBinding;
+       }
+       
+       public IMemberValuePairBinding[] getDeclaredMemberValuePairs() {
+               ReferenceBinding typeBinding = this.binding.getAnnotationType();
+               if (typeBinding == null || ((typeBinding.tagBits & TagBits.HasMissingType) != 0)) {
+                       return MemberValuePairBinding.NoPair;
+               }
+               ElementValuePair[] internalPairs = this.binding.getElementValuePairs();
+               int length = internalPairs.length;
+               IMemberValuePairBinding[] pairs = length == 0 ? MemberValuePairBinding.NoPair : new MemberValuePairBinding[length];
+               int counter = 0;
+               for (int i = 0; i < length; i++) {
+                       ElementValuePair valuePair = internalPairs[i];
+                       if (valuePair.binding == null) continue;
+                       pairs[counter++] = this.bindingResolver.getMemberValuePairBinding(valuePair);
+               }
+               if (counter == 0) return MemberValuePairBinding.NoPair;
+               if (counter != length) {
+                       // resize
+                       System.arraycopy(pairs, 0, (pairs = new MemberValuePairBinding[counter]), 0, counter);
+               }
+               return pairs;
+       }
+
+       public IMemberValuePairBinding[] getAllMemberValuePairs() {
+               IMemberValuePairBinding[] pairs = getDeclaredMemberValuePairs();
+               ReferenceBinding typeBinding = this.binding.getAnnotationType();
+               if (typeBinding == null || ((typeBinding.tagBits & TagBits.HasMissingType) != 0)) return pairs;
+               MethodBinding[] methods = typeBinding.availableMethods(); // resilience
+               int methodLength = methods == null ? 0 : methods.length;
+               if (methodLength == 0) return pairs;
+
+               int declaredLength = pairs.length;
+               if (declaredLength == methodLength)
+                       return pairs;
+
+               HashtableOfObject table = new HashtableOfObject(declaredLength);
+               for (int i = 0; i < declaredLength; i++) {
+                       char[] internalName = ((MemberValuePairBinding) pairs[i]).internalName();
+                       if (internalName == null) continue;
+                       table.put(internalName, pairs[i]);
+               }
+
+               // handle case of more methods than declared members
+               IMemberValuePairBinding[] allPairs = new  IMemberValuePairBinding[methodLength];
+               for (int i = 0; i < methodLength; i++) {
+                       Object pair = table.get(methods[i].selector);
+                       allPairs[i] = pair == null ? new DefaultValuePairBinding(methods[i], this.bindingResolver) : (IMemberValuePairBinding) pair;
+               }
+               return allPairs;
+       }
+       
+       public IJavaElement getJavaElement() {
+               if (!(this.bindingResolver instanceof DefaultBindingResolver)) return null;
+               ASTNode node = (ASTNode) ((DefaultBindingResolver) this.bindingResolver).bindingsToAstNodes.get(this);
+               if (!(node instanceof Annotation)) return null;
+               ASTNode parent = node.getParent();
+               IJavaElement parentElement = null;
+               switch (parent.getNodeType()) {
+               case ASTNode.PACKAGE_DECLARATION:
+                       IJavaElement cu = ((CompilationUnit) parent.getParent()).getJavaElement();
+                       if (cu instanceof ICompilationUnit) {
+                               String pkgName = ((PackageDeclaration) parent).getName().getFullyQualifiedName();
+                               parentElement =  ((ICompilationUnit) cu).getPackageDeclaration(pkgName);
+                       }
+                       break;
+               case ASTNode.TYPE_DECLARATION:
+                       parentElement = ((TypeDeclaration) parent).resolveBinding().getJavaElement();
+                       break;
+               case ASTNode.FIELD_DECLARATION:
+                       VariableDeclarationFragment fragment = (VariableDeclarationFragment) ((FieldDeclaration) parent).fragments().get(0);
+                       parentElement = fragment.resolveBinding().getJavaElement();
+                       break;
+               case ASTNode.METHOD_DECLARATION:
+                       parentElement = ((MethodDeclaration) parent).resolveBinding().getJavaElement();
+                       break;
+               case ASTNode.VARIABLE_DECLARATION_STATEMENT:
+                       fragment = (VariableDeclarationFragment) ((VariableDeclarationStatement) parent).fragments().get(0);
+                       parentElement = fragment.resolveBinding().getJavaElement();
+                       break;
+               default:
+                       return null;
+               }
+               if (! (parentElement instanceof IAnnotatable)) return null;
+               return ((IAnnotatable) parentElement).getAnnotation(getName());
+       }
+
+       public String getKey() {
+               if (this.key == null) {
+                       String recipientKey = getRecipientKey();
+                       this.key = new String(this.binding.computeUniqueKey(recipientKey.toCharArray()));
+               }
+               return this.key;
+       }
+       
+       private String getRecipientKey() {
+               if (!(this.bindingResolver instanceof DefaultBindingResolver)) return ""; //$NON-NLS-1$
+               DefaultBindingResolver resolver = (DefaultBindingResolver) this.bindingResolver;
+               ASTNode node = (ASTNode) resolver.bindingsToAstNodes.get(this);
+               if (node == null) {
+                       // Can happen if annotation bindings have been resolved before having parsed the declaration
+                       return ""; //$NON-NLS-1$
+               }
+               ASTNode recipient = node.getParent();
+               switch (recipient.getNodeType()) {
+               case ASTNode.PACKAGE_DECLARATION:
+                       String pkgName = ((PackageDeclaration) recipient).getName().getFullyQualifiedName();
+                       return pkgName.replace('.', '/');
+               case ASTNode.TYPE_DECLARATION:
+                       return ((TypeDeclaration) recipient).resolveBinding().getKey();
+               case ASTNode.FIELD_DECLARATION:
+                       VariableDeclarationFragment fragment = (VariableDeclarationFragment) ((FieldDeclaration) recipient).fragments().get(0);
+                       return fragment.resolveBinding().getKey();
+               case ASTNode.METHOD_DECLARATION:
+                       return ((MethodDeclaration) recipient).resolveBinding().getKey();
+               case ASTNode.VARIABLE_DECLARATION_STATEMENT:
+                       fragment = (VariableDeclarationFragment) ((VariableDeclarationStatement) recipient).fragments().get(0);
+                       return fragment.resolveBinding().getKey();
+               default:
+                       return ""; //$NON-NLS-1$
+               }
+       }
+
+       public int getKind() {
+               return IBinding.ANNOTATION;
+       }
+
+       public int getModifiers() {
+               return Modifier.NONE;
+       }
+
+       public String getName() {
+               ITypeBinding annotationType = getAnnotationType();
+               if (annotationType == null) {
+                       return new String(this.binding.getAnnotationType().sourceName());
+               } else {
+                       return annotationType.getName();
+               }
+       }
+       
+       public boolean isDeprecated() {
+               ReferenceBinding typeBinding = this.binding.getAnnotationType();
+               if (typeBinding == null) return false;
+               return typeBinding.isDeprecated();
+       }
+       
+       public boolean isEqualTo(IBinding otherBinding) {
+               if (this == otherBinding)
+                       return true;
+               if (otherBinding.getKind() != IBinding.ANNOTATION)
+                       return false;
+               IAnnotationBinding other = (IAnnotationBinding) otherBinding;
+               if (!getAnnotationType().isEqualTo(other.getAnnotationType()))
+                       return false;
+               IMemberValuePairBinding[] memberValuePairs = getDeclaredMemberValuePairs();
+               IMemberValuePairBinding[] otherMemberValuePairs = other.getDeclaredMemberValuePairs();
+               if (memberValuePairs.length != otherMemberValuePairs.length)
+                       return false;
+               for (int i = 0, length = memberValuePairs.length; i < length; i++) {
+                       if (!memberValuePairs[i].isEqualTo(otherMemberValuePairs[i]))
+                               return false;
+               }
+               return true;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.IBinding#isRecovered()
+        */
+       public boolean isRecovered() {
+        ReferenceBinding annotationType = binding.getAnnotationType();
+        return annotationType == null || (annotationType.tagBits & TagBits.HasMissingType) != 0;       }
+
+       public boolean isSynthetic() {
+               return false;
+       }
+
+       public String toString() {
+               ITypeBinding type = getAnnotationType();
+               final StringBuffer buffer = new StringBuffer();
+               buffer.append('@');
+               if (type != null)
+                       buffer.append(type.getName());
+               buffer.append('(');
+               IMemberValuePairBinding[] pairs = getDeclaredMemberValuePairs();
+               for (int i = 0, len = pairs.length; i < len; i++) {
+                       if (i != 0)
+                               buffer.append(", "); //$NON-NLS-1$
+                       buffer.append(pairs[i].toString());
+               }
+               buffer.append(')');
+               return buffer.toString();
+       }
+       
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnnotationTypeDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnnotationTypeDeclaration.java
new file mode 100644 (file)
index 0000000..380593d
--- /dev/null
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Annotation type declaration AST node type (added in JLS3 API).
+ * <pre>
+ * AnnotationTypeDeclaration:
+ *   [ Javadoc ] { ExtendedModifier } <b>@</b> <b>interface</b> Identifier
+ *             <b>{</b> { AnnotationTypeBodyDeclaration | <b>;</b> } <b>}</b>
+ * AnnotationTypeBodyDeclaration:
+ *   AnnotationTypeMemberDeclaration
+ *   FieldDeclaration
+ *   TypeDeclaration
+ *   EnumDeclaration
+ *   AnnotationTypeDeclaration
+ * </pre>
+ * <p>
+ * The thing to note is that method declaration are replaced
+ * by annotation type member declarations in this context.
+ * </p>
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the first modifier keyword (if modifiers), or the
+ * first character of the "@interface" (if no
+ * modifiers). The source range extends through the last character of the "}"
+ * token following the body declarations.
+ * </p>
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class AnnotationTypeDeclaration extends AbstractTypeDeclaration {
+       
+       /**
+        * The "javadoc" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
+               internalJavadocPropertyFactory(AnnotationTypeDeclaration.class);
+
+       /**
+        * The "modifiers" structural property of this node type.
+        */
+       public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
+               internalModifiers2PropertyFactory(AnnotationTypeDeclaration.class);
+       
+       /**
+        * The "name" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               internalNamePropertyFactory(AnnotationTypeDeclaration.class);
+
+       /**
+        * The "bodyDeclarations" structural property of this node type.
+        */
+       public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY = 
+               internalBodyDeclarationPropertyFactory(AnnotationTypeDeclaration.class);
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(5);
+               createPropertyList(AnnotationTypeDeclaration.class, properyList);
+               addProperty(JAVADOC_PROPERTY, properyList);
+               addProperty(MODIFIERS2_PROPERTY, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               addProperty(BODY_DECLARATIONS_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})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                       
+       /**
+        * Creates a new AST node for an annotation type declaration owned by the given 
+        * AST. By default, the type declaration is for an annotation
+        * type of an unspecified, but legal, name; no modifiers; no javadoc; 
+        * and an empty list of body 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
+        */
+       AnnotationTypeDeclaration(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == JAVADOC_PROPERTY) {
+                       if (get) {
+                               return getJavadoc();
+                       } else {
+                               setJavadoc((Javadoc) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == MODIFIERS2_PROPERTY) {
+                       return modifiers();
+               }
+               if (property == BODY_DECLARATIONS_PROPERTY) {
+                       return bodyDeclarations();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildPropertyDescriptor internalJavadocProperty() {
+               return JAVADOC_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildListPropertyDescriptor internalModifiers2Property() {
+               return MODIFIERS2_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final SimplePropertyDescriptor internalModifiersProperty() {
+               // this property will not be asked for (node type did not exist in JLS2)
+               return null;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on AbstractTypeDeclaration.
+        */
+       final ChildPropertyDescriptor internalNameProperty() {
+               return NAME_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on AbstractTypeDeclaration.
+        */
+       final ChildListPropertyDescriptor internalBodyDeclarationsProperty() {
+               return BODY_DECLARATIONS_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return ANNOTATION_TYPE_DECLARATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               AnnotationTypeDeclaration result = new AnnotationTypeDeclaration(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setJavadoc(
+                       (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+               result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+               result.setName((SimpleName) getName().clone(target));
+               result.bodyDeclarations().addAll(ASTNode.copySubtrees(target, bodyDeclarations()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getJavadoc());
+                       acceptChildren(visitor, this.modifiers);
+                       acceptChild(visitor, getName());
+                       acceptChildren(visitor, this.bodyDeclarations);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on AsbtractTypeDeclaration.
+        */
+       ITypeBinding internalResolveBinding() {
+               return this.ast.getBindingResolver().resolveType(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize();
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+                       + this.modifiers.listSize()
+                       + (this.typeName == null ? 0 : getName().treeSize())
+                       + this.bodyDeclarations.listSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnnotationTypeMemberDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnnotationTypeMemberDeclaration.java
new file mode 100644 (file)
index 0000000..54d855a
--- /dev/null
@@ -0,0 +1,417 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Annotation type member declaration AST node type (added in JLS3 API).
+ * <pre>
+ * AnnotationTypeMemberDeclaration:
+ *   [ Javadoc ] { ExtendedModifier }
+ *       Type Identifier <b>(</b> <b>)</b> [ <b>default</b> Expression ] <b>;</b>
+ * </pre>
+ * <p>
+ * Note that annotation type member declarations are only meaningful as
+ * elements of {@link AnnotationTypeDeclaration#bodyDeclarations()}.
+ * </p>
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the first modifier keyword (if modifiers), 
+ * or the first character of the member type (no modifiers). 
+ * The source range extends through the last character of the
+ * ";" token.
+ * </p>
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class AnnotationTypeMemberDeclaration extends BodyDeclaration {
+       
+       /**
+        * The "javadoc" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
+               internalJavadocPropertyFactory(AnnotationTypeMemberDeclaration.class);
+
+       /**
+        * The "modifiers" structural property of this node type.
+        */
+       public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
+               internalModifiers2PropertyFactory(AnnotationTypeMemberDeclaration.class);
+       
+       /**
+        * The "name" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(AnnotationTypeMemberDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "type" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(AnnotationTypeMemberDeclaration.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "default" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor DEFAULT_PROPERTY = 
+               new ChildPropertyDescriptor(AnnotationTypeMemberDeclaration.class, "default", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(6);
+               createPropertyList(AnnotationTypeMemberDeclaration.class, properyList);
+               addProperty(JAVADOC_PROPERTY, properyList);
+               addProperty(MODIFIERS2_PROPERTY, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               addProperty(TYPE_PROPERTY, properyList);
+               addProperty(DEFAULT_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})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                                               
+       /**
+        * The member name; lazily initialized; defaults to an unspecified,
+        * legal Java identifier.
+        */
+       private SimpleName memberName = null;
+
+       /**
+        * The member type; lazily initialized; defaults to int.
+        */
+       private Type memberType = null;
+       
+       /**
+        * The optional default expression; <code>null</code> for none; defaults to none.
+        */
+       private Expression optionalDefaultValue = null;
+       
+       /**
+        * Creates a new AST node for an annotation type member declaration owned 
+        * by the given AST. By default, the declaration is for a member of an
+        * unspecified, but legal, name; no modifiers; no javadoc;
+        * an unspecified value type; and no default value.
+        * <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
+        */
+       AnnotationTypeMemberDeclaration(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == JAVADOC_PROPERTY) {
+                       if (get) {
+                               return getJavadoc();
+                       } else {
+                               setJavadoc((Javadoc) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) child);
+                               return null;
+                       }
+               }
+               if (property == TYPE_PROPERTY) {
+                       if (get) {
+                               return getType();
+                       } else {
+                               setType((Type) child);
+                               return null;
+                       }
+               }
+               if (property == DEFAULT_PROPERTY) {
+                       if (get) {
+                               return getDefault();
+                       } else {
+                               setDefault((Expression) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == MODIFIERS2_PROPERTY) {
+                       return modifiers();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildPropertyDescriptor internalJavadocProperty() {
+               return JAVADOC_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildListPropertyDescriptor internalModifiers2Property() {
+               return MODIFIERS2_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final SimplePropertyDescriptor internalModifiersProperty() {
+               // this property will not be asked for (node type did not exist in JLS2)
+               return null;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return ANNOTATION_TYPE_MEMBER_DECLARATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               AnnotationTypeMemberDeclaration result = new AnnotationTypeMemberDeclaration(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setJavadoc(
+                       (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+               result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+               result.setType((Type) ASTNode.copySubtree(target, getType()));
+               result.setName((SimpleName) getName().clone(target));
+               result.setDefault((Expression) ASTNode.copySubtree(target, getDefault()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getJavadoc());
+                       acceptChildren(visitor, this.modifiers);
+                       acceptChild(visitor, getType());
+                       acceptChild(visitor, getName());
+                       acceptChild(visitor, getDefault());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the name of the annotation type member declared in this declaration.
+        * 
+        * @return the member name node
+        */ 
+       public SimpleName getName() {
+               if (this.memberName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.memberName == null) {
+                                       preLazyInit();
+                                       this.memberName = new SimpleName(this.ast);
+                                       postLazyInit(this.memberName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.memberName;
+       }
+       
+       /**
+        * Sets the name of the annotation type member declared in this declaration to the
+        * given name.
+        * 
+        * @param memberName the new member name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName memberName) {
+               if (memberName == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.memberName;
+               preReplaceChild(oldChild, memberName, NAME_PROPERTY);
+               this.memberName = memberName;
+               postReplaceChild(oldChild, memberName, NAME_PROPERTY);
+       }
+
+       /**
+        * Returns the type of the annotation type member declared in this 
+        * declaration.
+        * 
+        * @return the type of the member
+        */ 
+       public Type getType() {
+               if (this.memberType == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.memberType == null) {
+                                       preLazyInit();
+                                       this.memberType = this.ast.newPrimitiveType(PrimitiveType.INT);
+                                       postLazyInit(this.memberType, TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.memberType;
+       }
+
+       /**
+        * Sets the type of the annotation type member declared in this declaration
+        * to the given type.
+        * 
+        * @param type the new member type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setType(Type type) {
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.memberType;
+               preReplaceChild(oldChild, type, TYPE_PROPERTY);
+               this.memberType = type;
+               postReplaceChild(oldChild, type, TYPE_PROPERTY);
+       }
+
+       /**
+        * Returns the default value of this annotation type member, or 
+        * <code>null</code> if there is none.
+        * 
+        * @return the expression node, or <code>null</code> if there is none
+        */ 
+       public Expression getDefault() {
+               return this.optionalDefaultValue;
+       }
+       
+       /**
+        * Sets or clears the default value of this annotation type member.
+        * 
+        * @param defaultValue the expression node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setDefault(Expression defaultValue) {
+               // a AnnotationTypeMemberDeclaration may occur inside an Expression - must check cycles
+               ASTNode oldChild = this.optionalDefaultValue;
+               preReplaceChild(oldChild, defaultValue, DEFAULT_PROPERTY);
+               this.optionalDefaultValue = defaultValue;
+               postReplaceChild(oldChild, defaultValue, DEFAULT_PROPERTY);
+       }
+       
+       /**
+        * Resolves and returns the binding for the annotation type member declared
+        * in this declaration.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public IMethodBinding resolveBinding() {
+               return this.ast.getBindingResolver().resolveMember(this);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+                       + this.modifiers.listSize()
+                       + (this.memberName == null ? 0 : getName().treeSize())
+                       + (this.memberType == null ? 0 : getType().treeSize())
+                       + (this.optionalDefaultValue == null ? 0 : getDefault().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnonymousClassDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AnonymousClassDeclaration.java
new file mode 100644 (file)
index 0000000..a17a637
--- /dev/null
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Anonymous class declaration AST node type. For JLS2, this type of node appears
+ * only as a child on a class instance creation expression.
+ * For JLS3, this type of node appears may also appear as the child of
+ * an enum constant declaration.
+ *
+ * <pre>
+ * AnonymousClassDeclaration:
+ *        <b>{</b> ClassBodyDeclaration <b>}</b>
+ * </pre>
+ * 
+ * @see ClassInstanceCreation
+ * @see EnumConstantDeclaration
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class AnonymousClassDeclaration extends ASTNode {
+
+       /**
+        * The "bodyDeclarations" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY = 
+               new ChildListPropertyDescriptor(AnonymousClassDeclaration.class, "bodyDeclarations", BodyDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(2);
+               createPropertyList(AnonymousClassDeclaration.class, properyList);
+               addProperty(BODY_DECLARATIONS_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 body declarations (element type: <code>BodyDeclaration</code>).
+        * Defaults to none.
+        */
+       private ASTNode.NodeList bodyDeclarations = 
+               new ASTNode.NodeList(BODY_DECLARATIONS_PROPERTY);
+
+       /**
+        * Creates a new AST node for an anonymous class declaration owned 
+        * by the given AST. By default, the list of body declarations is empty.
+        * <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
+        */
+       AnonymousClassDeclaration(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == BODY_DECLARATIONS_PROPERTY) {
+                       return bodyDeclarations();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return ANONYMOUS_CLASS_DECLARATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               AnonymousClassDeclaration result = new AnonymousClassDeclaration(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.bodyDeclarations().addAll(
+                       ASTNode.copySubtrees(target, bodyDeclarations()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChildren(visitor, bodyDeclarations);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the live ordered list of body declarations of this
+        * anonymous class declaration.
+        * 
+        * @return the live list of body declarations
+        *    (element type: <code>BodyDeclaration</code>)
+        */ 
+       public List bodyDeclarations() {
+               return this.bodyDeclarations;
+       }
+
+       /**
+        * Resolves and returns the binding for the anonymous class declared in
+        * this declaration.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public ITypeBinding resolveBinding() {
+               return this.ast.getBindingResolver().resolveType(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + this.bodyDeclarations.listSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayAccess.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayAccess.java
new file mode 100644 (file)
index 0000000..278a80e
--- /dev/null
@@ -0,0 +1,271 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Array access expression AST node type.
+ *
+ * <pre>
+ * ArrayAccess:
+ *    Expression <b>[</b> Expression <b>]</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ArrayAccess extends Expression {
+       
+       /**
+        * The "array" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor ARRAY_PROPERTY = 
+               new ChildPropertyDescriptor(ArrayAccess.class, "array", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "index" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor INDEX_PROPERTY = 
+               new ChildPropertyDescriptor(ArrayAccess.class, "index", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(3);
+               createPropertyList(ArrayAccess.class, properyList);
+               addProperty(ARRAY_PROPERTY, properyList);
+               addProperty(INDEX_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 array expression; lazily initialized; defaults to an unspecified,
+        * but legal, expression.
+        */
+       private Expression arrayExpression = null;
+
+       /**
+        * The index expression; lazily initialized; defaults to an unspecified,
+        * but legal, expression.
+        */
+       private Expression indexExpression = null;
+
+       /**
+        * Creates a new unparented array access expression node owned by the given 
+        * AST. By default, the array and index expresssions are unspecified, 
+        * but legal.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ArrayAccess(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == ARRAY_PROPERTY) {
+                       if (get) {
+                               return getArray();
+                       } else {
+                               setArray((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == INDEX_PROPERTY) {
+                       if (get) {
+                               return getIndex();
+                       } else {
+                               setIndex((Expression) 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.
+        */
+       final int getNodeType0() {
+               return ARRAY_ACCESS;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ArrayAccess result = new ArrayAccess(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setArray((Expression) getArray().clone(target));
+               result.setIndex((Expression) getIndex().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getArray());
+                       acceptChild(visitor, getIndex());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the array expression of this array access expression.
+        * 
+        * @return the array expression node
+        */ 
+       public Expression getArray() {
+               if (this.arrayExpression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.arrayExpression == null) {
+                                       preLazyInit();
+                                       this.arrayExpression = new SimpleName(this.ast);
+                                       postLazyInit(this.arrayExpression, ARRAY_PROPERTY);
+                               }
+                       }
+               }
+               return this.arrayExpression;
+       }
+       
+       /**
+        * Sets the array expression of this array access expression.
+        * 
+        * @param expression the array expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setArray(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               // an ArrayAccess may occur inside an Expression
+               // must check cycles
+               ASTNode oldChild = this.arrayExpression;
+               preReplaceChild(oldChild, expression, ARRAY_PROPERTY);
+               this.arrayExpression = expression;
+               postReplaceChild(oldChild, expression, ARRAY_PROPERTY);
+       }
+       
+       /**
+        * Returns the index expression of this array access expression.
+        * 
+        * @return the index expression node
+        */ 
+       public Expression getIndex() {
+               if (this.indexExpression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.indexExpression == null) {
+                                       preLazyInit();
+                                       this.indexExpression = new SimpleName(this.ast);
+                                       postLazyInit(this.indexExpression, INDEX_PROPERTY);
+                               }
+                       }
+               }
+               return this.indexExpression;
+       }
+       
+       /**
+        * Sets the index expression of this array access expression.
+        * 
+        * @param expression the index expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setIndex(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               // an ArrayAccess may occur inside an Expression
+               // must check cycles
+               ASTNode oldChild = this.indexExpression;
+               preReplaceChild(oldChild, expression, INDEX_PROPERTY);
+               this.indexExpression = expression;
+               postReplaceChild(oldChild, expression, INDEX_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.arrayExpression == null ? 0 : getArray().treeSize())
+                       + (this.indexExpression == null ? 0 : getIndex().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayCreation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayCreation.java
new file mode 100644 (file)
index 0000000..d986c54
--- /dev/null
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Array creation expression AST node type.
+ * For JLS2:
+ * <pre>
+ * ArrayCreation:
+ *    <b>new</b> PrimitiveType <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
+ *    <b>new</b> TypeName <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
+ *    <b>new</b> PrimitiveType <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
+ *    <b>new</b> TypeName <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
+ * </pre>
+ * <p>
+ * The mapping from Java language syntax to AST nodes is as follows:
+ * <ul>
+ * <li>the type node is the array type of the creation expression,
+ *   with one level of array per set of square brackets,</li>
+ * <li>the dimension expressions are collected into the <code>dimensions</code>
+ *   list.</li>
+ * </ul>
+ * </p>
+ * For JLS3, type arguments are added:
+ * <pre>
+ * ArrayCreation:
+ *    <b>new</b> PrimitiveType <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
+ *    <b>new</b> TypeName [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ *        <b>[</b> Expression <b>]</b> { <b>[</b> Expression <b>]</b> } { <b>[</b> <b>]</b> }
+ *    <b>new</b> PrimitiveType <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
+ *    <b>new</b> TypeName [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ *        <b>[</b> <b>]</b> { <b>[</b> <b>]</b> } ArrayInitializer
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ArrayCreation extends Expression {
+       
+       /**
+        * The "type" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(ArrayCreation.class, "type", ArrayType.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "dimensions" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor DIMENSIONS_PROPERTY = 
+               new ChildListPropertyDescriptor(ArrayCreation.class, "dimensions", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "initializer" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor INITIALIZER_PROPERTY = 
+               new ChildPropertyDescriptor(ArrayCreation.class, "initializer", ArrayInitializer.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(4);
+               createPropertyList(ArrayCreation.class, properyList);
+               addProperty(TYPE_PROPERTY, properyList);
+               addProperty(DIMENSIONS_PROPERTY, properyList);
+               addProperty(INITIALIZER_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 array type; lazily initialized; defaults to a unspecified,
+        * legal array type.
+        */
+       private ArrayType arrayType = null;
+
+       /**
+        * The list of dimension expressions (element type:
+        * <code>Expression</code>). Defaults to an empty list.
+        */
+       private ASTNode.NodeList dimensions =
+               new ASTNode.NodeList(DIMENSIONS_PROPERTY);
+
+       /**
+        * The optional array initializer, or <code>null</code> if none;
+        * defaults to none.
+        */
+       private ArrayInitializer optionalInitializer = null;
+
+       /**
+        * Creates a new AST node for an array creation expression owned by the 
+        * given AST. By default, the array type is an unspecified 1-dimensional
+        * array, the list of dimensions is empty, and there is no array
+        * initializer.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ArrayCreation(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+               
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == INITIALIZER_PROPERTY) {
+                       if (get) {
+                               return getInitializer();
+                       } else {
+                               setInitializer((ArrayInitializer) child);
+                               return null;
+                       }
+               }
+               if (property == TYPE_PROPERTY) {
+                       if (get) {
+                               return getType();
+                       } else {
+                               setType((ArrayType) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == DIMENSIONS_PROPERTY) {
+                       return dimensions();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return ARRAY_CREATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ArrayCreation result = new ArrayCreation(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setType((ArrayType) getType().clone(target));
+               result.dimensions().addAll(ASTNode.copySubtrees(target, dimensions()));
+               result.setInitializer(
+                       (ArrayInitializer) ASTNode.copySubtree(target, getInitializer()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getType());
+                       acceptChildren(visitor, this.dimensions);
+                       acceptChild(visitor, getInitializer());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the array type in this array creation expression.
+        * 
+        * @return the array type
+        */ 
+       public ArrayType getType() {
+               if (this.arrayType == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.arrayType == null) {
+                                       preLazyInit();
+                                       this.arrayType = this.ast.newArrayType(
+                                                       this.ast.newPrimitiveType(PrimitiveType.INT));
+                                       postLazyInit(this.arrayType, TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.arrayType;
+       }
+
+       /**
+        * Sets the array type in this array creation expression.
+        * 
+        * @param type the new array type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setType(ArrayType type) {
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               // an ArrayCreation cannot occur inside a ArrayType - cycles not possible
+               ASTNode oldChild = this.arrayType;
+               preReplaceChild(oldChild, type, TYPE_PROPERTY);
+               this.arrayType = type;
+               postReplaceChild(oldChild, type, TYPE_PROPERTY);
+       }
+       
+       /**
+        * Returns the live ordered list of dimension expressions in this array
+        * initializer.
+        * 
+        * @return the live list of dimension expressions
+        *    (element type: <code>Expression</code>)
+        */ 
+       public List dimensions() {
+               return this.dimensions;
+       }
+       
+       /**
+        * Returns the array initializer of this array creation expression, or 
+        * <code>null</code> if there is none.
+        * 
+        * @return the array initializer node, or <code>null</code> if 
+        *    there is none
+        */ 
+       public ArrayInitializer getInitializer() {
+               return optionalInitializer;
+       }
+       
+       /**
+        * Sets or clears the array initializer of this array creation expression.
+        * 
+        * @param initializer the array initializer node, or <code>null</code>
+        *    if there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setInitializer(ArrayInitializer initializer) {
+               // an ArrayCreation may occur inside an ArrayInitializer
+               // must check cycles
+               ASTNode oldChild = this.optionalInitializer;
+               preReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+               this.optionalInitializer = initializer;
+               postReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               int size = memSize()
+                       + (this.arrayType == null ? 0 : getType().treeSize())
+                       + (this.optionalInitializer == null ? 0 : getInitializer().treeSize())
+                       + this.dimensions.listSize();
+               return size;
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayInitializer.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayInitializer.java
new file mode 100644 (file)
index 0000000..7995383
--- /dev/null
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Array initializer AST node type.
+ *
+ * <pre>
+ * ArrayInitializer:
+ *             <b>{</b> [ Expression { <b>,</b> Expression} [ <b>,</b> ]] <b>}</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ArrayInitializer extends Expression {
+       
+       /**
+        * The "expressions" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor EXPRESSIONS_PROPERTY = 
+               new ChildListPropertyDescriptor(ArrayInitializer.class, "expressions", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(2);
+               createPropertyList(ArrayInitializer.class, properyList);
+               addProperty(EXPRESSIONS_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 list of expressions (element type:
+        * <code>Expression</code>). Defaults to an empty list.
+        */
+       private ASTNode.NodeList expressions =
+               new ASTNode.NodeList(EXPRESSIONS_PROPERTY);
+
+       /**
+        * Creates a new AST node for an array initializer owned by the 
+        * given AST. By default, the list of expressions is empty.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ArrayInitializer(AST ast) {
+               super(ast);     
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == EXPRESSIONS_PROPERTY) {
+                       return expressions();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return ARRAY_INITIALIZER;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ArrayInitializer result = new ArrayInitializer(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.expressions().addAll(ASTNode.copySubtrees(target, expressions()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChildren(visitor, this.expressions);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the live ordered list of expressions in this array initializer.
+        * 
+        * @return the live list of expressions 
+        *    (element type: <code>Expression</code>)
+        */ 
+       public List expressions() {
+               return this.expressions;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize() + this.expressions.listSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayType.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ArrayType.java
new file mode 100644 (file)
index 0000000..5361970
--- /dev/null
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for an array type.
+ * <p>
+ * Array types are expressed in a recursive manner, one dimension at a time.
+ * </p>
+ * <pre>
+ * ArrayType:
+ *    Type <b>[</b> <b>]</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ArrayType extends Type {
+       
+       /**
+        * The "componentType" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor COMPONENT_TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(ArrayType.class, "componentType", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(2);
+               createPropertyList(ArrayType.class, properyList);
+               addProperty(COMPONENT_TYPE_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 component type; lazily initialized; defaults to a simple type with
+        * an unspecfied, but legal, name.
+        */
+       private Type componentType = null;
+       
+       /**
+        * Creates a new unparented node for an array type owned by the given AST.
+        * By default, a 1-dimensional array of an unspecified simple type.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ArrayType(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == COMPONENT_TYPE_PROPERTY) {
+                       if (get) {
+                               return getComponentType();
+                       } else {
+                               setComponentType((Type) 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.
+        */
+       final int getNodeType0() {
+               return ARRAY_TYPE;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ArrayType result = new ArrayType(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setComponentType((Type) getComponentType().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getComponentType());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the component type of this array type. The component type
+        * may be another array type.
+        * 
+        * @return the component type node
+        */ 
+       public Type getComponentType() {
+               if (this.componentType == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.componentType == null) {
+                                       preLazyInit();
+                                       this.componentType = new SimpleType(this.ast);
+                                       postLazyInit(this.componentType, COMPONENT_TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.componentType;
+       }
+
+       /**
+        * Sets the component type of this array type. The component type
+        * may be another array type.
+        * 
+        * @param componentType the component type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setComponentType(Type componentType) {
+               if (componentType == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.componentType;
+               preReplaceChild(oldChild, componentType, COMPONENT_TYPE_PROPERTY);
+               this.componentType = componentType;
+               postReplaceChild(oldChild, componentType, COMPONENT_TYPE_PROPERTY);
+       }
+
+       /**
+        * Returns the element type of this array type. The element type is
+        * never an array type.
+        * <p>
+        * This is a convenience method that descends a chain of nested array types
+        * until it reaches a non-array type. 
+        * </p>
+        * 
+        * @return the component type node
+        */ 
+       public Type getElementType() {
+               Type t = getComponentType();
+               while (t.isArrayType()) {
+                       t = ((ArrayType) t).getComponentType();
+               }
+               return t;
+       }
+       
+       /**
+        * Returns the number of dimensions in this array type.
+        * <p>
+        * This is a convenience method that descends a chain of nested array types
+        * until it reaches a non-array type. 
+        * </p>
+        * 
+        * @return the number of dimensions (always positive)
+        */ 
+       public int getDimensions() {
+               Type t = getComponentType();
+               int dimensions = 1; // always include this array type
+               while (t.isArrayType()) {
+                       dimensions++;
+                       t = ((ArrayType) t).getComponentType();
+               }
+               return dimensions;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize() 
+                       + (this.componentType == null ? 0 : getComponentType().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AssertStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/AssertStatement.java
new file mode 100644 (file)
index 0000000..5e48249
--- /dev/null
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Assert statement AST node type.
+ *
+ * <pre>
+ * AssertStatement:
+ *    <b>assert</b> Expression [ <b>:</b> Expression ] <b>;</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class AssertStatement extends Statement {
+                       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(AssertStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "message" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor MESSAGE_PROPERTY = 
+               new ChildPropertyDescriptor(AssertStatement.class, "message", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(3);
+               createPropertyList(AssertStatement.class, properyList);
+               addProperty(EXPRESSION_PROPERTY, properyList);
+               addProperty(MESSAGE_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 expression; lazily initialized; defaults to a unspecified, but legal,
+        * expression.
+        */
+       private Expression expression = null;
+
+       /**
+        * The message expression; <code>null</code> for none; defaults to none.
+        */
+       private Expression optionalMessageExpression = null;
+       
+       /**
+        * Creates a new unparented assert statement node owned by the given 
+        * AST. By default, the assert statement has an unspecified, but legal,
+        * expression, and not message expression.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       AssertStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == MESSAGE_PROPERTY) {
+                       if (get) {
+                               return getMessage();
+                       } else {
+                               setMessage((Expression) 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.
+        */
+       final int getNodeType0() {
+               return ASSERT_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               AssertStatement result = new AssertStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setExpression(
+                       (Expression) ASTNode.copySubtree(target, getExpression()));
+               result.setMessage(
+                       (Expression) ASTNode.copySubtree(target, getMessage()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getExpression());
+                       acceptChild(visitor, getMessage());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the first expression of this assert statement.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new SimpleName(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return expression;
+       }
+               
+       /**
+        * Sets the first expression of this assert statement.
+        * 
+        * @param expression the new expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               // an AssertStatement may occur inside an Expression - must check cycles
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the message expression of this assert statement, or 
+        * <code>null</code> if there is none.
+        * 
+        * @return the message expression node, or <code>null</code> if there 
+        *    is none
+        */ 
+       public Expression getMessage() {
+               return this.optionalMessageExpression;
+       }
+       
+       /**
+        * Sets or clears the message expression of this assert statement.
+        * 
+        * @param expression the message expression node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setMessage(Expression expression) {
+               // an AsertStatement may occur inside an Expression - must check cycles
+               ASTNode oldChild = this.optionalMessageExpression;
+               preReplaceChild(oldChild, expression, MESSAGE_PROPERTY);
+               this.optionalMessageExpression = expression;
+               postReplaceChild(oldChild, expression, MESSAGE_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.expression == null ? 0 : getExpression().treeSize())
+                       + (this.optionalMessageExpression == null ? 0 : getMessage().treeSize());
+                       
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Assignment.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Assignment.java
new file mode 100644 (file)
index 0000000..7c13752
--- /dev/null
@@ -0,0 +1,441 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Assignment expression AST node type.
+ *
+ * <pre>
+ * Assignment:
+ *    Expression AssignmentOperator Expression
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class Assignment extends Expression {
+               
+       /**
+        * Assignment operators (typesafe enumeration).
+        * <pre>
+        * AssignmentOperator:<code>
+        *    <b>=</b> ASSIGN
+        *    <b>+=</b> PLUS_ASSIGN
+        *    <b>-=</b> MINUS_ASSIGN
+        *    <b>*=</b> TIMES_ASSIGN
+        *    <b>/=</b> DIVIDE_ASSIGN
+        *    <b>&amp;=</b> BIT_AND_ASSIGN
+        *    <b>|=</b> BIT_OR_ASSIGN
+        *    <b>^=</b> BIT_XOR_ASSIGN
+        *    <b>%=</b> REMAINDER_ASSIGN
+        *    <b>&lt;&lt;=</b> LEFT_SHIFT_ASSIGN
+        *    <b>&gt;&gt;=</b> RIGHT_SHIFT_SIGNED_ASSIGN
+        *    <b>&gt;&gt;&gt;=</b> RIGHT_SHIFT_UNSIGNED_ASSIGN</code>
+        * </pre>
+        */
+       public static class Operator {
+       
+               /**
+                * The name of the operator
+                */
+               private String op;
+               
+               /**
+                * Creates a new assignment operator with the given name.
+                * <p>
+                * Note: this constructor is private. The only instances
+                * ever created are the ones for the standard operators.
+                * </p>
+                * 
+                * @param op the character sequence for the operator
+                */
+               private Operator(String op) {
+                       this.op = op;
+               }
+               
+               /**
+                * Returns the character sequence for the operator.
+                * 
+                * @return the character sequence for the operator
+                */
+               public String toString() {
+                       return op;
+               }
+               
+               /** = operator. */
+               public static final Operator ASSIGN = new Operator("=");//$NON-NLS-1$
+               /** += operator. */
+               public static final Operator PLUS_ASSIGN = new Operator("+=");//$NON-NLS-1$
+               /** -= operator. */
+               public static final Operator MINUS_ASSIGN = new Operator("-=");//$NON-NLS-1$
+               /** *= operator. */
+               public static final Operator TIMES_ASSIGN = new Operator("*=");//$NON-NLS-1$
+               /** /= operator. */
+               public static final Operator DIVIDE_ASSIGN = new Operator("/=");//$NON-NLS-1$
+               /** &amp;= operator. */
+               public static final Operator BIT_AND_ASSIGN = new Operator("&=");//$NON-NLS-1$
+               /** |= operator. */
+               public static final Operator BIT_OR_ASSIGN = new Operator("|=");//$NON-NLS-1$
+               /** ^= operator. */
+               public static final Operator BIT_XOR_ASSIGN = new Operator("^=");//$NON-NLS-1$
+               /** %= operator. */
+               public static final Operator REMAINDER_ASSIGN = new Operator("%=");//$NON-NLS-1$
+               /** &lt;&lt;== operator. */
+               public static final Operator LEFT_SHIFT_ASSIGN =
+                       new Operator("<<=");//$NON-NLS-1$
+               /** &gt;&gt;= operator. */
+               public static final Operator RIGHT_SHIFT_SIGNED_ASSIGN =
+                       new Operator(">>=");//$NON-NLS-1$
+               /** &gt;&gt;&gt;= operator. */
+               public static final Operator RIGHT_SHIFT_UNSIGNED_ASSIGN =
+                       new Operator(">>>=");//$NON-NLS-1$
+               
+               /**
+                * Returns the assignment operator corresponding to the given string,
+                * or <code>null</code> if none.
+                * <p>
+                * <code>toOperator</code> is the converse of <code>toString</code>:
+                * that is, <code>Operator.toOperator(op.toString()) == op</code> for all 
+                * operators <code>op</code>.
+                * </p>
+                * 
+                * @param token the character sequence for the operator
+                * @return the assignment operator, or <code>null</code> if none
+                */
+               public static Operator toOperator(String token) {
+                       return (Operator) CODES.get(token);
+               }
+               
+               /**
+                * Map from token to operator (key type: <code>String</code>;
+                * value type: <code>Operator</code>).
+                */
+               private static final Map CODES;
+               static {
+                       CODES = new HashMap(20);
+                       Operator[] ops = {
+                                       ASSIGN,
+                                       PLUS_ASSIGN,
+                                       MINUS_ASSIGN,
+                                       TIMES_ASSIGN,
+                                       DIVIDE_ASSIGN,
+                                       BIT_AND_ASSIGN,
+                                       BIT_OR_ASSIGN,
+                                       BIT_XOR_ASSIGN,
+                                       REMAINDER_ASSIGN,
+                                       LEFT_SHIFT_ASSIGN,
+                                       RIGHT_SHIFT_SIGNED_ASSIGN,
+                                       RIGHT_SHIFT_UNSIGNED_ASSIGN
+                               };
+                       for (int i = 0; i < ops.length; i++) {
+                               CODES.put(ops[i].toString(), ops[i]);
+                       }
+               }
+       }
+       
+       /**
+        * The "leftHandSide" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor LEFT_HAND_SIDE_PROPERTY = 
+               new ChildPropertyDescriptor(Assignment.class, "leftHandSide", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "operator" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor OPERATOR_PROPERTY = 
+               new SimplePropertyDescriptor(Assignment.class, "operator", Assignment.Operator.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "rightHandSide" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor RIGHT_HAND_SIDE_PROPERTY = 
+               new ChildPropertyDescriptor(Assignment.class, "rightHandSide", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(4);
+               createPropertyList(Assignment.class, properyList);
+               addProperty(LEFT_HAND_SIDE_PROPERTY, properyList);
+               addProperty(OPERATOR_PROPERTY, properyList);
+               addProperty(RIGHT_HAND_SIDE_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 assignment operator; defaults to Assignment.Operator.ASSIGN
+        */
+       private Assignment.Operator assignmentOperator = Assignment.Operator.ASSIGN;
+
+       /**
+        * The left hand side; lazily initialized; defaults to an unspecified,
+        * but legal, simple name.
+        */
+       private Expression leftHandSide = null;
+
+       /**
+        * The right hand side; lazily initialized; defaults to an unspecified,
+        * but legal, simple name.
+        */
+       private Expression rightHandSide = null;
+
+       /**
+        * Creates a new AST node for an assignment expression owned by the given 
+        * AST. By default, the node has an assignment operator, and unspecified
+        * left and right hand sides.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       Assignment(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == OPERATOR_PROPERTY) {
+                       if (get) {
+                               return getOperator();
+                       } else {
+                               setOperator((Operator) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == LEFT_HAND_SIDE_PROPERTY) {
+                       if (get) {
+                               return getLeftHandSide();
+                       } else {
+                               setLeftHandSide((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == RIGHT_HAND_SIDE_PROPERTY) {
+                       if (get) {
+                               return getRightHandSide();
+                       } else {
+                               setRightHandSide((Expression) 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.
+        */
+       final int getNodeType0() {
+               return ASSIGNMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               Assignment result = new Assignment(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setOperator(getOperator());
+               result.setLeftHandSide((Expression) getLeftHandSide().clone(target));
+               result.setRightHandSide((Expression) getRightHandSide().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getLeftHandSide());
+                       acceptChild(visitor, getRightHandSide());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the operator of this assignment expression.
+        * 
+        * @return the assignment operator
+        */ 
+       public Assignment.Operator getOperator() {
+               return this.assignmentOperator;
+       }
+
+       /**
+        * Sets the operator of this assignment expression.
+        * 
+        * @param assignmentOperator the assignment operator
+        * @exception IllegalArgumentException if the argument is incorrect
+        */ 
+       public void setOperator(Assignment.Operator assignmentOperator) {
+               if (assignmentOperator == null) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(OPERATOR_PROPERTY);
+               this.assignmentOperator = assignmentOperator;
+               postValueChange(OPERATOR_PROPERTY);
+       }
+
+       /**
+        * Returns the left hand side of this assignment expression.
+        * 
+        * @return the left hand side node
+        */ 
+       public Expression getLeftHandSide() {
+               if (this.leftHandSide  == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.leftHandSide == null) {
+                                       preLazyInit();
+                                       this.leftHandSide= new SimpleName(this.ast);
+                                       postLazyInit(this.leftHandSide, LEFT_HAND_SIDE_PROPERTY);
+                               }
+                       }
+               }
+               return this.leftHandSide;
+       }
+               
+       /**
+        * Sets the left hand side of this assignment expression.
+        * 
+        * @param expression the left hand side node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setLeftHandSide(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               // an Assignment may occur inside a Expression - must check cycles
+               ASTNode oldChild = this.leftHandSide;
+               preReplaceChild(oldChild, expression, LEFT_HAND_SIDE_PROPERTY);
+               this.leftHandSide = expression;
+               postReplaceChild(oldChild, expression, LEFT_HAND_SIDE_PROPERTY);
+       }
+
+       /**
+        * Returns the right hand side of this assignment expression.
+        * 
+        * @return the right hand side node
+        */ 
+       public Expression getRightHandSide() {
+               if (this.rightHandSide  == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.rightHandSide == null) {
+                                       preLazyInit();
+                                       this.rightHandSide= new SimpleName(this.ast);
+                                       postLazyInit(this.rightHandSide, RIGHT_HAND_SIDE_PROPERTY);
+                               }
+                       }
+               }
+               return this.rightHandSide;
+       }
+               
+       /**
+        * Sets the right hand side of this assignment expression.
+        * 
+        * @param expression the right hand side node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setRightHandSide(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               // an Assignment may occur inside a Expression - must check cycles
+               ASTNode oldChild = this.rightHandSide;
+               preReplaceChild(oldChild, expression, RIGHT_HAND_SIDE_PROPERTY);
+               this.rightHandSide = expression;
+               postReplaceChild(oldChild, expression, RIGHT_HAND_SIDE_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.leftHandSide == null ? 0 : getLeftHandSide().treeSize())
+                       + (this.rightHandSide == null ? 0 : getRightHandSide().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BindingComparator.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BindingComparator.java
new file mode 100644 (file)
index 0000000..1d11344
--- /dev/null
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.HashSet;
+
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
+import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
+import net.sourceforge.phpdt.internal.compiler.lookup.CaptureBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ImportBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeVariableBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.WildcardBinding;
+
+/**
+ * Internal helper class for comparing bindings.
+ * 
+ * @since 3.1
+ */
+class BindingComparator {
+       /**
+        * @param bindings
+        * @param otherBindings
+        * @return true if both parameters are equals, false otherwise
+        */
+       static boolean isEqual(TypeVariableBinding[] bindings, TypeVariableBinding[] otherBindings) {
+               if (bindings == null) {
+                       return otherBindings == null;
+               }
+               if (otherBindings == null) {
+                       return false;
+               }
+               int length = bindings.length;
+               int otherLength = otherBindings.length;
+               if (length != otherLength) {
+                       return false;
+               }
+               for (int i = 0; i < length; i++) {
+                       TypeVariableBinding typeVariableBinding = bindings[i];
+                       TypeVariableBinding typeVariableBinding2 = otherBindings[i];
+                       if (!isEqual(typeVariableBinding, typeVariableBinding2)) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+       
+       /**
+        * @param declaringElement
+        * @param declaringElement2
+        * @return true if both parameters are equals, false otherwise
+        */
+       static boolean isEqual(Binding declaringElement, Binding declaringElement2, HashSet visitedTypes) {
+               if (declaringElement instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
+                       if (!(declaringElement2 instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)){
+                               return false;
+                       }
+                       return isEqual((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) declaringElement,
+                                       (net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) declaringElement2,
+                                       visitedTypes);
+               } else if (declaringElement instanceof net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding) {
+                       if (!(declaringElement2 instanceof net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding)) {
+                               return false;
+                       }
+                       return isEqual((net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding) declaringElement,
+                                       (net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding) declaringElement2,
+                                       visitedTypes);
+               } else if (declaringElement instanceof VariableBinding) {
+                       if (!(declaringElement2 instanceof VariableBinding)) {
+                               return false;
+                       }
+                       return isEqual((VariableBinding) declaringElement,
+                                       (VariableBinding) declaringElement2);
+               } else if (declaringElement instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
+                       if (!(declaringElement2 instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding)) {
+                               return false;
+                       }
+                       net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding packageBinding = (net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) declaringElement;
+                       net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding packageBinding2 = (net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) declaringElement2;
+                       return CharOperation.equals(packageBinding.compoundName, packageBinding2.compoundName);
+               } else if (declaringElement instanceof ImportBinding) {
+                       if (!(declaringElement2 instanceof ImportBinding)) {
+                               return false;
+                       }
+                       ImportBinding importBinding = (ImportBinding) declaringElement;
+                       ImportBinding importBinding2 = (ImportBinding) declaringElement2;
+                       return importBinding.isStatic() == importBinding2.isStatic()
+                               && importBinding.onDemand == importBinding2.onDemand
+                               && CharOperation.equals(importBinding.compoundName, importBinding2.compoundName);
+               }
+               return false;
+       }
+       
+       static boolean isEqual(net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding,
+                       net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding2) {
+               return isEqual(methodBinding, methodBinding2, new HashSet());
+       }
+                       
+       static boolean isEqual(net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding,
+                       net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding2,
+                       HashSet visitedTypes) {
+               if (methodBinding == null) {
+                       return methodBinding2 == null;
+               }
+               if (methodBinding2 == null) return false;
+               return CharOperation.equals(methodBinding.selector, methodBinding2.selector)
+                               && isEqual(methodBinding.returnType, methodBinding2.returnType, visitedTypes) 
+                               && isEqual(methodBinding.thrownExceptions, methodBinding2.thrownExceptions, visitedTypes)
+                               && isEqual(methodBinding.declaringClass, methodBinding2.declaringClass, visitedTypes)
+                               && isEqual(methodBinding.typeVariables, methodBinding2.typeVariables, visitedTypes)
+                               && isEqual(methodBinding.parameters, methodBinding2.parameters, visitedTypes);
+       }
+
+       static boolean isEqual(VariableBinding variableBinding, VariableBinding variableBinding2) {
+               return (variableBinding.modifiers & ExtraCompilerModifiers.AccJustFlag) == (variableBinding2.modifiers & ExtraCompilerModifiers.AccJustFlag)
+                               && CharOperation.equals(variableBinding.name, variableBinding2.name)
+                               && isEqual(variableBinding.type, variableBinding2.type)
+                               && (variableBinding.id == variableBinding2.id);
+       }
+
+       static boolean isEqual(FieldBinding fieldBinding, FieldBinding fieldBinding2) {
+               HashSet visitedTypes = new HashSet();
+               return (fieldBinding.modifiers & ExtraCompilerModifiers.AccJustFlag) == (fieldBinding2.modifiers & ExtraCompilerModifiers.AccJustFlag)
+                               && CharOperation.equals(fieldBinding.name, fieldBinding2.name)
+                               && isEqual(fieldBinding.type, fieldBinding2.type, visitedTypes)
+                               && isEqual(fieldBinding.declaringClass, fieldBinding2.declaringClass, visitedTypes);
+       }
+
+       /**
+        * @param bindings
+        * @param otherBindings
+        * @return true if both parameters are equals, false otherwise
+        */
+       static boolean isEqual(net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] bindings, net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] otherBindings) {
+               return isEqual(bindings, otherBindings, new HashSet());
+       }
+       /**
+        * @param bindings
+        * @param otherBindings
+        * @return true if both parameters are equals, false otherwise
+        */
+       static boolean isEqual(net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] bindings, net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] otherBindings, HashSet visitedTypes) {
+               if (bindings == null) {
+                       return otherBindings == null;
+               }
+               if (otherBindings == null) {
+                       return false;
+               }
+               int length = bindings.length;
+               int otherLength = otherBindings.length;
+               if (length != otherLength) {
+                       return false;
+               }
+               for (int i = 0; i < length; i++) {
+                       if (!isEqual(bindings[i], otherBindings[i], visitedTypes)) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+       static boolean isEqual(net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding, net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding2, HashSet visitedTypes) {
+               if (typeBinding == typeBinding2)
+                       return true;
+               if (typeBinding == null || typeBinding2 == null)
+                       return false;
+
+               switch (typeBinding.kind()) {
+                       case Binding.BASE_TYPE :
+                               if (!typeBinding2.isBaseType()) {
+                                       return false;
+                               }
+                               return typeBinding.id == typeBinding2.id;
+                               
+                       case Binding.ARRAY_TYPE :
+                               if (!typeBinding2.isArrayType()) {
+                                       return false;
+                               }
+                               return typeBinding.dimensions() == typeBinding2.dimensions()
+                                               && isEqual(typeBinding.leafComponentType(), typeBinding2.leafComponentType(), visitedTypes);
+                               
+                       case Binding.PARAMETERIZED_TYPE :
+                               if (!typeBinding2.isParameterizedType()) {
+                                       return false;
+                               }
+                               ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) typeBinding;
+                               ParameterizedTypeBinding parameterizedTypeBinding2 = (ParameterizedTypeBinding) typeBinding2;
+                               return CharOperation.equals(parameterizedTypeBinding.compoundName, parameterizedTypeBinding2.compoundName)
+                                       && (parameterizedTypeBinding.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+                                                       == (parameterizedTypeBinding2.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+                                       && isEqual(parameterizedTypeBinding.arguments, parameterizedTypeBinding2.arguments, visitedTypes)
+                                       && isEqual(parameterizedTypeBinding.enclosingType(), parameterizedTypeBinding2.enclosingType(), visitedTypes);
+                                                       
+                       case Binding.WILDCARD_TYPE :
+                               if (typeBinding2.kind() != Binding.WILDCARD_TYPE) {
+                                       return false;
+                               }
+                               WildcardBinding wildcardBinding = (WildcardBinding) typeBinding;
+                               WildcardBinding wildcardBinding2 = (WildcardBinding) typeBinding2;
+                               return isEqual(wildcardBinding.bound, wildcardBinding2.bound, visitedTypes)
+                                       && wildcardBinding.boundKind == wildcardBinding2.boundKind;
+                               
+                       case Binding.INTERSECTION_TYPE:
+                               if (typeBinding2.kind() != Binding.INTERSECTION_TYPE) {
+                                       return false;
+                               }
+                               WildcardBinding intersectionBinding = (WildcardBinding) typeBinding;
+                               WildcardBinding intersectionBinding2 = (WildcardBinding) typeBinding2;
+                               return isEqual(intersectionBinding.bound, intersectionBinding2.bound, visitedTypes)
+                                       && isEqual(intersectionBinding.otherBounds, intersectionBinding2.otherBounds, visitedTypes);
+                               
+                       case Binding.TYPE_PARAMETER :
+                               if (!(typeBinding2.isTypeVariable())) {
+                                       return false;
+                               }
+                               if (typeBinding.isCapture()) {
+                                       if (!(typeBinding2.isCapture())) {
+                                               return false;
+                                       }
+                                       CaptureBinding captureBinding = (CaptureBinding) typeBinding;
+                                       CaptureBinding captureBinding2 = (CaptureBinding) typeBinding2;
+                                       if (captureBinding.position == captureBinding2.position) {
+                                               if (visitedTypes.contains(typeBinding)) return true;
+                                               visitedTypes.add(typeBinding);
+                                               
+                                               return isEqual(captureBinding.wildcard, captureBinding2.wildcard, visitedTypes)
+                                                       && isEqual(captureBinding.sourceType, captureBinding2.sourceType, visitedTypes);
+                                       }
+                                       return false;
+                               }
+                               TypeVariableBinding typeVariableBinding = (TypeVariableBinding) typeBinding;
+                               TypeVariableBinding typeVariableBinding2 = (TypeVariableBinding) typeBinding2;
+                               if (CharOperation.equals(typeVariableBinding.sourceName, typeVariableBinding2.sourceName)) {
+                                       if (visitedTypes.contains(typeBinding)) return true;
+                                       visitedTypes.add(typeBinding);
+
+                                       return isEqual(typeVariableBinding.declaringElement, typeVariableBinding2.declaringElement, visitedTypes)
+                                       && isEqual(typeVariableBinding.superclass(), typeVariableBinding2.superclass(), visitedTypes)
+                                       && isEqual(typeVariableBinding.superInterfaces(), typeVariableBinding2.superInterfaces(), visitedTypes);
+                               }
+                               return false;
+                       case Binding.GENERIC_TYPE :
+                               if (!typeBinding2.isGenericType()) {
+                                       return false;
+                               }
+                               ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
+                               ReferenceBinding referenceBinding2 = (ReferenceBinding) typeBinding2;
+                               return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
+                                       && (referenceBinding.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+                                                       == (referenceBinding2.modifiers & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+                                       && isEqual(referenceBinding.typeVariables(), referenceBinding2.typeVariables(), visitedTypes)
+                                       && isEqual(referenceBinding.enclosingType(), referenceBinding2.enclosingType(), visitedTypes);
+
+                       case Binding.RAW_TYPE :
+                       default :
+                               if (!(typeBinding2 instanceof ReferenceBinding)) {
+                                       return false;
+                               }                               
+                               referenceBinding = (ReferenceBinding) typeBinding;
+                               referenceBinding2 = (ReferenceBinding) typeBinding2;
+                               char[] constantPoolName = referenceBinding.constantPoolName();
+                               char[] constantPoolName2 = referenceBinding2.constantPoolName();
+                               // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=116833
+                               if (constantPoolName == null) {
+                                       if (constantPoolName2 != null) {
+                                               return false;
+                                       }
+                                       if (!CharOperation.equals(referenceBinding.computeUniqueKey(), referenceBinding2.computeUniqueKey())) {
+                                               return false;
+                                       }
+                               } else {
+                                       if (constantPoolName2 == null) {
+                                               return false;
+                                       }
+                                       if (!CharOperation.equals(constantPoolName, constantPoolName2)) {
+                                               return false;
+                                       }
+                               }
+                               return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
+                                       && (!referenceBinding2.isGenericType())
+                                       && (referenceBinding.isRawType() == referenceBinding2.isRawType())
+                                       && ((referenceBinding.modifiers & ~ClassFileConstants.AccSuper) & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+                                                       == ((referenceBinding2.modifiers & ~ClassFileConstants.AccSuper) & (ExtraCompilerModifiers.AccJustFlag | ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation))
+                                       && isEqual(referenceBinding.enclosingType(), referenceBinding2.enclosingType(), visitedTypes);
+               }
+       }
+       /**
+        * @param typeBinding
+        * @param typeBinding2
+        * @return true if both parameters are equals, false otherwise
+        */
+       static boolean isEqual(net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding, net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding2) {
+               return isEqual(typeBinding, typeBinding2, new HashSet());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BindingResolver.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BindingResolver.java
new file mode 100644 (file)
index 0000000..f3913fb
--- /dev/null
@@ -0,0 +1,1001 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.WorkingCopyOwner;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.CompilationUnitScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ElementValuePair;
+import net.sourceforge.phpdt.internal.compiler.lookup.LookupEnvironment;
+
+/**
+ * A binding resolver is an internal mechanism for figuring out the binding
+ * for a major declaration, type, or name reference. This also handles
+ * the creation and mapping between annotations and the ast nodes that define them.
+ * <p>
+ * The default implementation serves as the default binding resolver
+ * that does no resolving whatsoever. Internal subclasses do all the real work.
+ * </p>
+ *
+ * @see AST#getBindingResolver
+ */
+class BindingResolver {
+
+       /**
+        * Creates a binding resolver.
+        */
+       BindingResolver() {
+               // default implementation: do nothing
+       }
+
+       /**
+        * Finds the corresponding AST node from which the given binding originated.
+        * Returns <code>null</code> if the binding does not correspond to any node
+        * in the compilation unit.
+        * <p>
+        * The following table indicates the expected node type for the various
+        * different kinds of bindings:
+        * <ul>
+        * <li></li>
+        * <li>package - a <code>PackageDeclaration</code></li>
+        * <li>class or interface - a <code>TypeDeclaration</code> or a
+        *    <code>ClassInstanceCreation</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>annotation type member - an <code>AnnotationTypeMemberDeclaration</code>
+        * </ul>
+        * </p>
+        * <p>
+        * The implementation of <code>CompilationUnit.findDeclaringNode</code>
+        * forwards to this method.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param binding the binding
+        * @return the corresponding node where the bindings is declared,
+        *    or <code>null</code> if none
+        */
+       ASTNode findDeclaringNode(IBinding binding) {
+               return null;
+       }
+
+       /**
+        * Finds the corresponding AST node from which the given binding key originated.
+        *
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param bindingKey the binding key
+        * @return the corresponding node where the bindings is declared,
+        *    or <code>null</code> if none
+        */
+       ASTNode findDeclaringNode(String bindingKey) {
+               return null;
+       }
+
+       /**
+        * Finds the corresponding AST node from which the given annotation instance originated.
+        *
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param instance the dom annotation
+        * @return the corresponding node where the bindings is declared,
+        *    or <code>null</code> if none
+        */
+       ASTNode findDeclaringNode(IAnnotationBinding instance) {
+               return null;
+       }
+
+       /**
+        * Allows the user to get information about the given old/new pair of
+        * AST nodes.
+        * <p>
+        * The default implementation of this method does nothing.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param currentNode the new node
+        * @return org.eclipse.jdt.internal.compiler.ast.ASTNode
+        */
+       net.sourceforge.phpdt.internal.compiler.ast.ASTNode getCorrespondingNode(ASTNode currentNode) {
+               return null;
+       }
+
+       /**
+        * Returns the new method binding corresponding to the given old method binding.
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param methodBinding the old method binding
+        * @return the new method binding
+        */
+       IMethodBinding getMethodBinding(net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding) {
+               return null;
+       }
+
+       /**
+        * Returns the new member value pair binding corresponding to the given old value pair binding.
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param valuePair the old value pair binding
+        * @return the new member value pair binding
+        */
+       IMemberValuePairBinding getMemberValuePairBinding(ElementValuePair valuePair) {
+               return null;
+       }
+
+       /**
+        * Returns the new package binding corresponding to the given old package binding.
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param packageBinding the old package binding
+        * @return the new package binding
+        */
+       IPackageBinding getPackageBinding(net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding packageBinding) {
+               return null;
+       }
+
+       /**
+        * Returns the new type binding corresponding to the given old type binding.
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param referenceBinding the old type binding
+        * @return the new type binding
+        */
+       ITypeBinding getTypeBinding(net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding referenceBinding) {
+               return null;
+       }
+
+
+       /**
+        * Returns the new type binding corresponding to the given variableDeclaration.
+        * This is used for recovered binding only.
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param variableDeclaration the given variable declaration
+        * @return the new type binding
+        */
+       ITypeBinding getTypeBinding(VariableDeclaration variableDeclaration) {
+               return null;
+       }
+
+       /**
+        * Returns the new type binding corresponding to the given type. This is used for recovered binding
+        * only.
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param type the given type
+        * @return the new type binding
+        */
+       ITypeBinding getTypeBinding(Type type) {
+               return null;
+       }
+
+       /**
+        * Returns the new type binding corresponding to the given recovered type binding.
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param recoveredTypeBinding the recovered type binding
+        * @param dimensions the dimensions to add the to given type binding dimensions
+        * @return the new type binding
+        */
+       ITypeBinding getTypeBinding(RecoveredTypeBinding recoveredTypeBinding, int dimensions) {
+               return null;
+       }
+
+       /**
+        * Returns the new variable binding corresponding to the given old variable binding.
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param binding the old variable binding
+        * @return the new variable binding
+        */
+       IVariableBinding getVariableBinding(net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding binding) {
+               return null;
+       }
+
+       /**
+        * Return the working copy owner for the receiver.
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        * @return the working copy owner for the receiver
+        */
+       public WorkingCopyOwner getWorkingCopyOwner() {
+               return null;
+       }
+
+       /**
+        * Return the new annotation corresponding to the given old annotation
+        * <p>
+        * The default implementation of this method returns <code>null</code>
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param instance the old annotation
+        * @return the new DOM annotation
+        */
+       IAnnotationBinding getAnnotationInstance(net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding instance) {
+               return null;
+       }
+
+       boolean isResolvedTypeInferredFromExpectedType(MethodInvocation methodInvocation) {
+               return false;
+       }
+
+       boolean isResolvedTypeInferredFromExpectedType(SuperMethodInvocation methodInvocation) {
+               return false;
+       }
+
+       /**
+        * Returns the compiler lookup environment used by this binding resolver.
+        * Returns <code>null</code> if none.
+        *
+        * @return the lookup environment used by this resolver, or <code>null</code> if none.
+        */
+       LookupEnvironment lookupEnvironment() {
+               return null;
+       }
+
+       /**
+        * This method is used to record the scope and its corresponding node.
+        * <p>
+        * The default implementation of this method does nothing.
+        * Subclasses may reimplement.
+        * </p>
+        * @param astNode
+        */
+       void recordScope(ASTNode astNode, BlockScope blockScope) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * Returns whether this expression node is the site of a boxing
+        * conversion (JLS3 5.1.7). This information is available only
+        * when bindings are requested when the AST is being built.
+        *
+        * @return <code>true</code> if this expression is the site of a
+        * boxing conversion, or <code>false</code> if either no boxing conversion
+        * is involved or if bindings were not requested when the AST was created
+        * @since 3.1
+        */
+       boolean resolveBoxing(Expression expression) {
+               return false;
+       }
+
+       /**
+        * Returns whether this expression node is the site of an unboxing
+        * conversion (JLS3 5.1.8). This information is available only
+        * when bindings are requested when the AST is being built.
+        *
+        * @return <code>true</code> if this expression is the site of an
+        * unboxing conversion, or <code>false</code> if either no unboxing
+        * conversion is involved or if bindings were not requested when the
+        * AST was created
+        * @since 3.1
+        */
+       boolean resolveUnboxing(Expression expression) {
+               return false;
+       }
+
+       /**
+        * Resolves and returns the compile-time constant expression value as
+        * specified in JLS2 15.28, if this expression has one. Constant expression
+        * values are unavailable unless bindings are requested when the AST is
+        * being built. If the type of the value is a primitive type, the result
+        * is the boxed equivalent (i.e., int returned as an <code>Integer</code>);
+        * if the type of the value is <code>String</code>, the result is the string
+        * itself. If the expression does not have a compile-time constant expression
+        * value, the result is <code>null</code>.
+        * <p>
+        * Resolving constant expressions takes into account the value of simple
+        * and qualified names that refer to constant variables (JLS2 4.12.4).
+        * </p>
+        * <p>
+        * Note 1: enum constants are not considered constant expressions either.
+        * The result is always <code>null</code> for these.
+        * </p>
+        * <p>
+        * Note 2: Compile-time constant expressions cannot denote <code>null</code>.
+        * So technically {@link NullLiteral} nodes are not constant expressions.
+        * The result is <code>null</code> for these nonetheless.
+        * </p>
+        *
+        * @return the constant expression value, or <code>null</code> if this
+        * expression has no constant expression value or if bindings were not
+        * requested when the AST was created
+        * @since 3.1
+        */
+       Object resolveConstantExpressionValue(Expression expression) {
+               return null;
+       }
+
+       /**
+        * Resolves and returns the binding for the constructor being invoked.
+        * <p>
+        * The implementation of
+        * <code>ClassInstanceCreation.resolveConstructor</code>
+        * forwards to this method. Which constructor is invoked is often a function
+        * of the context in which the expression node is embedded as well as
+        * the expression subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param expression the expression of interest
+        * @return the binding for the constructor being invoked, or
+        *    <code>null</code> if no binding is available
+        */
+       IMethodBinding resolveConstructor(ClassInstanceCreation expression) {
+               return null;
+       }
+
+       /**
+        * Resolves and returns the binding for the constructor being invoked.
+        * <p>
+        * The implementation of
+        * <code>ConstructorInvocation.resolveConstructor</code>
+        * forwards to this method. Which constructor is invoked is often a function
+        * of the context in which the expression node is embedded as well as
+        * the expression subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param expression the expression of interest
+        * @return the binding for the constructor being invoked, or
+        *    <code>null</code> if no binding is available
+        */
+       IMethodBinding resolveConstructor(ConstructorInvocation expression) {
+               return null;
+       }
+       /**
+        * Resolves and returns the binding for the constructor being invoked.
+        * <p>
+        * The implementation of
+        * <code>ConstructorInvocation.resolveConstructor</code>
+        * forwards to this method. Which constructor is invoked is often a function
+        * of the context in which the expression node is embedded as well as
+        * the expression subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param enumConstantDeclaration the enum constant declaration of interest
+        * @return the binding for the constructor being invoked, or
+        *    <code>null</code> if no binding is available
+        */
+       IMethodBinding resolveConstructor(EnumConstantDeclaration enumConstantDeclaration) {
+               return null;
+       }
+       /**
+        * Resolves and returns the binding for the constructor being invoked.
+        * <p>
+        * The implementation of
+        * <code>SuperConstructorInvocation.resolveConstructor</code>
+        * forwards to this method. Which constructor is invoked is often a function
+        * of the context in which the expression node is embedded as well as
+        * the expression subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param expression the expression of interest
+        * @return the binding for the constructor being invoked, or
+        *    <code>null</code> if no binding is available
+        */
+       IMethodBinding resolveConstructor(SuperConstructorInvocation expression) {
+               return null;
+       }
+       /**
+        * Resolves the type of the given expression and returns the type binding
+        * for it.
+        * <p>
+        * The implementation of <code>Expression.resolveTypeBinding</code>
+        * forwards to this method. The result is often a function of the context
+        * in which the expression node is embedded as well as the expression
+        * subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param expression the expression whose type is of interest
+        * @return the binding for the type of the given expression, or
+        *    <code>null</code> if no binding is available
+        */
+       ITypeBinding resolveExpressionType(Expression expression) {
+               return null;
+       }
+
+       /**
+        * Resolves the given field access and returns the binding for it.
+        * <p>
+        * The implementation of <code>FieldAccess.resolveFieldBinding</code>
+        * forwards to this method. How the field resolves is often a function of
+        * the context in which the field access node is embedded as well as
+        * the field access subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param fieldAccess the field access of interest
+        * @return the binding for the given field access, or
+        *    <code>null</code> if no binding is available
+        */
+       IVariableBinding resolveField(FieldAccess fieldAccess) {
+               return null;
+       }
+
+       /**
+        * Resolves the given super field access and returns the binding for it.
+        * <p>
+        * The implementation of <code>SuperFieldAccess.resolveFieldBinding</code>
+        * forwards to this method. How the field resolves is often a function of
+        * the context in which the super field access node is embedded as well as
+        * the super field access subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param fieldAccess the super field access of interest
+        * @return the binding for the given field access, or
+        *    <code>null</code> if no binding is available
+        */
+       IVariableBinding resolveField(SuperFieldAccess fieldAccess) {
+               return null;
+       }
+
+       /**
+        * Resolves the given import declaration and returns the binding for it.
+        * <p>
+        * The implementation of <code>ImportDeclaration.resolveBinding</code>
+        * forwards to this method.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param importDeclaration the import declaration of interest
+        * @return the binding for the given package declaration, or
+        *         the package binding (for on-demand imports) or type binding
+        *         (for single-type imports), or <code>null</code> if no binding is
+        *         available
+        */
+       IBinding resolveImport(ImportDeclaration importDeclaration) {
+               return null;
+       }
+
+       /**
+        * Resolves the given annotation type declaration and returns the binding
+        * for it.
+        * <p>
+        * The implementation of <code>AnnotationTypeMemberDeclaration.resolveBinding</code>
+        * forwards to this method. How the declaration resolves is often a
+        * function of the context in which the declaration node is embedded as well
+        * as the declaration subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param member the annotation type member declaration of interest
+        * @return the binding for the given annotation type member declaration, or <code>null</code>
+        *    if no binding is available
+        * @since 3.0
+        */
+       IMethodBinding resolveMember(AnnotationTypeMemberDeclaration member) {
+               return null;
+       }
+
+       /**
+        * Resolves the given method declaration and returns the binding for it.
+        * <p>
+        * The implementation of <code>MethodDeclaration.resolveBinding</code>
+        * forwards to this method. How the method resolves is often a function of
+        * the context in which the method declaration node is embedded as well as
+        * the method declaration subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param method the method or constructor declaration of interest
+        * @return the binding for the given method declaration, or
+        *    <code>null</code> if no binding is available
+        */
+       IMethodBinding resolveMethod(MethodDeclaration method) {
+               return null;
+       }
+
+       /**
+        * Resolves the given method invocation and returns the binding for it.
+        * <p>
+        * The implementation of <code>MethodInvocation.resolveMethodBinding</code>
+        * forwards to this method. How the method resolves is often a function of
+        * the context in which the method invocation node is embedded as well as
+        * the method invocation subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param method the method invocation of interest
+        * @return the binding for the given method invocation, or
+        *    <code>null</code> if no binding is available
+        */
+       IMethodBinding resolveMethod(MethodInvocation method) {
+               return null;
+       }
+
+       /**
+        * Resolves the given method invocation and returns the binding for it.
+        * <p>
+        * The implementation of <code>MethodInvocation.resolveMethodBinding</code>
+        * forwards to this method. How the method resolves is often a function of
+        * the context in which the method invocation node is embedded as well as
+        * the method invocation subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param method the method invocation of interest
+        * @return the binding for the given method invocation, or
+        *    <code>null</code> if no binding is available
+        */
+       IMethodBinding resolveMethod(SuperMethodInvocation method) {
+               return null;
+       }
+
+       /**
+        * Resolves the given name and returns the type binding for it.
+        * <p>
+        * The implementation of <code>Name.resolveBinding</code> forwards to
+        * this method. How the name resolves is often a function of the context
+        * in which the name node is embedded as well as the name itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param name the name of interest
+        * @return the binding for the name, or <code>null</code> if no binding is
+        *    available
+        */
+       IBinding resolveName(Name name) {
+               return null;
+       }
+
+       /**
+        * Resolves the given package declaration and returns the binding for it.
+        * <p>
+        * The implementation of <code>PackageDeclaration.resolveBinding</code>
+        * forwards to this method.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param pkg the package declaration of interest
+        * @return the binding for the given package declaration, or
+        *    <code>null</code> if no binding is available
+        */
+       IPackageBinding resolvePackage(PackageDeclaration pkg) {
+               return null;
+       }
+
+       /**
+        * Resolves the given reference and returns the binding for it.
+        * <p>
+        * The implementation of <code>MemberRef.resolveBinding</code> forwards to
+        * this method. How the name resolves is often a function of the context
+        * in which the name node is embedded as well as the name itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param ref the reference of interest
+        * @return the binding for the reference, or <code>null</code> if no binding is
+        *    available
+        * @since 3.0
+        */
+       IBinding resolveReference(MemberRef ref) {
+               return null;
+       }
+
+       /**
+        * Resolves the given member value pair and returns the binding for it.
+        * <p>
+        * The implementation of <code>MemberValuePair.resolveMemberValuePairBinding</code> forwards to
+        * this method. How the name resolves is often a function of the context
+        * in which the name node is embedded as well as the name itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param memberValuePair the member value pair of interest
+        * @return the binding for the member value pair, or <code>null</code> if no binding is
+        *    available
+        * @since 3.2
+        */
+       IMemberValuePairBinding resolveMemberValuePair(MemberValuePair memberValuePair) {
+               return null;
+       }
+
+       /**
+        * Resolves the given reference and returns the binding for it.
+        * <p>
+        * The implementation of <code>MethodRef.resolveBinding</code> forwards to
+        * this method. How the name resolves is often a function of the context
+        * in which the name node is embedded as well as the name itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param ref the reference of interest
+        * @return the binding for the reference, or <code>null</code> if no binding is
+        *    available
+        * @since 3.0
+        */
+       IBinding resolveReference(MethodRef ref) {
+               return null;
+       }
+
+       /**
+        * Resolves the given annotation type declaration and returns the binding
+        * for it.
+        * <p>
+        * The implementation of <code>AnnotationTypeDeclaration.resolveBinding</code>
+        * forwards to this method. How the declaration resolves is often a
+        * function of the context in which the declaration node is embedded as well
+        * as the declaration subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param type the annotation type declaration of interest
+        * @return the binding for the given annotation type declaration, or <code>null</code>
+        *    if no binding is available
+        * @since 3.0
+        */
+       ITypeBinding resolveType(AnnotationTypeDeclaration type) {
+               return null;
+       }
+
+       /**
+        * Resolves the given anonymous class declaration and returns the binding
+        * for it.
+        * <p>
+        * The implementation of <code>AnonymousClassDeclaration.resolveBinding</code>
+        * forwards to this method. How the declaration resolves is often a
+        * function of the context in which the declaration node is embedded as well
+        * as the declaration subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param type the anonymous class declaration of interest
+        * @return the binding for the given class declaration, or <code>null</code>
+        *    if no binding is available
+        */
+       ITypeBinding resolveType(AnonymousClassDeclaration type) {
+               return null;
+       }
+
+       /**
+        * Resolves the given enum declaration and returns the binding
+        * for it.
+        * <p>
+        * The implementation of <code>EnumDeclaration.resolveBinding</code>
+        * forwards to this method. How the enum declaration resolves is often
+        * a function of the context in which the declaration node is embedded
+        * as well as the enum declaration subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param type the enum declaration of interest
+        * @return the binding for the given enum declaration, or <code>null</code>
+        *    if no binding is available
+        * @since 3.0
+        */
+       ITypeBinding resolveType(EnumDeclaration type) {
+               return null;
+       }
+
+       /**
+        * Resolves the given type and returns the type binding for it.
+        * <p>
+        * The implementation of <code>Type.resolveBinding</code>
+        * forwards to this method. How the type resolves is often a function
+        * of the context in which the type node is embedded as well as the type
+        * subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param type the type of interest
+        * @return the binding for the given type, or <code>null</code>
+        *    if no binding is available
+        */
+       ITypeBinding resolveType(Type type) {
+               return null;
+       }
+
+       /**
+        * Resolves the given class or interface declaration and returns the binding
+        * for it.
+        * <p>
+        * The implementation of <code>TypeDeclaration.resolveBinding</code>
+        * (and <code>TypeDeclarationStatement.resolveBinding</code>) forwards
+        * to this method. How the type declaration resolves is often a function of
+        * the context in which the type declaration node is embedded as well as the
+        * type declaration subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param type the class or interface declaration of interest
+        * @return the binding for the given type declaration, or <code>null</code>
+        *    if no binding is available
+        */
+       ITypeBinding resolveType(TypeDeclaration type) {
+               return null;
+       }
+
+       /**
+        * Resolves the given type parameter and returns the type binding for the
+        * type parameter.
+        * <p>
+        * The implementation of <code>TypeParameter.resolveBinding</code>
+        * forwards to this method. How the declaration resolves is often a
+        * function of the context in which the declaration node is embedded as well
+        * as the declaration subtree itself.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param typeParameter the type paramter of interest
+        * @return the binding for the given type parameter, or <code>null</code>
+        *    if no binding is available
+        * @since 3.1
+        */
+       ITypeBinding resolveTypeParameter(TypeParameter typeParameter) {
+               return null;
+       }
+
+       /**
+        * Resolves the given enum constant declaration and returns the binding for
+        * the field.
+        * <p>
+        * The implementation of <code>EnumConstantDeclaration.resolveVariable</code>
+        * forwards to this method.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param enumConstant the enum constant declaration of interest
+        * @return the field binding for the given enum constant declaration, or
+        *    <code>null</code> if no binding is available
+        * @since 3.0
+        */
+       IVariableBinding resolveVariable(EnumConstantDeclaration enumConstant) {
+               return null;
+       }
+
+       /**
+        * Resolves the given variable declaration and returns the binding for it.
+        * <p>
+        * The implementation of <code>VariableDeclaration.resolveBinding</code>
+        * forwards to this method. How the variable declaration resolves is often
+        * a function of the context in which the variable declaration node is
+        * embedded as well as the variable declaration subtree itself. VariableDeclaration
+        * declarations used as local variable, formal parameter and exception
+        * variables resolve to local variable bindings; variable declarations
+        * used to declare fields resolve to field bindings.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param variable the variable declaration of interest
+        * @return the binding for the given variable declaration, or
+        *    <code>null</code> if no binding is available
+        */
+       IVariableBinding resolveVariable(VariableDeclaration variable) {
+               return null;
+       }
+
+       /**
+        * Resolves the given well known type by name and returns the type binding
+        * for it.
+        * <p>
+        * The implementation of <code>AST.resolveWellKnownType</code>
+        * forwards to this method.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param name the name of a well known type
+        * @return the corresponding type binding, or <code>null<code> if the
+        *   named type is not considered well known or if no binding can be found
+        *   for it
+        */
+       ITypeBinding resolveWellKnownType(String name) {
+               return null;
+       }
+
+       /**
+        * Resolves the given annotation instance and returns the DOM representation for it.
+        * <p>
+        * The implementation of {@link Annotation#resolveAnnotationBinding()}
+        * forwards to this method.
+        * </p>
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param annotation the annotation ast node of interest
+        * @return the DOM annotation representation for the given ast node, or
+        *    <code>null</code> if none is available
+        */
+       IAnnotationBinding resolveAnnotation(Annotation annotation) {
+               return null;
+       }
+
+       /**
+        * Answer an array type binding with the given type binding and the given
+        * dimensions.
+        *
+        * <p>If the given type binding is an array binding, then the resulting dimensions is the given dimensions
+        * plus the existing dimensions of the array binding. Otherwise the resulting dimensions is the given
+        * dimensions.</p>
+        *
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param typeBinding the given type binding
+        * @param dimensions the given dimensions
+        * @return an array type binding with the given type binding and the given
+        * dimensions
+        * @throws IllegalArgumentException if the type binding represents the <code>void</code> type binding
+        */
+       ITypeBinding resolveArrayType(ITypeBinding typeBinding, int dimensions) {
+               return null;
+       }
+
+       /**
+        * Returns the compilation unit scope used by this binding resolver.
+        * Returns <code>null</code> if none.
+        *
+        * @return the compilation unit scope by this resolver, or <code>null</code> if none.
+        */
+       public CompilationUnitScope scope() {
+               return null;
+       }
+
+       /**
+        * Allows the user to store information about the given old/new pair of
+        * AST nodes.
+        * <p>
+        * The default implementation of this method does nothing.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param newNode the new AST node
+        * @param oldASTNode the old AST node
+        */
+       void store(ASTNode newNode, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) {
+               // default implementation: do nothing
+       }
+
+       /**
+        * Allows the user to update information about the given old/new pair of
+        * AST nodes.
+        * <p>
+        * The default implementation of this method does nothing.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param node the old AST node
+        * @param newNode the new AST node
+        */
+       void updateKey(ASTNode node, ASTNode newNode) {
+               // default implementation: do nothing
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Block.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Block.java
new file mode 100644 (file)
index 0000000..fcdc98e
--- /dev/null
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Block statement AST node type.
+ *
+ * <pre>
+ * Block:
+ *    <b>{</b> { Statement } <b>}</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class Block extends Statement {
+       
+       /**
+        * The "statements" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor STATEMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(Block.class, "statements", Statement.class, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(2);
+               createPropertyList(Block.class, properyList);
+               addProperty(STATEMENTS_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 list of statements (element type: <code>Statement</code>). 
+        * Defaults to an empty list.
+        */
+       private ASTNode.NodeList statements = 
+               new ASTNode.NodeList(STATEMENTS_PROPERTY);
+
+       /**
+        * Creates a new unparented block node owned by the given AST.
+        * By default, the block is empty.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       Block(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == STATEMENTS_PROPERTY) {
+                       return statements();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return BLOCK;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               Block result = new Block(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.statements().addAll(
+                       ASTNode.copySubtrees(target, statements()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChildren(visitor, this.statements);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the live list of statements in this block. Adding and
+        * removing nodes from this list affects this node dynamically.
+        * All nodes in this list must be <code>Statement</code>s;
+        * attempts to add any other type of node will trigger an
+        * exception.
+        * 
+        * @return the live list of statements in this block
+        *    (element type: <code>Statement</code>)
+        */ 
+       public List statements() {
+               return this.statements;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize() + this.statements.listSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BlockComment.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BlockComment.java
new file mode 100644 (file)
index 0000000..eb5c87e
--- /dev/null
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Block comment AST node type.
+ * <p>
+ * Block comments (also called "traditional" comments in JLS 3.7)
+ * begin with "/&#42;", may contain line breaks, and must end
+ * with "&#42;/". Following the definition in the JLS (first edition
+ * but not second edition), block comment normally exclude comments
+ * that begin with "/&#42;#42;", which are instead classified as doc
+ * comments ({@link Javadoc}).
+ * </p>
+ * <p>
+ * Note that this node type is a comment placeholder, and is
+ * only useful for recording the source range where a comment
+ * was found in a source string. It is not useful for creating
+ * comments.
+ * </p>
+ * 
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class BlockComment extends Comment {
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(1);
+               createPropertyList(BlockComment.class, 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;
+       }
+                       
+       /**
+        * Creates a new block comment node owned by the given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       BlockComment(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return BLOCK_COMMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               BlockComment result = new BlockComment(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize();
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BodyDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BodyDeclaration.java
new file mode 100644 (file)
index 0000000..9c0ab01
--- /dev/null
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Abstract base class of all AST nodes that represent body declarations 
+ * that may appear in the body of some kind of class or interface declaration,
+ * including anonymous class declarations, enumeration declarations, and
+ * enumeration constant declarations.
+ * <p>
+ * For JLS2:
+ * <pre>
+ * BodyDeclaration:
+ *             ClassDeclaration
+ *             InterfaceDeclaration
+ *             MethodDeclaration
+ *             ConstructorDeclaration
+ *             FieldDeclaration
+ *             Initializer
+ * </pre>
+ * For JLS3, a number of new node types were introduced:
+ * <pre>
+ * BodyDeclaration:
+ *             ClassDeclaration
+ *             InterfaceDeclaration
+ *             EnumDeclaration
+ *             MethodDeclaration
+ *             ConstructorDeclaration
+ *             FieldDeclaration
+ *             Initializer
+ *             EnumConstantDeclaration
+ *             AnnotationTypeDeclaration
+ *             AnnotationTypeMemberDeclaration
+ * </pre>
+ * </p>
+ * <p>
+ * All types of body declarations carry modifiers (and annotations), although they differ in
+ * which modifiers are allowed. Most types of body declarations can carry a
+ * doc comment; Initializer is the only ones that does not. The source range
+ * for body declarations always includes the doc comment if present.
+ * </p>
+ * 
+ * @since 2.0
+ */
+public abstract class BodyDeclaration extends ASTNode {
+       
+       /**
+        * The doc comment, or <code>null</code> if none.
+        * Defaults to none.
+        */
+       Javadoc optionalDocComment = null;
+
+       /**
+        * The modifier flags; bit-wise or of Modifier flags.
+        * Defaults to none. Not used in 3.0.
+        * @since 3.0 - field was moved up from subclasses
+        */
+       private int modifierFlags = Modifier.NONE;
+       
+       /**
+        * The extended modifiers (element type: <code>IExtendedModifier</code>). 
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * 
+        * @since 3.0
+        */
+       ASTNode.NodeList modifiers = null;
+       
+       /**
+        * Returns structural property descriptor for the "modifiers" property
+        * of this node as used in JLS2.
+        * 
+        * @return the property descriptor
+        */
+       abstract SimplePropertyDescriptor internalModifiersProperty();
+
+       /**
+        * Returns structural property descriptor for the "modifiers" property
+        * of this node as used in JLS3.
+        * 
+        * @return the property descriptor
+        */
+       abstract ChildListPropertyDescriptor internalModifiers2Property();
+
+       /**
+        * Returns structural property descriptor for the "modifiers" property
+        * of this node as used in JLS3.
+        * 
+        * @return the property descriptor
+        * @since 3.1
+        */
+       public final ChildListPropertyDescriptor getModifiersProperty() {
+               // important: return property for AST.JLS3
+               return internalModifiers2Property();
+       }
+
+       /**
+        * Returns structural property descriptor for the "javadoc" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        */
+       abstract ChildPropertyDescriptor internalJavadocProperty();
+
+       /**
+        * Returns structural property descriptor for the "javadoc" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        * @since 3.1
+        */
+       public final ChildPropertyDescriptor getJavadocProperty() {
+               return internalJavadocProperty();
+       }
+
+       /**
+        * Creates and returns a structural property descriptor for the
+        * "javadoc" property declared on the given concrete node type.
+        * 
+        * @return the property descriptor
+        */
+       static final ChildPropertyDescriptor internalJavadocPropertyFactory(Class nodeClass) {
+               return new ChildPropertyDescriptor(nodeClass, "javadoc", Javadoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+       }
+       
+       /**
+        * Creates and returns a structural property descriptor for the
+        * "modifiers" property declared on the given concrete node type.
+        * 
+        * @return the property descriptor
+        */
+       static final SimplePropertyDescriptor internalModifiersPropertyFactory(Class nodeClass) {
+               return new SimplePropertyDescriptor(nodeClass, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+       }
+       
+       /**
+        * Creates and returns a structural property descriptor for the
+        * "modifiers" property declared on the given concrete node type.
+        * 
+        * @return the property descriptor
+        */
+       static final ChildListPropertyDescriptor internalModifiers2PropertyFactory(Class nodeClass) {
+               return new ChildListPropertyDescriptor(nodeClass, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+       }
+       
+       /**
+        * Creates a new AST node for a body declaration node owned by the 
+        * given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       BodyDeclaration(AST ast) {
+               super(ast);
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.modifiers = new ASTNode.NodeList(internalModifiers2Property());
+               }
+       }
+       
+       /**
+        * Returns the doc comment node.
+        * 
+        * @return the doc comment node, or <code>null</code> if none
+        */
+       public Javadoc getJavadoc() {
+               return this.optionalDocComment;
+       }
+
+       /**
+        * Sets or clears the doc comment node.
+        * 
+        * @param docComment the doc comment node, or <code>null</code> if none
+        * @exception IllegalArgumentException if the doc comment string is invalid
+        */
+       public void setJavadoc(Javadoc docComment) {
+               ChildPropertyDescriptor p = internalJavadocProperty();
+               ASTNode oldChild = this.optionalDocComment;
+               preReplaceChild(oldChild, docComment, p);
+               this.optionalDocComment = docComment;
+               postReplaceChild(oldChild, docComment, p);
+       }
+
+       /**
+        * Returns the modifiers explicitly specified on this declaration.
+        * <p>
+        * In the JLS3 API, this method is a convenience method that
+        * computes these flags from <code>modifiers()</code>.
+        * </p>
+        * 
+        * @return the bit-wise or of <code>Modifier</code> constants
+        * @see Modifier
+        */ 
+       public int getModifiers() {
+               // more efficient than checking getAST().API_LEVEL
+               if (this.modifiers == null) {
+                       // JLS2 behavior - bona fide property
+                       return this.modifierFlags;
+               } else {
+                       // JLS3 behavior - convenience method
+                       // performance could be improved by caching computed flags
+                       // but this would require tracking changes to this.modifiers
+                       int computedmodifierFlags = Modifier.NONE;
+                       for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+                               Object x = it.next();
+                               if (x instanceof Modifier) {
+                                       computedmodifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+                               }
+                       }
+                       return computedmodifierFlags;
+               }
+       }
+
+       /**
+        * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+        * 
+        * @param modifiers the given modifiers (bit-wise or of <code>Modifier</code> constants)
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @see Modifier
+        * @deprecated In the JLS3 API, this method is replaced by 
+        * {@link #modifiers()} which contains a list of a <code>Modifier</code> nodes.
+        */ 
+       public void setModifiers(int modifiers) {
+               internalSetModifiers(modifiers);
+       }
+       
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ final void internalSetModifiers(int pmodifiers) {
+               // more efficient than just calling supportedOnlyIn2() to check
+               if (this.modifiers != null) {
+                       supportedOnlyIn2();
+               }
+               SimplePropertyDescriptor p = internalModifiersProperty();
+               preValueChange(p);
+               this.modifierFlags = pmodifiers;
+               postValueChange(p);
+       }
+
+       /**
+        * Returns the live ordered list of modifiers and annotations
+        * of this declaration (added in JLS3 API).
+        * 
+        * @return the live list of modifiers and annotations
+        *    (element type: <code>IExtendedModifier</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public List modifiers() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.modifiers == null) {
+                       unsupportedIn2();
+               }
+               return this.modifiers;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 3 * 4;
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BooleanLiteral.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BooleanLiteral.java
new file mode 100644 (file)
index 0000000..9685b89
--- /dev/null
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Boolean literal node.
+ * 
+ * <pre>
+ * BooleanLiteral:
+ *             <b>true</b>
+ *             <b>false</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class BooleanLiteral extends Expression {
+       
+       /**
+        * The "booleanValue" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor BOOLEAN_VALUE_PROPERTY = 
+               new SimplePropertyDescriptor(BooleanLiteral.class, "booleanValue", boolean.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(2);
+               createPropertyList(BooleanLiteral.class, properyList);
+               addProperty(BOOLEAN_VALUE_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 boolean; defaults to the literal for <code>false</code>.
+        */
+       private boolean value = false;
+
+       /**
+        * Creates a new unparented boolean literal node owned by the given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       BooleanLiteral(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean newValue) {
+               if (property == BOOLEAN_VALUE_PROPERTY) {
+                       if (get) {
+                               return booleanValue();
+                       } else {
+                               setBooleanValue(newValue);
+                               return false;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetBooleanProperty(property, get, newValue);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return BOOLEAN_LITERAL;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               BooleanLiteral result = new BooleanLiteral(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setBooleanValue(booleanValue());
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the boolean value of this boolean literal node.
+        * 
+        * @return <code>true</code> for the boolean literal spelled
+        *    <code>"true"</code>, and <code>false</code> for the boolean literal 
+        *    spelled <code>"false"</code>.
+        */ 
+       public boolean booleanValue() {
+               return this.value;
+       }
+               
+       /**
+        * Sets the boolean value of this boolean literal node.
+        * 
+        * @param value <code>true</code> for the boolean literal spelled
+        *    <code>"true"</code>, and <code>false</code> for the boolean literal 
+        *    spelled <code>"false"</code>.
+        */ 
+       public void setBooleanValue(boolean value) {
+               preValueChange(BOOLEAN_VALUE_PROPERTY);
+               this.value = value;
+               postValueChange(BOOLEAN_VALUE_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BreakStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/BreakStatement.java
new file mode 100644 (file)
index 0000000..9276688
--- /dev/null
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Break statement AST node type.
+ *
+ * <pre>
+ * BreakStatement:
+ *    <b>break</b> [ Identifier ] <b>;</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class BreakStatement extends Statement {
+                       
+       /**
+        * The "label" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor LABEL_PROPERTY = 
+               new ChildPropertyDescriptor(BreakStatement.class, "label", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(2);
+               createPropertyList(BreakStatement.class, properyList);
+               addProperty(LABEL_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 label, or <code>null</code> if none; none by default.
+        */
+       private SimpleName optionalLabel = null;
+
+       /**
+        * Creates a new unparented break statement node owned by the given 
+        * AST. By default, the break statement has no label.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       BreakStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == LABEL_PROPERTY) {
+                       if (get) {
+                               return getLabel();
+                       } else {
+                               setLabel((SimpleName) 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.
+        */
+       final int getNodeType0() {
+               return BREAK_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               BreakStatement result = new BreakStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setLabel((SimpleName) ASTNode.copySubtree(target, getLabel()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getLabel());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the label of this break statement, or <code>null</code> if
+        * there is none.
+        * 
+        * @return the label, or <code>null</code> if there is none
+        */ 
+       public SimpleName getLabel() {
+               return this.optionalLabel;
+       }
+       
+       /**
+        * Sets or clears the label of this break statement.
+        * 
+        * @param label the label, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setLabel(SimpleName label) {
+               ASTNode oldChild = this.optionalLabel;
+               preReplaceChild(oldChild, label, LABEL_PROPERTY);
+               this.optionalLabel = label;
+               postReplaceChild(oldChild, label, LABEL_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalLabel == null ? 0 : getLabel().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CastExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CastExpression.java
new file mode 100644 (file)
index 0000000..145bd1a
--- /dev/null
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Cast expression AST node type.
+ *
+ * <pre>
+ * CastExpression:
+ *    <b>(</b> Type <b>)</b> Expression 
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class CastExpression extends Expression {
+
+       /**
+        * The "type" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(CastExpression.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(CastExpression.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(3);
+               createPropertyList(CastExpression.class, properyList);
+               addProperty(TYPE_PROPERTY, properyList);
+               addProperty(EXPRESSION_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 type; lazily initialized; defaults to a unspecified,
+        * legal type.
+        */
+       private Type type = null;
+
+       /**
+        * The expression; lazily initialized; defaults to a unspecified, but legal,
+        * expression.
+        */
+       private Expression expression = null;
+
+       /**
+        * Creates a new AST node for a cast expression owned by the given 
+        * AST. By default, the type and expression are unspecified (but legal).
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       CastExpression(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == TYPE_PROPERTY) {
+                       if (get) {
+                               return getType();
+                       } else {
+                               setType((Type) 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.
+        */
+       final int getNodeType0() {
+               return CAST_EXPRESSION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               CastExpression result = new CastExpression(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setType((Type) getType().clone(target));
+               result.setExpression((Expression) getExpression().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getType());
+                       acceptChild(visitor, getExpression());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the type in this cast expression.
+        * 
+        * @return the type
+        */ 
+       public Type getType() {
+               if (this.type == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.type == null) {
+                                       preLazyInit();
+                                       this.type = this.ast.newPrimitiveType(PrimitiveType.INT);
+                                       postLazyInit(this.type, TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.type;
+       }
+
+       /**
+        * Sets the type in this cast expression to the given type.
+        * 
+        * @param type the new type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setType(Type type) {
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.type;
+               preReplaceChild(oldChild, type, TYPE_PROPERTY);
+               this.type = type;
+               postReplaceChild(oldChild, type, TYPE_PROPERTY);
+       }
+       
+       /**
+        * Returns the expression of this cast expression.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new SimpleName(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.expression;
+       }
+               
+       /**
+        * Sets the expression of this cast expression.
+        * 
+        * @param expression the new expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.expression == null ? 0 : getExpression().treeSize())
+                       + (this.type == null ? 0 : getType().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CatchClause.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CatchClause.java
new file mode 100644 (file)
index 0000000..d5bd605
--- /dev/null
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Catch clause AST node type.
+ *
+ * <pre>
+ * CatchClause:
+ *    <b>catch</b> <b>(</b> FormalParameter <b>)</b> Block
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class CatchClause extends ASTNode {
+       
+       /**
+        * The "exception" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXCEPTION_PROPERTY = 
+               new ChildPropertyDescriptor(CatchClause.class, "exception", SingleVariableDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "body" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor BODY_PROPERTY = 
+               new ChildPropertyDescriptor(CatchClause.class, "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(3);
+               createPropertyList(CatchClause.class, properyList);
+               addProperty(EXCEPTION_PROPERTY, properyList);
+               addProperty(BODY_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 body; lazily initialized; defaults to an empty block.
+        */
+       private Block body = null;
+
+       /**
+        * The exception variable declaration; lazily initialized; defaults to a
+        * unspecified, but legal, variable declaration.
+        */
+       private SingleVariableDeclaration exceptionDecl = null;
+
+       /**
+        * Creates a new AST node for a catch clause owned by the given 
+        * AST. By default, the catch clause declares an unspecified, but legal, 
+        * exception declaration and has an empty block.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       CatchClause(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXCEPTION_PROPERTY) {
+                       if (get) {
+                               return getException();
+                       } else {
+                               setException((SingleVariableDeclaration) child);
+                               return null;
+                       }
+               }
+               if (property == BODY_PROPERTY) {
+                       if (get) {
+                               return getBody();
+                       } else {
+                               setBody((Block) 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.
+        */
+       final int getNodeType0() {
+               return CATCH_CLAUSE;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               CatchClause result = new CatchClause(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setBody((Block) getBody().clone(target));
+               result.setException(
+                       (SingleVariableDeclaration) ASTNode.copySubtree(target, getException()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getException());
+                       acceptChild(visitor, getBody());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the exception variable declaration of this catch clause.
+        * 
+        * @return the exception variable declaration node
+        */ 
+       public SingleVariableDeclaration getException() {
+               if (this.exceptionDecl == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.exceptionDecl == null) {
+                                       preLazyInit();
+                                       this.exceptionDecl = new SingleVariableDeclaration(this.ast);
+                                       postLazyInit(this.exceptionDecl, EXCEPTION_PROPERTY);
+                               }
+                       }
+               }
+               return this.exceptionDecl;
+       }
+               
+       /**
+        * Sets the variable declaration of this catch clause.
+        * 
+        * @param exception the exception variable declaration node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setException(SingleVariableDeclaration exception) {
+               if (exception == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.exceptionDecl;
+               preReplaceChild(oldChild, exception, EXCEPTION_PROPERTY);
+               this.exceptionDecl= exception;
+               postReplaceChild(oldChild, exception, EXCEPTION_PROPERTY);
+       }
+       
+       /**
+        * Returns the body of this catch clause.
+        * 
+        * @return the catch clause body
+        */ 
+       public Block getBody() {
+               if (this.body == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.body == null) {
+                                       preLazyInit();
+                                       this.body = new Block(this.ast);
+                                       postLazyInit(this.body, BODY_PROPERTY);
+                               }
+                       }
+               }
+               return this.body;
+       }
+       
+       /**
+        * Sets the body of this catch clause.
+        * 
+        * @param body the catch clause block node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setBody(Block body) {
+               if (body == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.body;
+               preReplaceChild(oldChild, body, BODY_PROPERTY);
+               this.body = body;
+               postReplaceChild(oldChild, body, BODY_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.exceptionDecl == null ? 0 : getException().treeSize())
+                       + (this.body == null ? 0 : getBody().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CharacterLiteral.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CharacterLiteral.java
new file mode 100644 (file)
index 0000000..1f1e1f7
--- /dev/null
@@ -0,0 +1,389 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.ScannerHelper;
+import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Character literal nodes.
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class CharacterLiteral extends Expression {
+
+       /**
+        * The "escapedValue" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor ESCAPED_VALUE_PROPERTY = 
+               new SimplePropertyDescriptor(CharacterLiteral.class, "escapedValue", String.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(2);
+               createPropertyList(CharacterLiteral.class, properyList);
+               addProperty(ESCAPED_VALUE_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 literal string, including quotes and escapes; defaults to the 
+        * literal for the character 'X'.
+        */
+       private String escapedValue = "\'X\'";//$NON-NLS-1$
+
+       /**
+        * Creates a new unparented character literal node owned by the given AST.
+        * By default, the character literal denotes an unspecified character.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       CharacterLiteral(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == ESCAPED_VALUE_PROPERTY) {
+                       if (get) {
+                               return getEscapedValue();
+                       } else {
+                               setEscapedValue((String) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return CHARACTER_LITERAL;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               CharacterLiteral result = new CharacterLiteral(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setEscapedValue(getEscapedValue());
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the string value of this literal node. The value is the sequence
+        * of characters that would appear in the source program, including
+        * enclosing single quotes and embedded escapes.
+        * 
+        * @return the escaped string value, including enclosing single quotes
+        *    and embedded escapes
+        */ 
+       public String getEscapedValue() {
+               return this.escapedValue;
+       }
+               
+       /**
+        * Sets the string value of this literal node. The value is the sequence
+        * of characters that would appear in the source program, including
+        * enclosing single quotes and embedded escapes. For example,
+        * <ul>
+        * <li><code>'a'</code> <code>setEscapedValue("\'a\'")</code></li>
+        * <li><code>'\n'</code> <code>setEscapedValue("\'\\n\'")</code></li>
+        * </ul>
+        * 
+        * @param value the string value, including enclosing single quotes
+        *    and embedded escapes
+        * @exception IllegalArgumentException if the argument is incorrect
+        */ 
+       public void setEscapedValue(String value) {
+               // check setInternalEscapedValue(String) if this method is changed
+               if (value == null) {
+                       throw new IllegalArgumentException();
+               }
+               Scanner scanner = this.ast.scanner;
+               char[] source = value.toCharArray();
+               scanner.setSource(source);
+               scanner.resetTo(0, source.length);
+               try {
+                       int tokenType = scanner.getNextToken();
+                       switch(tokenType) {
+                               case TerminalTokens.TokenNameCharacterLiteral:
+                                       break;
+                               default:
+                                       throw new IllegalArgumentException();
+                       }
+               } catch(InvalidInputException e) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(ESCAPED_VALUE_PROPERTY);
+               this.escapedValue = value;
+               postValueChange(ESCAPED_VALUE_PROPERTY);
+       }
+
+
+       /* (omit javadoc for this method)
+        * This method is a copy of setEscapedValue(String) that doesn't do any validation.
+        */
+       void internalSetEscapedValue(String value) {
+               preValueChange(ESCAPED_VALUE_PROPERTY);
+               this.escapedValue = value;
+               postValueChange(ESCAPED_VALUE_PROPERTY);
+       }
+
+       /**
+        * Returns the value of this literal node. 
+        * <p>
+        * For example,
+        * <pre>
+        * CharacterLiteral s;
+        * s.setEscapedValue("\'x\'");
+        * assert s.charValue() == 'x';
+        * </pre>
+        * </p>
+        * 
+        * @return the character value without enclosing quotes and embedded
+        *    escapes
+        * @exception IllegalArgumentException if the literal value cannot be converted
+        */ 
+       public char charValue() {
+               Scanner scanner = this.ast.scanner;
+               char[] source = escapedValue.toCharArray();
+               scanner.setSource(source);
+               scanner.resetTo(0, source.length);
+               int firstChar = scanner.getNextChar();
+               int secondChar = scanner.getNextChar();
+
+               if (firstChar == -1 || firstChar != '\'') {
+                       throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+               }
+               char value = (char) secondChar;
+               int nextChar = scanner.getNextChar();
+               if (secondChar == '\\') {
+                       if (nextChar == -1) {
+                               throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+                       }
+                       switch(nextChar) {
+                               case 'b' :
+                                       value = '\b';
+                                       break;
+                               case 't' :
+                                       value = '\t';
+                                       break;
+                               case 'n' :
+                                       value = '\n';
+                                       break;
+                               case 'f' :
+                                       value = '\f';
+                                       break;
+                               case 'r' :
+                                       value = '\r';
+                                       break;
+                               case '\"':
+                                       value = '\"';
+                                       break;
+                               case '\'':
+                                       value = '\'';
+                                       break;
+                               case '\\':
+                                       value = '\\';
+                                       break;
+                               default : //octal (well-formed: ended by a ' )
+                                       try {
+                                               if (ScannerHelper.isDigit((char) nextChar)) {
+                                                       int number = ScannerHelper.getNumericValue((char) nextChar);
+                                                       nextChar = scanner.getNextChar();
+                                                       if (nextChar == -1) {
+                                                               throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+                                                       }
+                                                       if (nextChar != '\'') {
+                                                               if (!ScannerHelper.isDigit((char) nextChar)) {
+                                                                       throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+                                                               }
+                                                               number = (number * 8) + ScannerHelper.getNumericValue((char) nextChar);
+                                                               nextChar = scanner.getNextChar();
+                                                               if (nextChar == -1) {
+                                                                       throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+                                                               }
+                                                               if (nextChar != '\'') {
+                                                                       if (!ScannerHelper.isDigit((char) nextChar)) {
+                                                                               throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+                                                                       }
+                                                                       number = (number * 8) + ScannerHelper.getNumericValue((char) nextChar);
+                                                               }
+                                                       }
+                                                       return (char) number;
+                                               } else {
+                                                       throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+                                               }
+                                       } catch (InvalidInputException e) {
+                                               throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+                                       }
+                       }
+                       nextChar = scanner.getNextChar();
+                       if (nextChar == -1) {
+                               throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+                       }
+               }
+               if (nextChar == -1 || nextChar != '\'') {
+                       throw new IllegalArgumentException("illegal character literal");//$NON-NLS-1$
+               }
+               return value;
+       }
+       /**
+        * Sets the value of this character literal node to the given character. 
+        * <p>
+        * For example,
+        * <pre>
+        * CharacterLiteral s;
+        * s.setCharValue('x');
+        * assert s.charValue() == 'x';
+        * assert s.getEscapedValue("\'x\'");
+        * </pre>
+        * </p>
+        * 
+        * @param value the character value
+        */
+       public void setCharValue(char value) {
+               StringBuffer b = new StringBuffer(3);
+               
+               b.append('\''); // opening delimiter
+               switch(value) {
+                       case '\b' :
+                               b.append("\\b"); //$NON-NLS-1$
+                               break;
+                       case '\t' :
+                               b.append("\\t"); //$NON-NLS-1$
+                               break;
+                       case '\n' :
+                               b.append("\\n"); //$NON-NLS-1$
+                               break;
+                       case '\f' :
+                               b.append("\\f"); //$NON-NLS-1$
+                               break;
+                       case '\r' :
+                               b.append("\\r"); //$NON-NLS-1$
+                               break;
+                       case '\"':
+                               b.append("\\\""); //$NON-NLS-1$
+                               break;
+                       case '\'':
+                               b.append("\\\'"); //$NON-NLS-1$
+                               break;
+                       case '\\':
+                               b.append("\\\\"); //$NON-NLS-1$
+                               break;
+                       case '\0' :
+                               b.append("\\0"); //$NON-NLS-1$
+                               break;
+                       case '\1' :
+                               b.append("\\1"); //$NON-NLS-1$
+                               break;
+                       case '\2' :
+                               b.append("\\2"); //$NON-NLS-1$
+                               break;
+                       case '\3' :
+                               b.append("\\3"); //$NON-NLS-1$
+                               break;
+                       case '\4' :
+                               b.append("\\4"); //$NON-NLS-1$
+                               break;
+                       case '\5' :
+                               b.append("\\5"); //$NON-NLS-1$
+                               break;
+                       case '\6' :
+                               b.append("\\6"); //$NON-NLS-1$
+                               break;
+                       case '\7' :
+                               b.append("\\7"); //$NON-NLS-1$
+                               break;                  
+                       default:
+                               b.append(value);
+               }
+               b.append('\''); // closing delimiter
+               setEscapedValue(b.toString());
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               int size = BASE_NODE_SIZE + 1 * 4 + stringSize(escapedValue);
+               return size;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ChildListPropertyDescriptor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ChildListPropertyDescriptor.java
new file mode 100644 (file)
index 0000000..750f5e0
--- /dev/null
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Descriptor for a child list property of an AST node.
+ * A child list property is one whose value is a list of
+ * {@link ASTNode}.
+ * 
+ * @see org.eclipse.jdt.core.dom.ASTNode#getStructuralProperty(StructuralPropertyDescriptor)
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class ChildListPropertyDescriptor extends StructuralPropertyDescriptor {
+       
+       /**
+        * Element type. For example, for a node type like
+        * CompilationUnit, the "imports" property is ImportDeclaration.class.
+        * <p>
+        * Field is private, but marked package-visible for fast
+        * access from ASTNode.
+        * </p>
+        */
+       final Class elementType;
+       
+       /**
+        * Indicates whether a cycle is possible.
+        * <p>
+        * Field is private, but marked package-visible for fast
+        * access from ASTNode.
+        * </p>
+        */
+       final boolean cycleRisk;        
+       
+       /**
+        * Creates a new child list property descriptor with the given property id.
+        * Note that this constructor is declared package-private so that
+        * property descriptors can only be created by the AST
+        * implementation.
+        * 
+        * @param nodeClass concrete AST node type that owns this property
+        * @param propertyId the property id
+        * @param elementType the element type of this property
+        * @param cycleRisk <code>true</code> if this property is at
+        * risk of cycles, and <code>false</code> if there is no worry about cycles
+        */
+       ChildListPropertyDescriptor(Class nodeClass, String propertyId, Class elementType, boolean cycleRisk) {
+               super(nodeClass, propertyId);
+               if (elementType == null) {
+                       throw new IllegalArgumentException();
+               }
+               this.elementType = elementType;
+               this.cycleRisk = cycleRisk;
+       }
+       
+       /**
+        * Returns the element type of this list property.
+        * <p>
+        * For example, for a node type like CompilationUnit,
+        * the "imports" property returns <code>ImportDeclaration.class</code>.
+        * </p>
+        * 
+        * @return the element type of the property
+        */
+       public final Class getElementType() {
+               return this.elementType;
+       }
+       
+       /**
+        * Returns whether this property is vulnerable to cycles.
+        * <p>
+        * A property is vulnerable to cycles if a node of the owning
+        * type (that is, the type that owns this property) could legally
+        * appear in the AST subtree below this property. For example,
+        * the body property of a
+        * {@link MethodDeclaration} node
+        * admits a body which might include statement that embeds 
+        * another {@link MethodDeclaration} node.
+        * On the other hand, the name property of a
+        * MethodDeclaration node admits only names, and thereby excludes
+        * another MethodDeclaration node.
+        * </p>
+        * 
+        * @return <code>true</code> if cycles are possible,
+        * and <code>false</code> if cycles are impossible
+        */
+       public final boolean cycleRisk() {
+               return this.cycleRisk;
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ChildPropertyDescriptor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ChildPropertyDescriptor.java
new file mode 100644 (file)
index 0000000..d9db206
--- /dev/null
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Descriptor for a child property of an AST node.
+ * A child property is one whose value is an
+ * {@link ASTNode}.
+ * 
+ * @see org.eclipse.jdt.core.dom.ASTNode#getStructuralProperty(StructuralPropertyDescriptor)
+ * @see org.eclipse.jdt.core.dom.ASTNode#setStructuralProperty(StructuralPropertyDescriptor, Object)
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class ChildPropertyDescriptor extends StructuralPropertyDescriptor {
+       
+       /**
+        * Child type. For example, for a node type like
+        * CompilationUnit, the "package" property is PackageDeclaration.class
+        */
+       private final Class childClass;
+       
+       /**
+        * Indicates whether the child is mandatory. A child property is allowed
+        * to be <code>null</code> only if it is not mandatory.
+        */
+       private final boolean mandatory;        
+       
+       /**
+        * Indicates whether a cycle is possible.
+        * Field is private, but marked package-visible for fast
+        * access from ASTNode.
+        */
+       final boolean cycleRisk;        
+       
+       /**
+        * Creates a new child property descriptor with the given property id.
+        * Note that this constructor is declared package-private so that
+        * property descriptors can only be created by the AST
+        * implementation.
+        * 
+        * @param nodeClass concrete AST node type that owns this property
+        * @param propertyId the property id
+        * @param childType the child type of this property
+        * @param mandatory <code>true</code> if the property is mandatory,
+        * and <code>false</code> if it is may be <code>null</code>
+        * @param cycleRisk <code>true</code> if this property is at
+        * risk of cycles, and <code>false</code> if there is no worry about cycles
+        */
+       ChildPropertyDescriptor(Class nodeClass, String propertyId, Class childType, boolean mandatory, boolean cycleRisk) {
+               super(nodeClass, propertyId);
+               if (childType == null || !ASTNode.class.isAssignableFrom(childType)) {
+                       throw new IllegalArgumentException();
+               }
+               this.childClass = childType;
+               this.mandatory = mandatory;
+               this.cycleRisk = cycleRisk;
+       }
+       
+       /**
+        * Returns the child type of this property.
+        * <p>
+        * For example, for a node type like CompilationUnit,
+        * the "package" property returns <code>PackageDeclaration.class</code>.
+        * </p>
+        * 
+        * @return the child type of the property
+        */
+       public final Class getChildType() {
+               return this.childClass;
+       }
+       
+       /**
+        * Returns whether this property is mandatory. A property value
+        * is not allowed to be <code>null</code> if it is mandatory.
+        * 
+        * @return <code>true</code> if the property is mandatory,
+        * and <code>false</code> if it is may be <code>null</code>
+        */
+       public final boolean isMandatory() {
+               return this.mandatory;
+       }
+       
+       /**
+        * Returns whether this property is vulnerable to cycles.
+        * <p>
+        * A property is vulnerable to cycles if a node of the owning
+        * type (that is, the type that owns this property) could legally
+        * appear in the AST subtree below this property. For example,
+        * the body property of a
+        * {@link MethodDeclaration} node
+        * admits a body which might include statement that embeds 
+        * another {@link MethodDeclaration} node.
+        * On the other hand, the name property of a
+        * MethodDeclaration node admits only names, and thereby excludes
+        * another MethodDeclaration node.
+        * </p>
+        * 
+        * @return <code>true</code> if cycles are possible,
+        * and <code>false</code> if cycles are impossible
+        */
+       public final boolean cycleRisk() {
+               return this.cycleRisk;
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ClassInstanceCreation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ClassInstanceCreation.java
new file mode 100644 (file)
index 0000000..df92ea2
--- /dev/null
@@ -0,0 +1,585 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class instance creation expression AST node type.
+ * For JLS2:
+ * <pre>
+ * ClassInstanceCreation:
+ *        [ Expression <b>.</b> ] <b>new</b> Name
+ *            <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ *            [ AnonymousClassDeclaration ]
+ * </pre>
+ * For JLS3, type arguments are added
+ * and the type name is generalized to a type so that parameterized
+ * types can be instantiated:
+ * <pre>
+ * ClassInstanceCreation:
+ *        [ Expression <b>.</b> ]
+ *            <b>new</b> [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ *            Type <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ *            [ AnonymousClassDeclaration ]
+ * </pre>
+ * <p>
+ * Not all node arragements will represent legal Java constructs. In particular,
+ * it is nonsense if the type is a primitive type or an array type (primitive
+ * types cannot be instantiated, and array creations must be represented with
+ * <code>ArrayCreation</code> nodes). The normal use is when the type is a
+ * simple, qualified, or parameterized type.
+ * </p>
+ * <p>
+ * A type like "A.B" can be represented either of two ways:
+ * <ol>
+ * <li>
+ * <code>QualifiedType(SimpleType(SimpleName("A")),SimpleName("B"))</code>
+ * </li>
+ * <li>
+ * <code>SimpleType(QualifiedName(SimpleName("A"),SimpleName("B")))</code>
+ * </li>
+ * </ol>
+ * The first form is preferred when "A" is known to be a type (as opposed
+ * to a package). However, a parser cannot always determine this. Clients
+ * should be prepared to handle either rather than make assumptions.
+ * (Note also that the first form became possible as of JLS3; only the second
+ * form existed in JLS2.)
+ * </p>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ClassInstanceCreation extends Expression {
+
+       /**
+        * The "typeArguments" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(ClassInstanceCreation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(ClassInstanceCreation.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "name" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(ClassInstanceCreation.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "type" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildPropertyDescriptor TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(ClassInstanceCreation.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "arguments" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(ClassInstanceCreation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "anonymousClassDeclaration" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor ANONYMOUS_CLASS_DECLARATION_PROPERTY = 
+               new ChildPropertyDescriptor(ClassInstanceCreation.class, "anonymousClassDeclaration", AnonymousClassDeclaration.class, OPTIONAL, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List properyList = new ArrayList(5);
+               createPropertyList(ClassInstanceCreation.class, properyList);
+               addProperty(EXPRESSION_PROPERTY, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               addProperty(ARGUMENTS_PROPERTY, properyList);
+               addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+               
+               properyList = new ArrayList(6);
+               createPropertyList(ClassInstanceCreation.class, properyList);
+               addProperty(EXPRESSION_PROPERTY, properyList);
+               addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+               addProperty(TYPE_PROPERTY, properyList);
+               addProperty(ARGUMENTS_PROPERTY, properyList);
+               addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_3_0 = 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The optional expression; <code>null</code> for none; defaults to none.
+        */
+       private Expression optionalExpression = null;
+       
+       /**
+        * The type arguments (element type: <code>Type</code>). 
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * @since 3.1
+        */
+       private ASTNode.NodeList typeArguments = null;
+
+       /**
+        * The type name; lazily initialized; defaults to a unspecified,
+        * legal type name. Not used in JLS3.
+        */
+       private Name typeName = null;
+       
+       /**
+        * The type; lazily initialized; defaults to a unspecified type.
+        * @since 3.0
+        */
+       private Type type = null;
+       
+       /**
+        * The list of argument expressions (element type: 
+        * <code>Expression</code>). Defaults to an empty list.
+        */
+       private ASTNode.NodeList arguments =
+               new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+               
+       /**
+        * The optional anonymous class declaration; <code>null</code> for none; 
+        * defaults to none.
+        */
+       private AnonymousClassDeclaration optionalAnonymousClassDeclaration = null;
+       
+       /**
+        * Creates a new AST node for a class instance creation expression owned 
+        * by the given AST. By default, there is no qualifying expression,
+        * an empty list of type parameters, an unspecified type, an empty
+     * list of arguments, and does not declare an anonymous class.
+        * <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
+        */
+       ClassInstanceCreation (AST ast) {
+               super(ast);
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+               }
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((Name) child);
+                               return null;
+                       }
+               }
+               if (property == TYPE_PROPERTY) {
+                       if (get) {
+                               return getType();
+                       } else {
+                               setType((Type) child);
+                               return null;
+                       }
+               }
+               if (property == ANONYMOUS_CLASS_DECLARATION_PROPERTY) {
+                       if (get) {
+                               return getAnonymousClassDeclaration();
+                       } else {
+                               setAnonymousClassDeclaration((AnonymousClassDeclaration) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == ARGUMENTS_PROPERTY) {
+                       return arguments();
+               }
+               if (property == TYPE_ARGUMENTS_PROPERTY) {
+                       return typeArguments();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return CLASS_INSTANCE_CREATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ClassInstanceCreation result = new ClassInstanceCreation(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setExpression(
+                       (Expression) ASTNode.copySubtree(target, getExpression()));
+               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                       result.setName((Name) getName().clone(target));
+               }
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+                       result.setType((Type) getType().clone(target));
+               }
+               result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+               result.setAnonymousClassDeclaration(
+                       (AnonymousClassDeclaration) 
+                          ASTNode.copySubtree(target, getAnonymousClassDeclaration()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getExpression());
+                       if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                               acceptChild(visitor, getName());
+                       }
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChildren(visitor, this.typeArguments);
+                               acceptChild(visitor, getType());
+                       }
+                       acceptChildren(visitor, this.arguments);
+                       acceptChild(visitor, getAnonymousClassDeclaration());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this class instance creation expression, or 
+        * <code>null</code> if there is none.
+        * 
+        * @return the expression node, or <code>null</code> if there is none
+        */ 
+       public Expression getExpression() {
+               return this.optionalExpression;
+       }
+       
+       /**
+        * Sets or clears the expression of this class instance creation expression.
+        * 
+        * @param expression the expression node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               // a ClassInstanceCreation may occur inside an Expression
+               // must check cycles
+               ASTNode oldChild = this.optionalExpression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.optionalExpression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of type arguments of this class
+        * instance creation (added in JLS3 API).
+        * 
+        * @return the live list of type arguments
+        *    (element type: <code>Type</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public List typeArguments() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.typeArguments == null) {
+                       unsupportedIn2();
+               }
+               return this.typeArguments;
+       }
+       
+    /**
+        * Returns the name of the type instantiated in this class instance 
+        * creation expression (JLS2 API only).
+        * 
+        * @return the type name node
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @deprecated In the JLS3 API, this method is replaced by
+        * {@link #getType()}, which returns a <code>Type</code> instead of a
+        * <code>Name</code>.
+        */ 
+       public Name getName() {
+               return internalGetName();
+       }
+
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ Name internalGetName() {
+           supportedOnlyIn2();
+               if (this.typeName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.typeName == null) {
+                                       preLazyInit();
+                                       this.typeName = new SimpleName(this.ast);
+                                       postLazyInit(this.typeName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return typeName;
+       }
+       
+       /**
+        * Sets the name of the type instantiated in this class instance 
+        * creation expression (JLS2 API only).
+        * 
+        * @param name the new type name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>`
+        * </ul>
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @deprecated In the JLS3 API, this method is replaced by 
+        * {@link #setType(Type)}, which expects a <code>Type</code> instead of
+        * a <code>Name</code>.
+        */ 
+       public void setName(Name name) {
+               internalSetName(name);
+       }
+
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ void internalSetName(Name name) {
+           supportedOnlyIn2();
+               if (name == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.typeName;
+               preReplaceChild(oldChild, name, NAME_PROPERTY);
+               this.typeName = name;
+               postReplaceChild(oldChild, name, NAME_PROPERTY);
+       }
+
+       /**
+        * Returns the type instantiated in this class instance creation
+        * expression (added in JLS3 API).
+        * 
+        * @return the type node
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public Type getType() {
+           unsupportedIn2();
+               if (this.type == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.type == null) {
+                                       preLazyInit();
+                                       this.type = new SimpleType(this.ast);
+                                       postLazyInit(this.type, TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.type;
+       }
+       
+       /**
+        * Sets the type instantiated in this class instance creation
+        * expression (added in JLS3 API).
+        * 
+        * @param type the new type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>`
+        * </ul>
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public void setType(Type type) {
+           unsupportedIn2();
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.type;
+               preReplaceChild(oldChild, type, TYPE_PROPERTY);
+               this.type = type;
+               postReplaceChild(oldChild, type, TYPE_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of argument expressions in this class
+        * instance creation expression.
+        * 
+        * @return the live list of argument expressions (possibly empty)
+        *    (element type: <code>Expression</code>)
+        */ 
+       public List arguments() {
+               return this.arguments;
+       }
+       
+       /**
+        * Returns the anonymous class declaration introduced by this
+        * class instance creation expression, if it has one.
+        * 
+        * @return the anonymous class declaration, or <code>null</code> if none
+        */ 
+       public AnonymousClassDeclaration getAnonymousClassDeclaration() {
+               return this.optionalAnonymousClassDeclaration;
+       }
+       
+       /**
+        * Sets whether this class instance creation expression declares
+        * an anonymous class (that is, has class body declarations).
+        * 
+        * @param decl the anonymous class declaration, or <code>null</code> 
+        *    if none
+        */ 
+       public void setAnonymousClassDeclaration(AnonymousClassDeclaration decl) {
+               ASTNode oldChild = this.optionalAnonymousClassDeclaration;
+               preReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+               this.optionalAnonymousClassDeclaration = decl;
+               postReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+       }
+
+       /**
+        * Resolves and returns the binding for the constructor invoked by this
+        * expression. For anonymous classes, the binding is that of the anonymous
+        * constructor.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the constructor binding, or <code>null</code> if the binding
+        *    cannot be resolved
+        */     
+       public IMethodBinding resolveConstructorBinding() {
+               return this.ast.getBindingResolver().resolveConstructor(this);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 6 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               // n.b. type == null for ast.API_LEVEL == JLS2
+               // n.b. typeArguments == null for ast.API_LEVEL == JLS2
+               // n.b. typeName == null for ast.API_LEVEL >= JLS3
+               return 
+                       memSize()
+                       + (this.typeName == null ? 0 : getName().treeSize())
+                       + (this.type == null ? 0 : getType().treeSize())
+                       + (this.optionalExpression == null ? 0 : getExpression().treeSize())
+                       + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+                       + (this.arguments == null ? 0 : this.arguments.listSize())
+                       + (this.optionalAnonymousClassDeclaration == null ? 0 : getAnonymousClassDeclaration().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Comment.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Comment.java
new file mode 100644 (file)
index 0000000..5443804
--- /dev/null
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Abstract base class for all AST nodes that represent comments.
+ * There are exactly three kinds of comment: 
+ * line comments ({@link LineComment}),
+ * block comments ({@link BlockComment}), and
+ * doc comments ({@link Javadoc}).
+ * <p>
+ * <pre>
+ * Comment:
+ *     LineComment
+ *     BlockComment
+ *     Javadoc
+ * </pre>
+ * </p>
+ * 
+ * @since 3.0
+ */
+public abstract class Comment extends ASTNode {
+       
+       /**
+        * Alternate root node, or <code>null</code> if none.
+        * Initially <code>null</code>.
+        */
+       private ASTNode alternateRoot = null;
+
+       /**
+        * Creates a new AST node for a comment owned by the given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       Comment(AST ast) {
+               super(ast);
+       }
+       
+       /**
+        * Returns whether this comment is a block comment
+        * (<code>BlockComment</code>).
+        * 
+        * @return <code>true</code> if this is a block comment, and 
+        *    <code>false</code> otherwise
+        */
+       public final boolean isBlockComment() {
+               return (this instanceof BlockComment);
+       }
+       
+       /**
+        * Returns whether this comment is a line comment
+        * (<code>LineComment</code>).
+        * 
+        * @return <code>true</code> if this is a line comment, and 
+        *    <code>false</code> otherwise
+        */
+       public final boolean isLineComment() {
+               return (this instanceof LineComment);
+       }
+       
+       /**
+        * Returns whether this comment is a doc comment
+        * (<code>Javadoc</code>).
+        * 
+        * @return <code>true</code> if this is a doc comment, and 
+        *    <code>false</code> otherwise
+        */
+       public final boolean isDocComment() {
+               return (this instanceof Javadoc);
+       }
+       
+       /**
+        * Returns the root AST node that this comment occurs
+        * within, or <code>null</code> if none (or not recorded).
+        * <p>
+        * Typically, the comment nodes created while parsing a compilation
+        * unit are not considered descendents of the normal AST
+        * root, namely an {@link CompilationUnit}. Instead, these
+        * comment nodes exist outside the normal AST and each is 
+        * a root in its own right. This optional property provides
+        * a well-known way to navigate from the comment to the
+        * compilation unit in such cases. Note that the alternate root
+        * property is not one of the comment node's children. It is simply a
+        * reference to a node.
+        * </p>
+        * 
+        * @return the alternate root node, or <code>null</code> 
+        * if none
+        * @see #setAlternateRoot(ASTNode)
+        */
+       public final ASTNode getAlternateRoot() {
+               return this.alternateRoot;
+       }
+       
+       /**
+        * Returns the root AST node that this comment occurs
+        * within, or <code>null</code> if none (or not recorded).
+        * <p>
+        * </p>
+        * 
+        * @param root the alternate root node, or <code>null</code> 
+        * if none
+        * @see #getAlternateRoot()
+        */
+       public final void setAlternateRoot(ASTNode root) {
+               // alternate root is *not* considered a structural property
+               // but we protect them nevertheless
+               checkModifiable();
+               this.alternateRoot = root;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 1 * 4;
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CompilationUnitResolver.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CompilationUnitResolver.java
new file mode 100644 (file)
index 0000000..fa57682
--- /dev/null
@@ -0,0 +1,942 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
+import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
+import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
+import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.ISourceType;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding;
+import net.sourceforge.phpdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
+import org.eclipse.jdt.internal.compiler.util.Messages;
+import org.eclipse.jdt.internal.core.BinaryMember;
+import org.eclipse.jdt.internal.core.CancelableNameEnvironment;
+import org.eclipse.jdt.internal.core.CancelableProblemFactory;
+import net.sourceforge.phpdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.NameLookup;
+import org.eclipse.jdt.internal.core.SourceRefElement;
+import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
+import org.eclipse.jdt.internal.core.util.BindingKeyResolver;
+import net.sourceforge.phpdt.internal.core.util.CommentRecorderParser;
+import org.eclipse.jdt.internal.core.util.DOMFinder;
+
+class CompilationUnitResolver extends Compiler {
+
+       /* A list of int */
+       static class IntArrayList {
+               public int[] list = new int[5];
+               public int length = 0;
+               public void add(int i) {
+                       if (this.list.length == this.length) {
+                               System.arraycopy(this.list, 0, this.list = new int[this.length*2], 0, this.length);
+                       }
+                               this.list[this.length++] = i;
+                       }
+               }
+
+       /*
+        * The sources that were requested.
+        * Map from file name (char[]) to ICompilationUnit.
+        */
+       HashtableOfObject requestedSources;
+
+       /*
+        * The binding keys that were requested.
+        * Map from file name (char[]) to BindingKey (or ArrayList if multiple keys in the same file).
+        */
+       HashtableOfObject requestedKeys;
+
+       DefaultBindingResolver.BindingTables bindingTables;
+
+       boolean hasCompilationAborted;
+
+       private IProgressMonitor monitor;
+
+       /**
+        * Answer a new CompilationUnitVisitor using the given name environment and compiler options.
+        * The environment and options will be in effect for the lifetime of the compiler.
+        * When the compiler is run, compilation results are sent to the given requestor.
+        *
+        *  @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
+        *      Environment used by the compiler in order to resolve type and package
+        *      names. The name environment implements the actual connection of the compiler
+        *      to the outside world (for example, in batch mode the name environment is performing
+        *      pure file accesses, reuse previous build state or connection to repositories).
+        *      Note: the name environment is responsible for implementing the actual classpath
+        *            rules.
+        *
+        *  @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
+        *      Configurable part for problem handling, allowing the compiler client to
+        *      specify the rules for handling problems (stop on first error or accumulate
+        *      them all) and at the same time perform some actions such as opening a dialog
+        *      in UI when compiling interactively.
+        *      @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
+        *
+        *      @param compilerOptions The compiler options to use for the resolution.
+        *
+        *  @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
+        *      Component which will receive and persist all compilation results and is intended
+        *      to consume them as they are produced. Typically, in a batch compiler, it is
+        *      responsible for writing out the actual .class files to the file system.
+        *      @see org.eclipse.jdt.internal.compiler.CompilationResult
+        *
+        *  @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
+        *      Factory used inside the compiler to create problem descriptors. It allows the
+        *      compiler client to supply its own representation of compilation problems in
+        *      order to avoid object conversions. Note that the factory is not supposed
+        *      to accumulate the created problems, the compiler will gather them all and hand
+        *      them back as part of the compilation unit result.
+        */
+       public CompilationUnitResolver(
+               INameEnvironment environment,
+               IErrorHandlingPolicy policy,
+               CompilerOptions compilerOptions,
+               ICompilerRequestor requestor,
+               IProblemFactory problemFactory,
+               IProgressMonitor monitor) {
+
+               super(environment, policy, compilerOptions, requestor, problemFactory);
+               this.hasCompilationAborted = false;
+               this.monitor =monitor;
+       }
+
+       /*
+        * Add additional source types
+        */
+       public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+               // Need to reparse the entire source of the compilation unit so as to get source positions
+               // (case of processing a source that was not known by beginToCompile (e.g. when asking to createBinding))
+               SourceTypeElementInfo sourceType = (SourceTypeElementInfo) sourceTypes[0];
+               accept((org.eclipse.jdt.internal.compiler.env.ICompilationUnit) sourceType.getHandle().getCompilationUnit(), accessRestriction);
+       }
+
+       /**
+        * Add the initial set of compilation units into the loop
+        *  ->  build compilation unit declarations, their bindings and record their results.
+        */
+       protected void beginToCompile(net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit[] sourceUnits, String[] bindingKeys) {
+               int sourceLength = sourceUnits.length;
+               int keyLength = bindingKeys.length;
+               int maxUnits = sourceLength + keyLength;
+               this.totalUnits = 0;
+               this.unitsToProcess = new CompilationUnitDeclaration[maxUnits];
+               int index = 0;
+
+               // walks the source units
+               this.requestedSources = new HashtableOfObject();
+               for (int i = 0; i < sourceLength; i++) {
+                       org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = sourceUnits[i];
+                       CompilationUnitDeclaration parsedUnit;
+                       CompilationResult unitResult =
+                               new CompilationResult(sourceUnit, index++, maxUnits, this.options.maxProblemsPerUnit);
+                       try {
+                               if (options.verbose) {
+                                       this.out.println(
+                                               Messages.bind(Messages.compilation_request,
+                                               new String[] {
+                                                       String.valueOf(index++ + 1),
+                                                       String.valueOf(maxUnits),
+                                                       new String(sourceUnit.getFileName())
+                                               }));
+                               }
+                               // diet parsing for large collection of units
+                               if (this.totalUnits < this.parseThreshold) {
+                                       parsedUnit = this.parser.parse(sourceUnit, unitResult);
+                               } else {
+                                       parsedUnit = this.parser.dietParse(sourceUnit, unitResult);
+                               }
+                               // initial type binding creation
+                               this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
+                               addCompilationUnit(sourceUnit, parsedUnit);
+                               this.requestedSources.put(unitResult.getFileName(), sourceUnit);
+                               worked(1);
+                       } finally {
+                               sourceUnits[i] = null; // no longer hold onto the unit
+                       }
+               }
+
+               // walk the binding keys
+               this.requestedKeys = new HashtableOfObject();
+               for (int i = 0; i < keyLength; i++) {
+                       BindingKeyResolver resolver = new BindingKeyResolver(bindingKeys[i], this, this.lookupEnvironment);
+                       resolver.parse(true/*pause after fully qualified name*/);
+                       // If it doesn't have a type name, then it is either an array type, package or base type, which will definitely not have a compilation unit.
+                       // Skipping it will speed up performance because the call will open jars. (theodora)
+                       CompilationUnitDeclaration parsedUnit = resolver.hasTypeName() ? resolver.getCompilationUnitDeclaration() : null;
+                       if (parsedUnit != null) {
+                               char[] fileName = parsedUnit.compilationResult.getFileName();
+                               Object existing = this.requestedKeys.get(fileName);
+                               if (existing == null)
+                                       this.requestedKeys.put(fileName, resolver);
+                               else if (existing instanceof ArrayList)
+                                       ((ArrayList) existing).add(resolver);
+                               else {
+                                       ArrayList list = new ArrayList();
+                                       list.add(existing);
+                                       list.add(resolver);
+                                       this.requestedKeys.put(fileName, list);
+                               }
+
+                       } else {
+                               char[] key = resolver.hasTypeName()
+                                       ? resolver.getKey().toCharArray() // binary binding
+                                       : CharOperation.concatWith(resolver.compoundName(), '.'); // package binding or base type binding
+                               this.requestedKeys.put(key, resolver);
+                       }
+                       worked(1);
+               }
+
+               // binding resolution
+               lookupEnvironment.completeTypeBindings();
+       }
+
+       IBinding createBinding(String key) {
+               if (this.bindingTables == null)
+                       throw new RuntimeException("Cannot be called outside ASTParser#createASTs(...)"); //$NON-NLS-1$
+               BindingKeyResolver keyResolver = new BindingKeyResolver(key, this, this.lookupEnvironment);
+               Binding compilerBinding = keyResolver.getCompilerBinding();
+               if (compilerBinding == null) return null;
+               DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, null/*no owner*/, this.bindingTables, false);
+               return resolver.getBinding(compilerBinding);
+       }
+
+       public static CompilationUnit convert(CompilationUnitDeclaration compilationUnitDeclaration, char[] source, int apiLevel, Map options, boolean needToResolveBindings, WorkingCopyOwner owner, DefaultBindingResolver.BindingTables bindingTables, int flags, IProgressMonitor monitor) {
+               BindingResolver resolver = null;
+               AST ast = AST.newAST(apiLevel);
+               ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+               CompilationUnit compilationUnit = null;
+               ASTConverter converter = new ASTConverter(options, needToResolveBindings, monitor);
+               if (needToResolveBindings) {
+                       resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope, owner, bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0);
+                       ast.setFlag(flags | AST.RESOLVED_BINDINGS);
+               } else {
+                       resolver = new BindingResolver();
+                       ast.setFlag(flags);
+               }
+               ast.setBindingResolver(resolver);
+               converter.setAST(ast);
+               compilationUnit = converter.convert(compilationUnitDeclaration, source);
+               compilationUnit.setLineEndTable(compilationUnitDeclaration.compilationResult.getLineSeparatorPositions());
+               ast.setDefaultNodeFlag(0);
+               ast.setOriginalModificationCount(ast.modificationCount());
+               return compilationUnit;
+       }
+
+       protected static CompilerOptions getCompilerOptions(Map options, boolean statementsRecovery) {
+               CompilerOptions compilerOptions = new CompilerOptions(options);
+               compilerOptions.performMethodsFullRecovery = statementsRecovery;
+               compilerOptions.performStatementsRecovery = statementsRecovery;
+               compilerOptions.parseLiteralExpressionsAsConstants = false;
+               compilerOptions.storeAnnotations = true /*store annotations in the bindings*/;
+               return compilerOptions;
+       }
+       /*
+        *  Low-level API performing the actual compilation
+        */
+       protected static IErrorHandlingPolicy getHandlingPolicy() {
+
+               // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
+               return new IErrorHandlingPolicy() {
+                       public boolean stopOnFirstError() {
+                               return false;
+                       }
+                       public boolean proceedOnErrors() {
+                               return false; // stop if there are some errors
+                       }
+               };
+       }
+
+       /*
+        * Answer the component to which will be handed back compilation results from the compiler
+        */
+       protected static ICompilerRequestor getRequestor() {
+               return new ICompilerRequestor() {
+                       public void acceptResult(CompilationResult compilationResult) {
+                               // do nothing
+                       }
+               };
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.Compiler#initializeParser()
+        */
+       public void initializeParser() {
+               this.parser = new CommentRecorderParser(this.problemReporter, false);
+       }
+       public void process(CompilationUnitDeclaration unit, int i) {
+               // don't resolve a second time the same unit (this would create the same binding twice)
+               char[] fileName = unit.compilationResult.getFileName();
+               if (!this.requestedKeys.containsKey(fileName) && !this.requestedSources.containsKey(fileName))
+                       super.process(unit, i);
+       }
+       /*
+        * Compiler crash recovery in case of unexpected runtime exceptions
+        */
+       protected void handleInternalException(
+                       Throwable internalException,
+                       CompilationUnitDeclaration unit,
+                       CompilationResult result) {
+               super.handleInternalException(internalException, unit, result);
+               if (unit != null) {
+                       removeUnresolvedBindings(unit);
+               }
+       }
+
+       /*
+        * Compiler recovery in case of internal AbortCompilation event
+        */
+       protected void handleInternalException(
+                       AbortCompilation abortException,
+                       CompilationUnitDeclaration unit) {
+               super.handleInternalException(abortException, unit);
+               if (unit != null) {
+                       removeUnresolvedBindings(unit);
+               }
+               this.hasCompilationAborted = true;
+       }
+
+       public static void parse(ICompilationUnit[] compilationUnits, ASTRequestor astRequestor, int apiLevel, Map options, int flags, IProgressMonitor monitor) {
+               try {
+                       CompilerOptions compilerOptions = new CompilerOptions(options);
+                       Parser parser = new CommentRecorderParser(
+                               new ProblemReporter(
+                                               DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+                                               compilerOptions,
+                                               new DefaultProblemFactory()),
+                               false);
+                       int unitLength = compilationUnits.length;
+                       if (monitor != null) monitor.beginTask("", unitLength); //$NON-NLS-1$
+                       for (int i = 0; i < unitLength; i++) {
+                               net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit sourceUnit = (net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit) compilationUnits[i];
+                               CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
+                               CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);
+
+                               if (compilationUnitDeclaration.ignoreMethodBodies) {
+                                       compilationUnitDeclaration.ignoreFurtherInvestigation = true;
+                                       // if initial diet parse did not work, no need to dig into method bodies.
+                                       continue;
+                               }
+
+                               //fill the methods bodies in order for the code to be generated
+                               //real parse of the method....
+                               net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+                               if (types != null) {
+                                       for (int j = 0, typeLength = types.length; j < typeLength; j++)
+                                               types[j].parseMethods(parser, compilationUnitDeclaration);
+                               }
+
+                               // convert AST
+                               CompilationUnit node = convert(compilationUnitDeclaration, parser.scanner.getSource(), apiLevel, options, false/*don't resolve binding*/, null/*no owner needed*/, null/*no binding table needed*/, flags /* flags */, monitor);
+                               node.setTypeRoot(compilationUnits[i]);
+
+                               // accept AST
+                               astRequestor.acceptAST(compilationUnits[i], node);
+
+                               if (monitor != null) monitor.worked(1);
+                       }
+               } finally {
+                       if (monitor != null) monitor.done();
+               }
+       }
+
+       public static CompilationUnitDeclaration parse(
+                       net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit sourceUnit,
+                       NodeSearcher nodeSearcher,
+                       Map settings,
+                       int flags) {
+               if (sourceUnit == null) {
+                       throw new IllegalStateException();
+               }
+               CompilerOptions compilerOptions = new CompilerOptions(settings);
+               boolean statementsRecovery = (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0;
+               compilerOptions.performMethodsFullRecovery = statementsRecovery;
+               compilerOptions.performStatementsRecovery = statementsRecovery;
+               Parser parser = new CommentRecorderParser(
+                       new ProblemReporter(
+                                       DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+                                       compilerOptions,
+                                       new DefaultProblemFactory()),
+                       false);
+               CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
+               CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);
+
+               if (compilationUnitDeclaration.ignoreMethodBodies) {
+                       compilationUnitDeclaration.ignoreFurtherInvestigation = true;
+                       // if initial diet parse did not work, no need to dig into method bodies.
+                       return null;
+               }
+
+               if (nodeSearcher != null) {
+                       char[] source = parser.scanner.getSource();
+                       int searchPosition = nodeSearcher.position;
+                       if (searchPosition < 0 || searchPosition > source.length) {
+                               // the position is out of range. There is no need to search for a node.
+                               return compilationUnitDeclaration;
+                       }
+
+                       compilationUnitDeclaration.traverse(nodeSearcher, compilationUnitDeclaration.scope);
+
+                       net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
+                       if (node == null) {
+                               return compilationUnitDeclaration;
+                       }
+
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
+
+                       if (node instanceof AbstractMethodDeclaration) {
+                               ((AbstractMethodDeclaration)node).parseStatements(parser, compilationUnitDeclaration);
+                       } else if (enclosingTypeDeclaration != null) {
+                               if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.Initializer) {
+                                       ((net.sourceforge.phpdt.internal.compiler.ast.Initializer) node).parseStatements(parser, enclosingTypeDeclaration, compilationUnitDeclaration);
+                               } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
+                                       ((net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration)node).parseMethods(parser, compilationUnitDeclaration);
+                               }
+                       }
+               } else {
+                       //fill the methods bodies in order for the code to be generated
+                       //real parse of the method....
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+                       if (types != null) {
+                               for (int i = 0, length = types.length; i < length; i++)
+                                       types[i].parseMethods(parser, compilationUnitDeclaration);
+                       }
+               }
+               return compilationUnitDeclaration;
+       }
+
+       public static void resolve(
+               ICompilationUnit[] compilationUnits,
+               String[] bindingKeys,
+               ASTRequestor requestor,
+               int apiLevel,
+               Map options,
+               IJavaProject javaProject,
+               WorkingCopyOwner owner,
+               int flags,
+               IProgressMonitor monitor) {
+
+               CancelableNameEnvironment environment = null;
+               CancelableProblemFactory problemFactory = null;
+               try {
+                       if (monitor != null) {
+                               int amountOfWork = (compilationUnits.length + bindingKeys.length) * 2; // 1 for beginToCompile, 1 for resolve
+                               monitor.beginTask("", amountOfWork); //$NON-NLS-1$
+                       }
+                       environment = new CancelableNameEnvironment(((JavaProject) javaProject), owner, monitor);
+                       problemFactory = new CancelableProblemFactory(monitor);
+                       CompilationUnitResolver resolver =
+                               new CompilationUnitResolver(
+                                       environment,
+                                       getHandlingPolicy(),
+                                       getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0),
+                                       getRequestor(),
+                                       problemFactory,
+                                       monitor);
+
+                       resolver.resolve(compilationUnits, bindingKeys, requestor, apiLevel, options, owner, flags);
+                       if (NameLookup.VERBOSE) {
+                               System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
+                               System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
+                       }
+               } catch (JavaModelException e) {
+                       // project doesn't exist -> simple parse without resolving
+                       parse(compilationUnits, requestor, apiLevel, options, flags, monitor);
+               } finally {
+                       if (monitor != null) monitor.done();
+                       if (environment != null) {
+                               environment.monitor = null; // don't hold a reference to this external object
+                       }
+                       if (problemFactory != null) {
+                               problemFactory.monitor = null; // don't hold a reference to this external object
+                       }
+               }
+       }
+       public static CompilationUnitDeclaration resolve(
+                       org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
+                       IJavaProject javaProject,
+                       NodeSearcher nodeSearcher,
+                       Map options,
+                       WorkingCopyOwner owner,
+                       int flags,
+                       IProgressMonitor monitor) throws JavaModelException {
+
+               CompilationUnitDeclaration unit = null;
+               CancelableNameEnvironment environment = null;
+               CancelableProblemFactory problemFactory = null;
+               CompilationUnitResolver resolver = null;
+               try {
+                       environment = new CancelableNameEnvironment(((JavaProject)javaProject), owner, monitor);
+                       problemFactory = new CancelableProblemFactory(monitor);
+                       resolver =
+                               new CompilationUnitResolver(
+                                       environment,
+                                       getHandlingPolicy(),
+                                       getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0),
+                                       getRequestor(),
+                                       problemFactory,
+                                       monitor);
+
+                       unit =
+                               resolver.resolve(
+                                       null, // no existing compilation unit declaration
+                                       sourceUnit,
+                                       nodeSearcher,
+                                       true, // method verification
+                                       true, // analyze code
+                                       true); // generate code
+                       if (resolver.hasCompilationAborted) {
+                               // the bindings could not be resolved due to missing types in name environment
+                               // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=86541
+                               CompilationUnitDeclaration unitDeclaration = parse(sourceUnit, nodeSearcher, options, flags);
+                               final int problemCount = unit.compilationResult.problemCount;
+                               if (problemCount != 0) {
+                                       unitDeclaration.compilationResult.problems = new CategorizedProblem[problemCount];
+                                       System.arraycopy(unit.compilationResult.problems, 0, unitDeclaration.compilationResult.problems, 0, problemCount);
+                                       unitDeclaration.compilationResult.problemCount = problemCount;
+                               }
+                               return unitDeclaration;
+                       }
+                       if (NameLookup.VERBOSE) {
+                               System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
+                               System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
+                       }
+                       return unit;
+               } finally {
+                       if (environment != null) {
+                               environment.monitor = null; // don't hold a reference to this external object
+                       }
+                       if (problemFactory != null) {
+                               problemFactory.monitor = null; // don't hold a reference to this external object
+                       }
+                       // first unit cleanup is done by caller, but cleanup all enqueued requested units (not processed)
+//                     if (resolver != null) {
+//                             for (int i = 1; i <  resolver.totalUnits; i++) { // could be more requested units
+//                                     CompilationUnitDeclaration parsedUnit = resolver.unitsToProcess[i];
+//                                     if (parsedUnit.scope != null)
+//                                             parsedUnit.scope.faultInTypes(); // force resolution of signatures, so clients can query DOM AST
+//                                     parsedUnit.cleanUp();
+//                             }
+//                     }
+               }
+       }
+       public static IBinding[] resolve(
+               final IJavaElement[] elements,
+               int apiLevel,
+               Map compilerOptions,
+               IJavaProject javaProject,
+               WorkingCopyOwner owner,
+               int flags,
+               IProgressMonitor monitor) {
+
+               final int length = elements.length;
+               final HashMap sourceElementPositions = new HashMap(); // a map from ICompilationUnit to int[] (positions in elements)
+               int cuNumber = 0;
+               final HashtableOfObjectToInt binaryElementPositions = new HashtableOfObjectToInt(); // a map from String (binding key) to int (position in elements)
+               for (int i = 0; i < length; i++) {
+                       IJavaElement element = elements[i];
+                       if (!(element instanceof SourceRefElement))
+                               throw new IllegalStateException(element + " is not part of a compilation unit or class file"); //$NON-NLS-1$
+                       Object cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
+                       if (cu != null) {
+                               // source member
+                               IntArrayList intList = (IntArrayList) sourceElementPositions.get(cu);
+                               if (intList == null) {
+                                       sourceElementPositions.put(cu, intList = new IntArrayList());
+                                       cuNumber++;
+                               }
+                               intList.add(i);
+                       } else {
+                               // binary member
+                               try {
+                                       String key = ((BinaryMember) element).getKey(true/*open to get resolved info*/);
+                                       binaryElementPositions.put(key, i);
+                               } catch (JavaModelException e) {
+                                       throw new IllegalArgumentException(element + " does not exist"); //$NON-NLS-1$
+                               }
+                       }
+               }
+               ICompilationUnit[] cus = new ICompilationUnit[cuNumber];
+               sourceElementPositions.keySet().toArray(cus);
+
+               int bindingKeyNumber = binaryElementPositions.size();
+               String[] bindingKeys = new String[bindingKeyNumber];
+               binaryElementPositions.keysToArray(bindingKeys);
+
+               class Requestor extends ASTRequestor {
+                       IBinding[] bindings = new IBinding[length];
+                       public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
+                               // TODO (jerome) optimize to visit the AST only once
+                               IntArrayList intList = (IntArrayList) sourceElementPositions.get(source);
+                               for (int i = 0; i < intList.length; i++) {
+                                       final int index = intList.list[i];
+                                       SourceRefElement element = (SourceRefElement) elements[index];
+                                       DOMFinder finder = new DOMFinder(ast, element, true/*resolve binding*/);
+                                       try {
+                                               finder.search();
+                                       } catch (JavaModelException e) {
+                                               throw new IllegalArgumentException(element + " does not exist"); //$NON-NLS-1$
+                                       }
+                                       this.bindings[index] = finder.foundBinding;
+                               }
+                       }
+                       public void acceptBinding(String bindingKey, IBinding binding) {
+                               int index = binaryElementPositions.get(bindingKey);
+                               this.bindings[index] = binding;
+                       }
+               }
+               Requestor requestor = new Requestor();
+               resolve(cus, bindingKeys, requestor, apiLevel, compilerOptions, javaProject, owner, flags, monitor);
+               return requestor.bindings;
+       }
+       /*
+        * When unit result is about to be accepted, removed back pointers
+        * to unresolved bindings
+        */
+       public void removeUnresolvedBindings(CompilationUnitDeclaration compilationUnitDeclaration) {
+               final org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+               if (types != null) {
+                       for (int i = 0, max = types.length; i < max; i++) {
+                               removeUnresolvedBindings(types[i]);
+                       }
+               }
+       }
+       private void removeUnresolvedBindings(net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration type) {
+               final net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration[] memberTypes = type.memberTypes;
+               if (memberTypes != null) {
+                       for (int i = 0, max = memberTypes.length; i < max; i++){
+                               removeUnresolvedBindings(memberTypes[i]);
+                       }
+               }
+               if (type.binding != null && (type.binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
+                       type.binding = null;
+               }
+
+               final org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = type.fields;
+               if (fields != null) {
+                       for (int i = 0, max = fields.length; i < max; i++){
+                               if (fields[i].binding != null && (fields[i].binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
+                                       fields[i].binding = null;
+                               }
+                       }
+               }
+
+               final AbstractMethodDeclaration[] methods = type.methods;
+               if (methods != null) {
+                       for (int i = 0, max = methods.length; i < max; i++){
+                               if (methods[i].binding !=  null && (methods[i].binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
+                                       methods[i].binding = null;
+                               }
+                       }
+               }
+       }
+
+       private void resolve(ICompilationUnit[] compilationUnits, String[] bindingKeys, ASTRequestor astRequestor, int apiLevel, Map compilerOptions, WorkingCopyOwner owner, int flags) {
+
+               // temporarily connect ourselves to the ASTResolver - must disconnect when done
+               astRequestor.compilationUnitResolver = this;
+               this.bindingTables = new DefaultBindingResolver.BindingTables();
+               CompilationUnitDeclaration unit = null;
+               int i = 0;
+               try {
+                       int length = compilationUnits.length;
+                       org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[length];
+                       System.arraycopy(compilationUnits, 0, sourceUnits, 0, length);
+                       beginToCompile(sourceUnits, bindingKeys);
+                       // process all units (some more could be injected in the loop by the lookup environment)
+                       for (; i < this.totalUnits; i++) {
+                               if (this.requestedSources.size() == 0 && this.requestedKeys.size() == 0) {
+                                       // no need to keep resolving if no more ASTs and no more binding keys are needed
+                                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=114935
+                                       // cleanup remaining units
+                                       for (; i < this.totalUnits; i++) {
+                                               this.unitsToProcess[i].cleanUp();
+                                               this.unitsToProcess[i] = null;
+                                       }
+                                       break;
+                               }
+                               unit = this.unitsToProcess[i];
+                               try {
+                                       super.process(unit, i); // this.process(...) is optimized to not process already known units
+
+                                       // requested AST
+                                       char[] fileName = unit.compilationResult.getFileName();
+                                       ICompilationUnit source = (ICompilationUnit) this.requestedSources.get(fileName);
+                                       if (source != null) {
+                                               // convert AST
+                                               CompilationResult compilationResult = unit.compilationResult;
+                                               org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationResult.compilationUnit;
+                                               char[] contents = sourceUnit.getContents();
+                                               AST ast = AST.newAST(apiLevel);
+                                               ast.setFlag(flags | AST.RESOLVED_BINDINGS);
+                                               ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+                                               ASTConverter converter = new ASTConverter(compilerOptions, true/*need to resolve bindings*/, this.monitor);
+                                               BindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0);
+                                               ast.setBindingResolver(resolver);
+                                               converter.setAST(ast);
+                                               CompilationUnit compilationUnit = converter.convert(unit, contents);
+                                               compilationUnit.setTypeRoot(source);
+                                               compilationUnit.setLineEndTable(compilationResult.getLineSeparatorPositions());
+                                               ast.setDefaultNodeFlag(0);
+                                               ast.setOriginalModificationCount(ast.modificationCount());
+
+                                               // pass it to requestor
+                                               astRequestor.acceptAST(source, compilationUnit);
+
+                                               worked(1);
+                                       }
+
+                                       // requested binding
+                                       Object key = this.requestedKeys.get(fileName);
+                                       if (key instanceof BindingKeyResolver) {
+                                               reportBinding(key, astRequestor, owner, unit);
+                                               worked(1);
+                                       } else if (key instanceof ArrayList) {
+                                               Iterator iterator = ((ArrayList) key).iterator();
+                                               while (iterator.hasNext()) {
+                                                       reportBinding(iterator.next(), astRequestor, owner, unit);
+                                                       worked(1);
+                                               }
+                                       }
+
+                                       // remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
+                                       this.requestedSources.removeKey(fileName);
+                                       this.requestedKeys.removeKey(fileName);
+                               } finally {
+                                       // cleanup compilation unit result
+                                       unit.cleanUp();
+                               }
+                               this.unitsToProcess[i] = null; // release reference to processed unit declaration
+                               this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+                       }
+
+                       // remaining binding keys
+                       DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, owner, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0);
+                       Object[] keys = this.requestedKeys.valueTable;
+                       for (int j = 0, keysLength = keys.length; j < keysLength; j++) {
+                               BindingKeyResolver keyResolver = (BindingKeyResolver) keys[j];
+                               if (keyResolver == null) continue;
+                               Binding compilerBinding = keyResolver.getCompilerBinding();
+                               IBinding binding = compilerBinding == null ? null : resolver.getBinding(compilerBinding);
+                               // pass it to requestor
+                               astRequestor.acceptBinding(((BindingKeyResolver) this.requestedKeys.valueTable[j]).getKey(), binding);
+                               worked(1);
+                       }
+               } catch (OperationCanceledException e) {
+                       throw e;
+               } catch (AbortCompilation e) {
+                       this.handleInternalException(e, unit);
+               } catch (Error e) {
+                       this.handleInternalException(e, unit, null);
+                       throw e; // rethrow
+               } catch (RuntimeException e) {
+                       this.handleInternalException(e, unit, null);
+                       throw e; // rethrow
+               } finally {
+                       // disconnect ourselves from ast requestor
+                       astRequestor.compilationUnitResolver = null;
+               }
+       }
+
+       private void reportBinding(Object key, ASTRequestor astRequestor, WorkingCopyOwner owner, CompilationUnitDeclaration unit) {
+               BindingKeyResolver keyResolver = (BindingKeyResolver) key;
+               Binding compilerBinding = keyResolver.getCompilerBinding();
+               if (compilerBinding != null) {
+                       DefaultBindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables, false);
+                       AnnotationBinding annotationBinding = keyResolver.getAnnotationBinding();
+                       IBinding binding;
+                       if (annotationBinding != null) {
+                               binding = resolver.getAnnotationInstance(annotationBinding);
+                       } else {
+                               binding = resolver.getBinding(compilerBinding);
+                       }
+                       if (binding != null)
+                               astRequestor.acceptBinding(keyResolver.getKey(), binding);
+               }
+       }
+
+       private CompilationUnitDeclaration resolve(
+                       CompilationUnitDeclaration unit,
+                       org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
+                       NodeSearcher nodeSearcher,
+                       boolean verifyMethods,
+                       boolean analyzeCode,
+                       boolean generateCode) {
+
+               try {
+
+                       if (unit == null) {
+                               // build and record parsed units
+                               this.parseThreshold = 0; // will request a full parse
+                               beginToCompile(new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] { sourceUnit });
+                               // process all units (some more could be injected in the loop by the lookup environment)
+                               unit = this.unitsToProcess[0];
+                       } else {
+                               // initial type binding creation
+                               this.lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);
+
+                               // binding resolution
+                               this.lookupEnvironment.completeTypeBindings();
+                       }
+
+                       if (nodeSearcher == null) {
+                               this.parser.getMethodBodies(unit); // no-op if method bodies have already been parsed
+                       } else {
+                               int searchPosition = nodeSearcher.position;
+                               char[] source = sourceUnit.getContents();
+                               int length = source.length;
+                               if (searchPosition >= 0 && searchPosition <= length) {
+                                       unit.traverse(nodeSearcher, unit.scope);
+
+                                       org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
+
+                                       if (node != null) {
+                                               // save existing values to restore them at the end of the parsing process
+                                               // see bug 47079 for more details
+                                               int[] oldLineEnds = this.parser.scanner.lineEnds;
+                                               int oldLinePtr = this.parser.scanner.linePtr;
+
+                                               this.parser.scanner.setSource(source, unit.compilationResult);
+
+                                               org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
+                                               if (node instanceof AbstractMethodDeclaration) {
+                                                       ((AbstractMethodDeclaration)node).parseStatements(this.parser, unit);
+                                               } else if (enclosingTypeDeclaration != null) {
+                                                       if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
+                                                               ((org.eclipse.jdt.internal.compiler.ast.Initializer) node).parseStatements(this.parser, enclosingTypeDeclaration, unit);
+                                                       } else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+                                                               ((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)node).parseMethods(this.parser, unit);
+                                                       }
+                                               }
+                                               // this is done to prevent any side effects on the compilation unit result
+                                               // line separator positions array.
+                                               this.parser.scanner.lineEnds = oldLineEnds;
+                                               this.parser.scanner.linePtr = oldLinePtr;
+                                       }
+                               }
+                       }
+
+                       if (unit.scope != null) {
+                               // fault in fields & methods
+                               unit.scope.faultInTypes();
+                               if (unit.scope != null && verifyMethods) {
+                                       // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
+                                       // verify inherited methods
+                                       unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier());
+                               }
+                               // type checking
+                               unit.resolve();
+
+                               // flow analysis
+                               if (analyzeCode) unit.analyseCode();
+
+                               // code generation
+                               if (generateCode) unit.generateCode();
+                               
+                               // finalize problems (suppressWarnings)
+                               unit.finalizeProblems();
+                       }
+                       if (this.unitsToProcess != null) this.unitsToProcess[0] = null; // release reference to processed unit declaration
+                       this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+                       return unit;
+               } catch (AbortCompilation e) {
+                       this.handleInternalException(e, unit);
+                       return unit == null ? this.unitsToProcess[0] : unit;
+               } catch (Error e) {
+                       this.handleInternalException(e, unit, null);
+                       throw e; // rethrow
+               } catch (RuntimeException e) {
+                       this.handleInternalException(e, unit, null);
+                       throw e; // rethrow
+               } finally {
+                       // No reset is performed there anymore since,
+                       // within the CodeAssist (or related tools),
+                       // the compiler may be called *after* a call
+                       // to this resolve(...) method. And such a call
+                       // needs to have a compiler with a non-empty
+                       // environment.
+                       // this.reset();
+               }
+       }
+       /*
+        * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+        */
+       public CompilationUnitDeclaration resolve(
+                       org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
+                       boolean verifyMethods,
+                       boolean analyzeCode,
+                       boolean generateCode) {
+
+               return resolve(
+                       null, /* no existing compilation unit declaration*/
+                       sourceUnit,
+                       null/*no node searcher*/,
+                       verifyMethods,
+                       analyzeCode,
+                       generateCode);
+       }
+
+       /*
+        * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+        */
+       public CompilationUnitDeclaration resolve(
+                       CompilationUnitDeclaration unit,
+                       org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
+                       boolean verifyMethods,
+                       boolean analyzeCode,
+                       boolean generateCode) {
+
+               return resolve(
+                       unit,
+                       sourceUnit,
+                       null/*no node searcher*/,
+                       verifyMethods,
+                       analyzeCode,
+                       generateCode);
+       }
+
+       private void worked(int work) {
+               if (this.monitor != null) {
+                       if (this.monitor.isCanceled())
+                               throw new OperationCanceledException();
+                       this.monitor.worked(work);
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ConditionalExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ConditionalExpression.java
new file mode 100644 (file)
index 0000000..d207b62
--- /dev/null
@@ -0,0 +1,334 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Conditional expression AST node type.
+ *
+ * <pre>
+ * ConditionalExpression:
+ *    Expression <b>?</b> Expression <b>:</b> Expression
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ConditionalExpression extends Expression {
+       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(ConditionalExpression.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "thenExpression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor THEN_EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(ConditionalExpression.class, "thenExpression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "elseExpression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor ELSE_EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(ConditionalExpression.class, "elseExpression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(4);
+               createPropertyList(ConditionalExpression.class, properyList);
+               addProperty(EXPRESSION_PROPERTY, properyList);
+               addProperty(THEN_EXPRESSION_PROPERTY, properyList);
+               addProperty(ELSE_EXPRESSION_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 condition expression; lazily initialized; defaults to an unspecified,
+        * but legal, expression.
+        */
+       private Expression conditionExpression = null;
+
+       /**
+        * The "then" expression; lazily initialized; defaults to an unspecified,
+        * but legal, expression.
+        */
+       private Expression thenExpression = null;
+
+       /**
+        * The "else" expression; lazily initialized; defaults to an unspecified,
+        * but legal, expression.
+        */
+       private Expression elseExpression = null;
+
+       /**
+        * Creates a new unparented conditional expression node owned by the given 
+        * AST. By default, the condition, "then", and "else" expresssions are
+        * unspecified, but legal.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ConditionalExpression(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == THEN_EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getThenExpression();
+                       } else {
+                               setThenExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == ELSE_EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getElseExpression();
+                       } else {
+                               setElseExpression((Expression) 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.
+        */
+       final int getNodeType0() {
+               return CONDITIONAL_EXPRESSION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ConditionalExpression result = new ConditionalExpression(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setExpression((Expression) getExpression().clone(target));
+               result.setThenExpression(
+                       (Expression) getThenExpression().clone(target));
+               result.setElseExpression(
+                       (Expression) getElseExpression().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getExpression());
+                       acceptChild(visitor, getThenExpression());
+                       acceptChild(visitor, getElseExpression());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the condition of this conditional expression.
+        * 
+        * @return the condition node
+        */ 
+       public Expression getExpression() {
+               if (this.conditionExpression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.conditionExpression == null) {
+                                       preLazyInit();
+                                       this.conditionExpression = new SimpleName(this.ast);
+                                       postLazyInit(this.conditionExpression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.conditionExpression;
+       }
+       
+       /**
+        * Sets the condition of this conditional expression.
+        * 
+        * @param expression the condition node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.conditionExpression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.conditionExpression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+       
+       /**
+        * Returns the "then" part of this conditional expression.
+        * 
+        * @return the "then" expression node
+        */ 
+       public Expression getThenExpression() {
+               if (this.thenExpression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.thenExpression == null) {
+                                       preLazyInit();
+                                       this.thenExpression = new SimpleName(this.ast);
+                                       postLazyInit(this.thenExpression, THEN_EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.thenExpression;
+       }
+       
+       /**
+        * Sets the "then" part of this conditional expression.
+        * 
+        * @param expression the "then" expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setThenExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.thenExpression;
+               preReplaceChild(oldChild, expression, THEN_EXPRESSION_PROPERTY);
+               this.thenExpression = expression;
+               postReplaceChild(oldChild, expression, THEN_EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the "else" part of this conditional expression.
+        * 
+        * @return the "else" expression node
+        */ 
+       public Expression getElseExpression() {
+               if (this.elseExpression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.elseExpression == null) {
+                                       preLazyInit();
+                                       this.elseExpression = new SimpleName(this.ast);
+                                       postLazyInit(this.elseExpression, ELSE_EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.elseExpression;
+       }
+       
+       /**
+        * Sets the "else" part of this conditional expression.
+        * 
+        * @param expression the "else" expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setElseExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.elseExpression;
+               preReplaceChild(oldChild, expression, ELSE_EXPRESSION_PROPERTY);
+               this.elseExpression = expression;
+               postReplaceChild(oldChild, expression, ELSE_EXPRESSION_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.conditionExpression == null ? 0 : getExpression().treeSize())
+                       + (this.thenExpression == null ? 0 : getThenExpression().treeSize())
+                       + (this.elseExpression == null ? 0 : getElseExpression().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ConstructorInvocation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ConstructorInvocation.java
new file mode 100644 (file)
index 0000000..716043b
--- /dev/null
@@ -0,0 +1,252 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Alternate constructor invocation statement AST node type.
+ * For JLS2:
+ * <pre>
+ * ConstructorInvocation:
+ *             <b>this</b> <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b> <b>;</b>
+ * </pre>
+ * For JLS3, type arguments are added:
+ * <pre>
+ * ConstructorInvocation:
+ *      [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ *                   <b>this</b> <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b> <b>;</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ConstructorInvocation extends Statement {
+       
+       /**
+        * The "typeArguments" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(ConstructorInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "arguments" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(ConstructorInvocation.class, "arguments", Expression.class, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List properyList = new ArrayList(2);
+               createPropertyList(ConstructorInvocation.class, properyList);
+               addProperty(ARGUMENTS_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+               
+               properyList = new ArrayList(3);
+               createPropertyList(ConstructorInvocation.class, properyList);
+               addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+               addProperty(ARGUMENTS_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_3_0 = 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The type arguments (element type: <code>Type</code>). 
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * @since 3.1
+        */
+       private ASTNode.NodeList typeArguments = null;
+
+       /**
+        * The list of argument expressions (element type: 
+        * <code>Expression</code>). Defaults to an empty list.
+        */
+       private ASTNode.NodeList arguments =
+               new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+       /**
+        * Creates a new AST node for an alternate constructor invocation statement
+        * owned by the given AST. By default, an empty list of arguments.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ConstructorInvocation(AST ast) {
+               super(ast);     
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+               }
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == ARGUMENTS_PROPERTY) {
+                       return arguments();
+               }
+               if (property == TYPE_ARGUMENTS_PROPERTY) {
+                       return typeArguments();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return CONSTRUCTOR_INVOCATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ConstructorInvocation result = new ConstructorInvocation(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+               }
+               result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChildren(visitor, this.typeArguments);
+                       }
+                       acceptChildren(visitor, this.arguments);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the live ordered list of type arguments of this constructor
+        * invocation (added in JLS3 API).
+        * 
+        * @return the live list of type arguments
+        *    (element type: <code>Type</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public List typeArguments() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.typeArguments == null) {
+                       unsupportedIn2();
+               }
+               return this.typeArguments;
+       }
+       
+       /**
+        * Returns the live ordered list of argument expressions in this alternate
+        * constructor invocation statement.
+        * 
+        * @return the live list of argument expressions 
+        *    (element type: <code>Expression</code>)
+        */ 
+       public List arguments() {
+               return this.arguments;
+       }
+
+       /**
+        * Resolves and returns the binding for the constructor invoked by this
+        * expression.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the constructor binding, or <code>null</code> if the binding
+        *    cannot be resolved
+        */     
+       public IMethodBinding resolveConstructorBinding() {
+               return this.ast.getBindingResolver().resolveConstructor(this);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+                       + (this.arguments == null ? 0 : this.arguments.listSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ContinueStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ContinueStatement.java
new file mode 100644 (file)
index 0000000..1cd6862
--- /dev/null
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Continue statement AST node type.
+ *
+ * <pre>
+ * ContinueStatement:
+ *    <b>continue</b> [ Identifier ] <b>;</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ContinueStatement extends Statement {
+                       
+       /**
+        * The "label" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor LABEL_PROPERTY = 
+               new ChildPropertyDescriptor(ContinueStatement.class, "label", SimpleName.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(2);
+               createPropertyList(ContinueStatement.class, properyList);
+               addProperty(LABEL_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 label, or <code>null</code> if none; none by default.
+        */
+       private SimpleName optionalLabel = null;
+
+       /**
+        * Creates a new unparented continue statement node owned by the given 
+        * AST. By default, the continue statement has no label.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ContinueStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == LABEL_PROPERTY) {
+                       if (get) {
+                               return getLabel();
+                       } else {
+                               setLabel((SimpleName) 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.
+        */
+       final int getNodeType0() {
+               return CONTINUE_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ContinueStatement result = new ContinueStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setLabel((SimpleName) ASTNode.copySubtree(target, getLabel()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getLabel());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the label of this continue statement, or <code>null</code> if
+        * there is none.
+        * 
+        * @return the label, or <code>null</code> if there is none
+        */ 
+       public SimpleName getLabel() {
+               return this.optionalLabel;
+       }
+       
+       /**
+        * Sets or clears the label of this continue statement.
+        * 
+        * @param label the label, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setLabel(SimpleName label) {
+               ASTNode oldChild = this.optionalLabel;
+               preReplaceChild(oldChild, label, LABEL_PROPERTY);
+               this.optionalLabel = label;
+               postReplaceChild(oldChild, label, LABEL_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (optionalLabel == null ? 0 : getLabel().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultASTVisitor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultASTVisitor.java
new file mode 100644 (file)
index 0000000..4d2823e
--- /dev/null
@@ -0,0 +1,562 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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 net.sourceforge.phpdt.core.dom;
+/**
+ */
+class DefaultASTVisitor extends ASTVisitor {
+       /**
+        * 
+        */
+       public DefaultASTVisitor() {
+               super();
+       }
+       
+       /**
+        * 
+        */
+       public DefaultASTVisitor(boolean visitDocTags) {
+               super(visitDocTags);
+       }
+       
+       public void endVisit(AnnotationTypeDeclaration node) {
+               endVisitNode(node);
+       }
+       
+       public void endVisit(AnnotationTypeMemberDeclaration node) {
+               endVisitNode(node);
+       }
+
+       public void endVisit(AnonymousClassDeclaration node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ArrayAccess node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ArrayCreation node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ArrayInitializer node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ArrayType node) {
+               endVisitNode(node);
+       }
+       public void endVisit(AssertStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(Assignment node) {
+               endVisitNode(node);
+       }
+       public void endVisit(Block node) {
+               endVisitNode(node);
+       }
+       /* since 3.0 */
+       public void endVisit(BlockComment node) {
+               endVisitNode(node);
+       }
+       public void endVisit(BooleanLiteral node) {
+               endVisitNode(node);
+       }
+       public void endVisit(BreakStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(CastExpression node) {
+               endVisitNode(node);
+       }
+       public void endVisit(CatchClause node) {
+               endVisitNode(node);
+       }
+       public void endVisit(CharacterLiteral node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ClassInstanceCreation node) {
+               endVisitNode(node);
+       }
+       public void endVisit(CompilationUnit node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ConditionalExpression node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ConstructorInvocation node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ContinueStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(DoStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(EmptyStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(EnhancedForStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(EnumConstantDeclaration node) {
+               endVisitNode(node);
+       }
+       public void endVisit(EnumDeclaration node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ExpressionStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(FieldAccess node) {
+               endVisitNode(node);
+       }
+       public void endVisit(FieldDeclaration node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ForStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(IfStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ImportDeclaration node) {
+               endVisitNode(node);
+       }
+       public void endVisit(InfixExpression node) {
+               endVisitNode(node);
+       }
+       public void endVisit(Initializer node) {
+               endVisitNode(node);
+       }
+       public void endVisit(InstanceofExpression node) {
+               endVisitNode(node);
+       }
+       public void endVisit(Javadoc node) {
+               endVisitNode(node);
+       }
+       public void endVisit(LabeledStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(LineComment node) {
+               endVisitNode(node);
+       }
+       public void endVisit(MarkerAnnotation node) {
+               endVisitNode(node);
+       }
+       public void endVisit(MemberRef node) {
+               endVisitNode(node);
+       }
+       public void endVisit(MemberValuePair node) {
+               endVisitNode(node);
+       }
+       public void endVisit(MethodDeclaration node) {
+               endVisitNode(node);
+       }
+       public void endVisit(MethodInvocation node) {
+               endVisitNode(node);
+       }
+       public void endVisit(MethodRef node) {
+               endVisitNode(node);
+       }
+       public void endVisit(MethodRefParameter node) {
+               endVisitNode(node);
+       }
+       public void endVisit(NormalAnnotation node) {
+               endVisitNode(node);
+       }
+       public void endVisit(NullLiteral node) {
+               endVisitNode(node);
+       }
+       public void endVisit(NumberLiteral node) {
+               endVisitNode(node);
+       }
+       public void endVisit(PackageDeclaration node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ParameterizedType node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ParenthesizedExpression node) {
+               endVisitNode(node);
+       }
+       public void endVisit(PostfixExpression node) {
+               endVisitNode(node);
+       }
+       public void endVisit(PrefixExpression node) {
+               endVisitNode(node);
+       }
+       public void endVisit(PrimitiveType node) {
+               endVisitNode(node);
+       }
+       public void endVisit(QualifiedName node) {
+               endVisitNode(node);
+       }
+       public void endVisit(QualifiedType node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ReturnStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(SimpleName node) {
+               endVisitNode(node);
+       }
+       public void endVisit(SimpleType node) {
+               endVisitNode(node);
+       }
+       public void endVisit(SingleMemberAnnotation node) {
+               endVisitNode(node);
+       }
+       public void endVisit(SingleVariableDeclaration node) {
+               endVisitNode(node);
+       }
+       public void endVisit(StringLiteral node) {
+               endVisitNode(node);
+       }
+       public void endVisit(SuperConstructorInvocation node) {
+               endVisitNode(node);
+       }
+       public void endVisit(SuperFieldAccess node) {
+               endVisitNode(node);
+       }
+       public void endVisit(SuperMethodInvocation node) {
+               endVisitNode(node);
+       }
+
+       public void endVisit(SwitchCase node) {
+               endVisitNode(node);
+       }
+       public void endVisit(SwitchStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(SynchronizedStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(TagElement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(TextElement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ThisExpression node) {
+               endVisitNode(node);
+       }
+       public void endVisit(ThrowStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(TryStatement node) {
+               endVisitNode(node);
+       }
+
+       public void endVisit(TypeDeclaration node) {
+               endVisitNode(node);
+       }
+       public void endVisit(TypeDeclarationStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(TypeLiteral node) {
+               endVisitNode(node);
+       }
+       public void endVisit(TypeParameter node) {
+               endVisitNode(node);
+       }
+       public void endVisit(VariableDeclarationExpression node) {
+               endVisitNode(node);
+       }
+       public void endVisit(VariableDeclarationFragment node) {
+               endVisitNode(node);
+       }
+       public void endVisit(VariableDeclarationStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(WhileStatement node) {
+               endVisitNode(node);
+       }
+       public void endVisit(WildcardType node) {
+               endVisitNode(node);
+       }
+       protected void endVisitNode(ASTNode node) {
+               // do nothing
+       }
+       public boolean visit(AnnotationTypeDeclaration node) {
+               return visitNode(node);
+       }
+       public boolean visit(AnnotationTypeMemberDeclaration node) {
+               return visitNode(node);
+       }
+       public boolean visit(AnonymousClassDeclaration node) {
+               return visitNode(node);
+       }
+       public boolean visit(ArrayAccess node) {
+               return visitNode(node);
+       }
+       public boolean visit(ArrayCreation node) {
+               return visitNode(node);
+       }
+       public boolean visit(ArrayInitializer node) {
+               return visitNode(node);
+       }
+       public boolean visit(ArrayType node) {
+               visitNode(node);
+               return false;
+       }
+       public boolean visit(AssertStatement node) {
+               return visitNode(node);
+       }
+       public boolean visit(Assignment node) {
+               return visitNode(node);
+       }
+       public boolean visit(Block node) {
+               return visitNode(node);
+       }
+       /* since 3.0 */
+       public boolean visit(BlockComment node) {
+               return visitNode(node);
+       }
+       public boolean visit(BooleanLiteral node) {
+               return visitNode(node);
+       }
+       public boolean visit(BreakStatement node) {
+               return visitNode(node);
+       }
+       public boolean visit(CastExpression node) {
+               return visitNode(node);
+       }
+       public boolean visit(CatchClause node) {
+               return visitNode(node);
+       }
+       public boolean visit(CharacterLiteral node) {
+               return visitNode(node);
+       }
+       public boolean visit(ClassInstanceCreation node) {
+               return visitNode(node);
+       }
+       public boolean visit(CompilationUnit node) {
+               return visitNode(node);
+       }
+       public boolean visit(ConditionalExpression node) {
+               return visitNode(node);
+       }
+       public boolean visit(ConstructorInvocation node) {
+               return visitNode(node);
+       }
+       public boolean visit(ContinueStatement node) {
+               return visitNode(node);
+       }
+       public boolean visit(DoStatement node) {
+               return visitNode(node);
+       }
+       public boolean visit(EmptyStatement node) {
+               return visitNode(node);
+       }
+       public boolean visit(EnhancedForStatement node) {
+               return visitNode(node);
+       }
+       public boolean visit(EnumConstantDeclaration node) {
+               return visitNode(node);
+       }
+       public boolean visit(EnumDeclaration node) {
+               return visitNode(node);
+       }
+       public boolean visit(ExpressionStatement node) {
+               return visitNode(node);
+       }
+       public boolean visit(FieldAccess node) {
+               return visitNode(node);
+       }
+       public boolean visit(FieldDeclaration node) {
+               return visitNode(node);
+       }
+       public boolean visit(ForStatement node) {
+               return visitNode(node);
+       }
+       public boolean visit(IfStatement node) {
+               return visitNode(node);
+       }
+       public boolean visit(ImportDeclaration node) {
+               return visitNode(node);
+       }
+       public boolean visit(InfixExpression node) {
+               return visitNode(node);
+       }
+       public boolean visit(Initializer node) {
+               return visitNode(node);
+       }
+       public boolean visit(InstanceofExpression node) {
+               return visitNode(node);
+       }
+       public boolean visit(Javadoc node) {
+               //      do not visit Javadoc tags by default. Use constructor with boolean to enable.
+               if (super.visit(node)) { 
+                       return visitNode(node);
+               }
+               return false;
+       }
+       public boolean visit(LabeledStatement node) {
+               return visitNode(node);
+       }
+       public boolean visit(LineComment node) {
+               return visitNode(node);
+       }
+       public boolean visit(MarkerAnnotation node) {
+               return visitNode(node);
+       }
+       public boolean visit(MemberRef node) {
+               return visitNode(node);
+       }
+       public boolean visit(MemberValuePair node) {
+               return visitNode(node);
+       }
+       public boolean visit(MethodDeclaration node) {
+               return visitNode(node);
+       }
+       public boolean visit(MethodInvocation node) {
+               return visitNode(node);
+       }
+       public boolean visit(MethodRef node) {
+               return visitNode(node);
+       }
+       public boolean visit(MethodRefParameter node) {
+               return visitNode(node);
+       }
+       public boolean visit(NormalAnnotation node) {
+               return visitNode(node);
+       }
+       public boolean visit(NullLiteral node) {
+               return visitNode(node);
+       }
+       public boolean visit(NumberLiteral node) {
+               return visitNode(node);
+       }
+       public boolean visit(PackageDeclaration node) {
+               return visitNode(node);
+       }
+       public boolean visit(ParameterizedType node) {
+               return visitNode(node);
+       }
+       public boolean visit(ParenthesizedExpression node) {
+               return visitNode(node);
+       }
+       public boolean visit(PostfixExpression node) {
+               return visitNode(node);
+       }
+       public boolean visit(PrefixExpression node) {
+               return visitNode(node);
+       }
+       
+       public boolean visit(PrimitiveType node) {
+               return visitNode(node);
+       }
+       public boolean visit(QualifiedName node) {
+               return visitNode(node);
+       }
+       public boolean visit(QualifiedType node) {
+               return visitNode(node);
+       }
+       public boolean visit(ReturnStatement node) {
+               return visitNode(node);
+       }
+       public boolean visit(SimpleName node) {
+               return visitNode(node);
+       }
+       public boolean visit(SimpleType node) {
+               return visitNode(node);
+       }
+       public boolean visit(SingleMemberAnnotation node) {
+               return visitNode(node);
+       }
+       public boolean visit(SingleVariableDeclaration node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(StringLiteral node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(SuperConstructorInvocation node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(SuperFieldAccess node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(SuperMethodInvocation node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(SwitchCase node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(SwitchStatement node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(SynchronizedStatement node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(TagElement node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(TextElement node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(ThisExpression node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(ThrowStatement node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(TryStatement node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(TypeDeclaration node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(TypeDeclarationStatement node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(TypeLiteral node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(TypeParameter node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(VariableDeclarationExpression node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(VariableDeclarationFragment node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(VariableDeclarationStatement node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(WhileStatement node) {
+               return visitNode(node);
+       }
+
+       public boolean visit(WildcardType node) {
+               return visitNode(node);
+       }
+
+       protected boolean visitNode(ASTNode node) {
+               return true;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultBindingResolver.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultBindingResolver.java
new file mode 100644 (file)
index 0000000..bfc9a09
--- /dev/null
@@ -0,0 +1,1818 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.phpdt.core.WorkingCopyOwner;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractVariableDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.AllocationExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.ArrayAllocationExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldReference;
+import net.sourceforge.phpdt.internal.compiler.ast.JavadocImplicitTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+import net.sourceforge.phpdt.internal.compiler.ast.JavadocAllocationExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.JavadocFieldReference;
+import net.sourceforge.phpdt.internal.compiler.ast.JavadocMessageSend;
+import net.sourceforge.phpdt.internal.compiler.ast.JavadocQualifiedTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.JavadocSingleNameReference;
+import net.sourceforge.phpdt.internal.compiler.ast.JavadocSingleTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.Literal;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair;
+import net.sourceforge.phpdt.internal.compiler.ast.MessageSend;
+import net.sourceforge.phpdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedNameReference;
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedSuperReference;
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.SingleNameReference;
+import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.ThisReference;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.CompilationUnitScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ElementValuePair;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.LookupEnvironment;
+import net.sourceforge.phpdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemFieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReasons;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TagBits;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.core.util.Util;
+
+/**
+ * Internal class for resolving bindings using old ASTs.
+ * <p>
+ * IMPORTANT: The methods on this class are synchronized. This is required
+ * because there may be multiple clients in separate threads concurrently
+ * reading an AST and asking for bindings for its nodes. These requests all
+ * end up invoking instance methods on this class. There are various internal
+ * tables and caches which are built and maintained in the course of looking
+ * up bindings. To ensure that they remain coherent in the presence of multiple
+ * threads, the methods are synchronized on the DefaultBindingResolver instance.
+ * </p>
+ */
+class DefaultBindingResolver extends BindingResolver {
+
+       /*
+        * Holds on binding tables that can be shared by several ASTs.
+        */
+       static class BindingTables {
+
+               /**
+                * This map is used to get a binding from its binding key.
+                */
+               Map bindingKeysToBindings;
+               /**
+                * This map is used to keep the correspondance between new bindings and the
+                * compiler bindings as well as new annotation instances to their internal counterpart.
+                * This is an identity map. We should only create one object for one binding or annotation.
+                */
+               Map compilerBindingsToASTBindings;
+
+               BindingTables() {
+                       this.compilerBindingsToASTBindings = new HashMap();
+                       this.bindingKeysToBindings = new HashMap();
+               }
+
+       }
+       /**
+        * This map is used to retrieve the corresponding block scope for a ast node
+        */
+       Map astNodesToBlockScope;
+
+       /**
+        * This map is used to get an ast node from its binding (new binding) or DOM
+        */
+       Map bindingsToAstNodes;
+
+       /*
+        * The shared binding tables accros ASTs.
+        */
+       BindingTables bindingTables;
+
+       /**
+        * This map is used to retrieve an old ast node using the new ast node. This is not an
+        * identity map.
+        */
+       Map newAstToOldAst;
+
+       /**
+        * Compilation unit scope
+        */
+       private CompilationUnitScope scope;
+
+       /**
+        * The working copy owner that defines the context in which this resolver is creating the bindings.
+        */
+       WorkingCopyOwner workingCopyOwner;
+
+       /**
+        * Toggle controlling whether DOM bindings should be created when missing internal compiler bindings..
+        */
+       boolean isRecoveringBindings;
+
+       /**
+        * Constructor for DefaultBindingResolver.
+        */
+       DefaultBindingResolver(CompilationUnitScope scope, WorkingCopyOwner workingCopyOwner, BindingTables bindingTables, boolean isRecoveringBindings) {
+               this.newAstToOldAst = new HashMap();
+               this.astNodesToBlockScope = new HashMap();
+               this.bindingsToAstNodes = new HashMap();
+               this.bindingTables = bindingTables;
+               this.scope = scope;
+               this.workingCopyOwner = workingCopyOwner;
+               this.isRecoveringBindings = isRecoveringBindings;
+       }
+
+       DefaultBindingResolver(LookupEnvironment lookupEnvironment, WorkingCopyOwner workingCopyOwner, BindingTables bindingTables, boolean isRecoveringBindings) {
+               this.newAstToOldAst = new HashMap();
+               this.astNodesToBlockScope = new HashMap();
+               this.bindingsToAstNodes = new HashMap();
+               this.bindingTables = bindingTables;
+               this.scope = new CompilationUnitScope(new CompilationUnitDeclaration(null, null, -1), lookupEnvironment);
+               this.workingCopyOwner = workingCopyOwner;
+               this.isRecoveringBindings = isRecoveringBindings;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized ASTNode findDeclaringNode(IBinding binding) {
+               if (binding == null) {
+                       return null;
+               }
+               if (binding instanceof IMethodBinding) {
+                       IMethodBinding methodBinding = (IMethodBinding) binding;
+                       return (ASTNode) this.bindingsToAstNodes.get(methodBinding.getMethodDeclaration());
+               } else if (binding instanceof ITypeBinding) {
+                       ITypeBinding typeBinding = (ITypeBinding) binding;
+                       return (ASTNode) this.bindingsToAstNodes.get(typeBinding.getTypeDeclaration());
+               } else if (binding instanceof IVariableBinding) {
+                       IVariableBinding variableBinding = (IVariableBinding) binding;
+                       return (ASTNode) this.bindingsToAstNodes.get(variableBinding.getVariableDeclaration());
+               }
+               return (ASTNode) this.bindingsToAstNodes.get(binding);
+       }
+
+       synchronized ASTNode findDeclaringNode(String bindingKey) {
+               if (bindingKey == null) {
+                       return null;
+               }
+               Object binding = this.bindingTables.bindingKeysToBindings.get(bindingKey);
+               if (binding == null)
+                       return null;
+               return (ASTNode) this.bindingsToAstNodes.get(binding);
+       }
+
+       IBinding getBinding(net.sourceforge.phpdt.internal.compiler.lookup.Binding binding) {
+               switch (binding.kind()) {
+                       case Binding.PACKAGE:
+                               return getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) binding);
+                       case Binding.TYPE:
+                       case Binding.BASE_TYPE:
+                       case Binding.GENERIC_TYPE:
+                       case Binding.PARAMETERIZED_TYPE:
+                       case Binding.RAW_TYPE:
+                               return getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
+                       case Binding.ARRAY_TYPE:
+                       case Binding.TYPE_PARAMETER:
+                               return new TypeBinding(this, (net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
+                       case Binding.METHOD:
+                               return getMethodBinding((net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding) binding);
+                       case Binding.FIELD:
+                       case Binding.LOCAL:
+                               return getVariableBinding((net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding) binding);
+               }
+               return null;
+       }
+       
+       Util.BindingsToNodesMap getBindingsToNodesMap() {
+               return new Util.BindingsToNodesMap() {
+                       public net.sourceforge.phpdt.internal.compiler.ast.ASTNode get(Binding binding) {
+                               return (net.sourceforge.phpdt.internal.compiler.ast.ASTNode)
+                                       DefaultBindingResolver.this.newAstToOldAst.get(DefaultBindingResolver.this.bindingsToAstNodes.get(binding));
+                       }
+               };
+       }
+
+       synchronized net.sourceforge.phpdt.internal.compiler.ast.ASTNode getCorrespondingNode(ASTNode currentNode) {
+               return (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(currentNode);
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized IMethodBinding getMethodBinding(net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding) {
+               if (methodBinding != null && !methodBinding.isValidBinding()) {
+                       net.sourceforge.phpdt.internal.compiler.lookup.ProblemMethodBinding problemMethodBinding =
+                               (net.sourceforge.phpdt.internal.compiler.lookup.ProblemMethodBinding) methodBinding;
+                       methodBinding = problemMethodBinding.closestMatch;
+               }
+
+               if (methodBinding != null) {
+                       if (!isRecoveringBindings && ((methodBinding.tagBits & TagBits.HasMissingType) != 0)) {
+                               return null;
+                       }
+                       IMethodBinding binding = (IMethodBinding) this.bindingTables.compilerBindingsToASTBindings.get(methodBinding);
+                       if (binding != null) {
+                               return binding;
+                       }
+                       binding = new MethodBinding(this, methodBinding);
+                       this.bindingTables.compilerBindingsToASTBindings.put(methodBinding, binding);
+                       return binding;
+               }
+               return null;
+       }
+
+       synchronized IMemberValuePairBinding getMemberValuePairBinding(ElementValuePair valuePair) {
+               if (valuePair == null || valuePair.binding == null) return null;
+               IMemberValuePairBinding binding =
+                       (IMemberValuePairBinding) this.bindingTables.compilerBindingsToASTBindings.get(valuePair);
+               if (binding != null)
+                       return binding;
+               binding = new MemberValuePairBinding(valuePair, this);
+               this.bindingTables.compilerBindingsToASTBindings.put(valuePair, binding);
+               return binding;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized IPackageBinding getPackageBinding(net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding packageBinding) {
+               if (packageBinding == null) {
+                       return null;
+               }
+               IPackageBinding binding = (IPackageBinding) this.bindingTables.compilerBindingsToASTBindings.get(packageBinding);
+               if (binding != null) {
+                       return binding;
+               }
+               binding = new PackageBinding(packageBinding, this);
+               this.bindingTables.compilerBindingsToASTBindings.put(packageBinding, binding);
+               return binding;
+       }
+       private int getTypeArguments(ParameterizedQualifiedTypeReference typeReference) {
+               TypeReference[][] typeArguments = typeReference.typeArguments;
+               int value = 0;
+               for (int i = 0, max = typeArguments.length; i < max; i++) {
+                       if ((typeArguments[i] != null) || (value != 0)) {
+                               value++;
+                       }
+               }
+               return value;
+       }
+
+       /**
+        * Returns the new type binding corresponding to the given variable declaration.
+        * This is used for recovered binding only.
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param variableDeclaration the given variable declaration
+        * @return the new type binding
+        */
+       synchronized ITypeBinding getTypeBinding(VariableDeclaration variableDeclaration) {
+               ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableDeclaration);
+               if (binding != null) {
+                       return binding;
+               }
+               binding = new RecoveredTypeBinding(this, variableDeclaration);
+               this.bindingTables.compilerBindingsToASTBindings.put(variableDeclaration, binding);
+               return binding;
+       }
+
+       /**
+        * Returns the new type binding corresponding to the given type.
+        * This is used for recovered binding only.
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param type the given type
+        * @return the new type binding
+        */
+       synchronized ITypeBinding getTypeBinding(Type type) {
+               ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(type);
+               if (binding != null) {
+                       return binding;
+               }
+               binding = new RecoveredTypeBinding(this, type);
+               this.bindingTables.compilerBindingsToASTBindings.put(type, binding);
+               return binding;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized ITypeBinding getTypeBinding(net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding referenceBinding) {
+               if (referenceBinding == null) {
+                       return null;
+               } else if (!referenceBinding.isValidBinding()) {
+                       switch(referenceBinding.problemId()) {
+                               case ProblemReasons.NotVisible :
+                               case ProblemReasons.NonStaticReferenceInStaticContext :
+                                       if (referenceBinding instanceof ProblemReferenceBinding) {
+                                               ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) referenceBinding;
+                                               net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding2 = problemReferenceBinding.closestMatch();
+                                               ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(binding2);
+                                               if (binding != null) {
+                                                       return binding;
+                                               }
+                                               binding = new TypeBinding(this, binding2);
+                                               this.bindingTables.compilerBindingsToASTBindings.put(binding2, binding);
+                                               return binding;
+                                       }
+                                       break;
+                               case ProblemReasons.NotFound :
+                                       if (!this.isRecoveringBindings) {
+                                               return null;
+                                       }
+                                       ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(referenceBinding);
+                                       if (binding != null) {
+                                               return binding;
+                                       }
+                                       if ((referenceBinding.tagBits & TagBits.HasMissingType) != 0) {
+                                               binding = new TypeBinding(this, referenceBinding);
+                                       } else {
+                                               binding = new RecoveredTypeBinding(this, referenceBinding);
+                                       }
+                                       this.bindingTables.compilerBindingsToASTBindings.put(referenceBinding, binding);
+                                       return binding;
+                       }
+                       return null;
+               } else {
+                       if ((referenceBinding.tagBits & TagBits.HasMissingType) != 0 && !this.isRecoveringBindings) {
+                               return null;
+                       }
+                       ITypeBinding binding = (ITypeBinding) this.bindingTables.compilerBindingsToASTBindings.get(referenceBinding);
+                       if (binding != null) {
+                               return binding;
+                       }
+                       binding = new TypeBinding(this, referenceBinding);
+                       this.bindingTables.compilerBindingsToASTBindings.put(referenceBinding, binding);
+                       return binding;
+               }
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized ITypeBinding getTypeBinding(RecoveredTypeBinding recoveredTypeBinding, int dimensions) {
+               if (recoveredTypeBinding== null) {
+                       return null;
+               }
+               return new RecoveredTypeBinding(this, recoveredTypeBinding, dimensions);
+       }
+
+       synchronized IVariableBinding getVariableBinding(net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding variableBinding, VariableDeclaration variableDeclaration) {
+               if (this.isRecoveringBindings) {
+                       if (variableBinding != null) {
+                               if (variableBinding.isValidBinding()) {
+                                       IVariableBinding binding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableBinding);
+                                       if (binding != null) {
+                                               return binding;
+                                       }
+                                       if (variableBinding.type != null) {
+                                               binding = new VariableBinding(this, variableBinding);
+                                       } else {
+                                               binding = new RecoveredVariableBinding(this, variableDeclaration);
+                                       }
+                                       this.bindingTables.compilerBindingsToASTBindings.put(variableBinding, binding);
+                                       return binding;
+                               } else {
+                                       /*
+                                        * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
+                                        */
+                                       if (variableBinding instanceof ProblemFieldBinding) {
+                                               ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) variableBinding;
+                                               switch(problemFieldBinding.problemId()) {
+                                                       case ProblemReasons.NotVisible :
+                                                       case ProblemReasons.NonStaticReferenceInStaticContext :
+                                                       case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+                                                               ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+                                                               FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
+                                                               if (exactBinding != null) {
+                                                                       IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+                                                                       if (variableBinding2 != null) {
+                                                                               return variableBinding2;
+                                                                       }
+                                                                       variableBinding2 = new VariableBinding(this, exactBinding);
+                                                                       this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
+                                                                       return variableBinding2;
+                                                               }
+                                                               break;
+                                               }
+                                       }
+                               }
+                       }
+                       return null;
+               }
+               return this.getVariableBinding(variableBinding);
+       }
+
+       public WorkingCopyOwner getWorkingCopyOwner() {
+               return this.workingCopyOwner;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized IVariableBinding getVariableBinding(net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding variableBinding) {
+               if (variableBinding != null) {
+                       if (variableBinding.isValidBinding()) {
+                               net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding variableType = variableBinding.type;
+                               if (variableType != null) {
+                                       if (!this.isRecoveringBindings && ((variableType.tagBits & TagBits.HasMissingType) != 0)) {
+                                               return null;
+                                       }
+                                       IVariableBinding binding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(variableBinding);
+                                       if (binding != null) {
+                                               return binding;
+                                       }
+                                       binding = new VariableBinding(this, variableBinding);
+                                       this.bindingTables.compilerBindingsToASTBindings.put(variableBinding, binding);
+                                       return binding;
+                               }
+                       } else {
+                               /*
+                                * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
+                                */
+                               if (variableBinding instanceof ProblemFieldBinding) {
+                                       ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) variableBinding;
+                                       switch(problemFieldBinding.problemId()) {
+                                               case ProblemReasons.NotVisible :
+                                               case ProblemReasons.NonStaticReferenceInStaticContext :
+                                               case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+                                                       ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+                                                       FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
+                                                       if (exactBinding != null) {
+                                                               IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+                                                               if (variableBinding2 != null) {
+                                                                       return variableBinding2;
+                                                               }
+                                                               variableBinding2 = new VariableBinding(this, exactBinding);
+                                                               this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
+                                                               return variableBinding2;
+                                                       }
+                                                       break;
+                                       }
+                               }
+                       }
+               }
+               return null;
+       }
+
+       synchronized IAnnotationBinding getAnnotationInstance(net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding internalInstance) {
+               if (internalInstance == null) return null;
+               ReferenceBinding annotationType = internalInstance.getAnnotationType();
+               if (!this.isRecoveringBindings) {
+                       if (annotationType == null || ((annotationType.tagBits & TagBits.HasMissingType) != 0)) {
+                               return null;
+                       }
+               }
+               IAnnotationBinding domInstance =
+                       (IAnnotationBinding) this.bindingTables.compilerBindingsToASTBindings.get(internalInstance);
+               if (domInstance != null)
+                       return domInstance;
+               domInstance = new AnnotationBinding(internalInstance, this);
+               this.bindingTables.compilerBindingsToASTBindings.put(internalInstance, domInstance);
+               return domInstance;
+       }
+
+       boolean isResolvedTypeInferredFromExpectedType(MethodInvocation methodInvocation) {
+               Object oldNode = this.newAstToOldAst.get(methodInvocation);
+               if (oldNode instanceof MessageSend) {
+                       MessageSend messageSend = (MessageSend) oldNode;
+                       net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding = messageSend.binding;
+                       if (methodBinding instanceof ParameterizedGenericMethodBinding) {
+                               ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) methodBinding;
+                               return genericMethodBinding.inferredReturnType;
+                       }
+               }
+               return false;
+       }
+
+       boolean isResolvedTypeInferredFromExpectedType(SuperMethodInvocation superMethodInvocation) {
+               Object oldNode = this.newAstToOldAst.get(superMethodInvocation);
+               if (oldNode instanceof MessageSend) {
+                       MessageSend messageSend = (MessageSend) oldNode;
+                       net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding = messageSend.binding;
+                       if (methodBinding instanceof ParameterizedGenericMethodBinding) {
+                               ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) methodBinding;
+                               return genericMethodBinding.inferredReturnType;
+                       }
+               }
+               return false;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       LookupEnvironment lookupEnvironment() {
+               return this.scope.environment();
+       }
+
+       /**
+        * @see org.eclipse.jdt.core.dom.BindingResolver#recordScope(ASTNode, BlockScope)
+        */
+       synchronized void recordScope(ASTNode astNode, BlockScope blockScope) {
+               this.astNodesToBlockScope.put(astNode, blockScope);
+       }
+
+       /*
+        * @see BindingResolver#resolveBoxing(Expression)
+        */
+       boolean resolveBoxing(Expression expression) {
+               net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+               if (node != null && (node instanceof net.sourceforge.phpdt.internal.compiler.ast.Expression)) {
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression compilerExpression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) node;
+                       return (compilerExpression.implicitConversion & TypeIds.BOXING) != 0;
+               }
+               return false;
+       }
+
+       /*
+        * @see BindingResolver#resolveUnboxing(Expression)
+        */
+       boolean resolveUnboxing(Expression expression) {
+               net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+               if (node != null && (node instanceof net.sourceforge.phpdt.internal.compiler.ast.Expression)) {
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression compilerExpression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) node;
+                       return (compilerExpression.implicitConversion & TypeIds.UNBOXING) != 0;
+               }
+               return false;
+       }
+
+       /*
+        * @see BindingResolver#resolveConstantExpressionValue(Expression)
+        */
+       Object resolveConstantExpressionValue(Expression expression) {
+               net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+               if (node != null && (node instanceof net.sourceforge.phpdt.internal.compiler.ast.Expression)) {
+                       net.sourceforge.phpdt.internal.compiler.ast.Expression compilerExpression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) node;
+                       Constant constant = compilerExpression.constant;
+                       if (constant != null && constant != Constant.NotAConstant) {
+                               switch (constant.typeID()) {
+                                       case TypeIds.T_int : return new Integer(constant.intValue());
+                                       case TypeIds.T_byte : return new Byte(constant.byteValue());
+                                       case TypeIds.T_short : return new Short(constant.shortValue());
+                                       case TypeIds.T_char : return new Character(constant.charValue());
+                                       case TypeIds.T_float : return new Float(constant.floatValue());
+                                       case TypeIds.T_double : return new Double(constant.doubleValue());
+                                       case TypeIds.T_boolean : return constant.booleanValue() ? Boolean.TRUE : Boolean.FALSE;
+                                       case TypeIds.T_long : return new Long(constant.longValue());
+                                       case TypeIds.T_JavaLangString : return constant.stringValue();
+                               }
+                               return null;
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * @see BindingResolver#resolveConstructor(ClassInstanceCreation)
+        */
+       synchronized IMethodBinding resolveConstructor(ClassInstanceCreation expression) {
+               net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+               if (node != null && (node.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.IsAnonymousType) != 0) {
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
+                       return this.getMethodBinding(anonymousLocalTypeDeclaration.allocation.binding);
+               } else if (node instanceof AllocationExpression) {
+                       return this.getMethodBinding(((AllocationExpression)node).binding);
+               }
+               return null;
+       }
+
+       /*
+        * @see BindingResolver#resolveConstructor(ConstructorInvocation)
+        */
+       synchronized IMethodBinding resolveConstructor(ConstructorInvocation expression) {
+               net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+               if (node instanceof ExplicitConstructorCall) {
+                       ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
+                       return this.getMethodBinding(explicitConstructorCall.binding);
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.BindingResolver#resolveConstructor(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
+        */
+       IMethodBinding resolveConstructor(EnumConstantDeclaration enumConstantDeclaration) {
+               net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(enumConstantDeclaration);
+               if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) node;
+                       if (fieldDeclaration.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT && fieldDeclaration.initialization != null) {
+                               AllocationExpression allocationExpression = (AllocationExpression) fieldDeclaration.initialization;
+                               return this.getMethodBinding(allocationExpression.binding);
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * @see BindingResolver#resolveConstructor(SuperConstructorInvocation)
+        */
+       synchronized IMethodBinding resolveConstructor(SuperConstructorInvocation expression) {
+               net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+               if (node instanceof ExplicitConstructorCall) {
+                       ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
+                       return this.getMethodBinding(explicitConstructorCall.binding);
+               }
+               return null;
+       }
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized ITypeBinding resolveExpressionType(Expression expression) {
+               try {
+                       switch(expression.getNodeType()) {
+                               case ASTNode.CLASS_INSTANCE_CREATION :
+                                       net.sourceforge.phpdt.internal.compiler.ast.ASTNode astNode = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+                                       if (astNode instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
+                                               // anonymous type case
+                                               net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) astNode;
+                                               ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+                                               if (typeBinding != null) {
+                                                       return typeBinding;
+                                               }
+                                       } else {
+                                               // should be an AllocationExpression
+                                               AllocationExpression allocationExpression = (AllocationExpression) astNode;
+                                               return this.getTypeBinding(allocationExpression.resolvedType);
+                                       }
+                                       break;
+                               case ASTNode.SIMPLE_NAME :
+                               case ASTNode.QUALIFIED_NAME :
+                                       return this.resolveTypeBindingForName((Name) expression);
+                               case ASTNode.ARRAY_INITIALIZER :
+                               case ASTNode.ARRAY_CREATION :
+                               case ASTNode.ASSIGNMENT :
+                               case ASTNode.POSTFIX_EXPRESSION :
+                               case ASTNode.PREFIX_EXPRESSION :
+                               case ASTNode.CAST_EXPRESSION :
+                               case ASTNode.TYPE_LITERAL :
+                               case ASTNode.INFIX_EXPRESSION :
+                               case ASTNode.INSTANCEOF_EXPRESSION :
+                               case ASTNode.FIELD_ACCESS :
+                               case ASTNode.SUPER_FIELD_ACCESS :
+                               case ASTNode.ARRAY_ACCESS :
+                               case ASTNode.METHOD_INVOCATION :
+                               case ASTNode.SUPER_METHOD_INVOCATION :
+                               case ASTNode.CONDITIONAL_EXPRESSION :
+                               case ASTNode.MARKER_ANNOTATION :
+                               case ASTNode.NORMAL_ANNOTATION :
+                               case ASTNode.SINGLE_MEMBER_ANNOTATION :
+                                       net.sourceforge.phpdt.internal.compiler.ast.Expression compilerExpression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(expression);
+                                       if (compilerExpression != null) {
+                                               return this.getTypeBinding(compilerExpression.resolvedType);
+                                       }
+                                       break;
+                               case ASTNode.STRING_LITERAL :
+                                       if (this.scope != null) {
+                                               return this.getTypeBinding(this.scope.getJavaLangString());
+                                       }
+                                       break;
+                               case ASTNode.BOOLEAN_LITERAL :
+                               case ASTNode.NULL_LITERAL :
+                               case ASTNode.CHARACTER_LITERAL :
+                               case ASTNode.NUMBER_LITERAL :
+                                       Literal literal = (Literal) this.newAstToOldAst.get(expression);
+                                       return this.getTypeBinding(literal.literalType(null));
+                               case ASTNode.THIS_EXPRESSION :
+                                       ThisReference thisReference = (ThisReference) this.newAstToOldAst.get(expression);
+                                       BlockScope blockScope = (BlockScope) this.astNodesToBlockScope.get(expression);
+                                       if (blockScope != null) {
+                                               return this.getTypeBinding(thisReference.resolveType(blockScope));
+                                       }
+                                       break;
+                               case ASTNode.PARENTHESIZED_EXPRESSION :
+                                       ParenthesizedExpression parenthesizedExpression = (ParenthesizedExpression) expression;
+                                       return this.resolveExpressionType(parenthesizedExpression.getExpression());
+                               case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
+                                       VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) expression;
+                                       Type type = variableDeclarationExpression.getType();
+                                       if (type != null) {
+                                               return type.resolveBinding();
+                                       }
+                                       break;
+                       }
+               } catch (AbortCompilation e) {
+                       // handle missing types
+               }
+               return null;
+       }
+
+       /*
+        * @see BindingResolver#resolveField(FieldAccess)
+        */
+       synchronized IVariableBinding resolveField(FieldAccess fieldAccess) {
+               Object oldNode = this.newAstToOldAst.get(fieldAccess);
+               if (oldNode instanceof FieldReference) {
+                       FieldReference fieldReference = (FieldReference) oldNode;
+                       return this.getVariableBinding(fieldReference.binding);
+               }
+               return null;
+       }
+
+       /*
+        * @see BindingResolver#resolveField(SuperFieldAccess)
+        */
+       synchronized IVariableBinding resolveField(SuperFieldAccess fieldAccess) {
+               Object oldNode = this.newAstToOldAst.get(fieldAccess);
+               if (oldNode instanceof FieldReference) {
+                       FieldReference fieldReference = (FieldReference) oldNode;
+                       return this.getVariableBinding(fieldReference.binding);
+               }
+               return null;
+       }
+
+       /*
+        * @see BindingResolver#resolveImport(ImportDeclaration)
+        */
+       synchronized IBinding resolveImport(ImportDeclaration importDeclaration) {
+               if (this.scope == null) return null;
+               try {
+                       net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(importDeclaration);
+                       if (node instanceof ImportReference) {
+                               ImportReference importReference = (ImportReference) node;
+                               final boolean isStatic = importReference.isStatic();
+                               if ((importReference.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OnDemand) != 0) {
+                                       Binding binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length), true, isStatic);
+                                       if (binding != null) {
+                                               if (isStatic) {
+                                                       if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
+                                                               ITypeBinding typeBinding = this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
+                                                               return typeBinding == null ? null : typeBinding;
+                                                       }
+                                               } else {
+                                                       if ((binding.kind() & Binding.PACKAGE) != 0) {
+                                                               IPackageBinding packageBinding = this.getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) binding);
+                                                               if (packageBinding == null) {
+                                                                       return null;
+                                                               }
+                                                               return packageBinding;
+                                                       } else {
+                                                               // if it is not a package, it has to be a type
+                                                               ITypeBinding typeBinding = this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
+                                                               if (typeBinding == null) {
+                                                                       return null;
+                                                               }
+                                                               return typeBinding;
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       Binding binding = this.scope.getImport(importReference.tokens, false, isStatic);
+                                       if (binding != null) {
+                                               if (isStatic) {
+                                                       if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
+                                                               ITypeBinding typeBinding = this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
+                                                               return typeBinding == null ? null : typeBinding;
+                                                       } else if (binding instanceof FieldBinding) {
+                                                               IVariableBinding variableBinding = this.getVariableBinding((FieldBinding) binding);
+                                                               return variableBinding == null ? null : variableBinding;
+                                                       } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding) {
+                                                               // it is a type
+                                                               return this.getMethodBinding((net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding)binding);
+                                                       }
+                                               } else {
+                                                       if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
+                                                               ITypeBinding typeBinding = this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) binding);
+                                                               return typeBinding == null ? null : typeBinding;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               } catch(AbortCompilation e) {
+                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.BindingResolver#resolveMember(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration)
+        */
+       IMethodBinding resolveMember(AnnotationTypeMemberDeclaration declaration) {
+               Object oldNode = this.newAstToOldAst.get(declaration);
+               if (oldNode instanceof AbstractMethodDeclaration) {
+                       AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode;
+                       IMethodBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
+                       if (methodBinding == null) {
+                               return null;
+                       }
+                       this.bindingsToAstNodes.put(methodBinding, declaration);
+                       String key = methodBinding.getKey();
+                       if (key != null) {
+                               this.bindingTables.bindingKeysToBindings.put(key, methodBinding);
+                       }
+                       return methodBinding;
+               }
+               return null;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized IMethodBinding resolveMethod(MethodDeclaration method) {
+               Object oldNode = this.newAstToOldAst.get(method);
+               if (oldNode instanceof AbstractMethodDeclaration) {
+                       AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) oldNode;
+                       IMethodBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
+                       if (methodBinding == null) {
+                               return null;
+                       }
+                       this.bindingsToAstNodes.put(methodBinding, method);
+                       String key = methodBinding.getKey();
+                       if (key != null) {
+                               this.bindingTables.bindingKeysToBindings.put(key, methodBinding);
+                       }
+                       return methodBinding;
+               }
+               return null;
+       }
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized IMethodBinding resolveMethod(MethodInvocation method) {
+               Object oldNode = this.newAstToOldAst.get(method);
+               if (oldNode instanceof MessageSend) {
+                       MessageSend messageSend = (MessageSend) oldNode;
+                       return this.getMethodBinding(messageSend.binding);
+               }
+               return null;
+       }
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized IMethodBinding resolveMethod(SuperMethodInvocation method) {
+               Object oldNode = this.newAstToOldAst.get(method);
+               if (oldNode instanceof MessageSend) {
+                       MessageSend messageSend = (MessageSend) oldNode;
+                       return this.getMethodBinding(messageSend.binding);
+               }
+               return null;
+       }
+
+       synchronized ITypeBinding resolveTypeBindingForName(Name name) {
+               net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(name);
+               int index = name.index;
+               if (node instanceof QualifiedNameReference) {
+                       QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) node;
+                       final char[][] tokens = qualifiedNameReference.tokens;
+                       if (tokens.length == index) {
+                               return this.getTypeBinding(qualifiedNameReference.resolvedType);
+                       }
+                       int indexOfFirstFieldBinding = qualifiedNameReference.indexOfFirstFieldBinding; // one-based
+                       if (index < indexOfFirstFieldBinding) {
+                               // an extra lookup is required
+                               BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+                               Binding binding = null;
+                               try {
+                                       if (internalScope == null) {
+                                               if (this.scope == null) return null;
+                                               binding = this.scope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+                                       } else {
+                                               binding = internalScope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+                                       }
+                               } catch (AbortCompilation e) {
+                                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+                                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+                               }
+                               if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
+                                       return null;
+                               } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
+                                       // it is a type
+                                       return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
+                               }
+                       } else if (index == indexOfFirstFieldBinding) {
+                               if (qualifiedNameReference.isTypeReference()) {
+                                       return this.getTypeBinding(qualifiedNameReference.resolvedType);
+                               } else {
+                                       // in this case we want to get the next field declaring's class
+                                       if (qualifiedNameReference.otherBindings == null) {
+                                               return null;
+                                       }
+                                       FieldBinding fieldBinding = qualifiedNameReference.otherBindings[0];
+                                       if (fieldBinding == null) return null;
+                                       net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding type = fieldBinding.declaringClass;
+                                       if (type == null) { // array length scenario
+                                               // use type from first binding (no capture needed for array type)
+                                               switch (qualifiedNameReference.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.RestrictiveFlagMASK) {
+                                                       case Binding.FIELD:
+                                                               type = ((FieldBinding) qualifiedNameReference.binding).type;
+                                                               break;
+                                                       case Binding.LOCAL:
+                                                               type = ((LocalVariableBinding) qualifiedNameReference.binding).type;
+                                                               break;
+                                               }
+                                       }
+                                       return this.getTypeBinding(type);
+                               }
+                       } else {
+                               /* This is the case for a name which is part of a qualified name that
+                                * cannot be resolved. See PR 13063.
+                                */
+                               if (qualifiedNameReference.otherBindings == null) return null;
+                               final int otherBindingsLength = qualifiedNameReference.otherBindings.length;
+                               if (otherBindingsLength == (index - indexOfFirstFieldBinding)) {
+                                       return this.getTypeBinding(qualifiedNameReference.resolvedType);
+                               }
+                               FieldBinding fieldBinding = qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding];
+                               if (fieldBinding == null) return null;
+                               net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding type = fieldBinding.declaringClass;
+                               if (type == null) { // array length scenario
+                                       // use type from previous binding (no capture needed for array type)
+                                       fieldBinding = qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding - 1];
+                                       if (fieldBinding == null) return null;
+                                       type = fieldBinding.type;
+                               }
+                               return this.getTypeBinding(type);
+                       }
+               } else if (node instanceof QualifiedTypeReference) {
+                       QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) node;
+                       if (qualifiedTypeReference.resolvedType == null) {
+                               return null;
+                       }
+                       if (index == qualifiedTypeReference.tokens.length) {
+                               if (!qualifiedTypeReference.resolvedType.isValidBinding() && qualifiedTypeReference instanceof JavadocQualifiedTypeReference) {
+                                       JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) node;
+                                       if (typeRef.packageBinding != null) {
+                                               return null;
+                                       }
+                               }
+                               return this.getTypeBinding(qualifiedTypeReference.resolvedType.leafComponentType());
+                       } else {
+                               if (index >= 0) {
+                                       BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+                                       Binding binding = null;
+                                       try {
+                                               if (internalScope == null) {
+                                                       if (this.scope == null) return null;
+                                                       binding = this.scope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+                                               } else {
+                                                       binding = internalScope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+                                               }
+                                       } catch (AbortCompilation e) {
+                                               // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+                                       }
+                                       if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
+                                               return null;
+                                       } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
+                                               // it is a type
+                                               return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
+                                       } else {
+                                               return null;
+                                       }
+                               }
+                       }
+               } else if (node instanceof ImportReference) {
+                       ImportReference importReference = (ImportReference) node;
+                       int importReferenceLength = importReference.tokens.length;
+                       if (index >= 0) {
+                               Binding binding = null;
+                               if (this.scope == null) return null;
+                               if (importReferenceLength == index) {
+                                       try {
+                                               binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), (importReference.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OnDemand) != 0, importReference.isStatic());
+                                       } catch (AbortCompilation e) {
+                                               // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+                                       }
+                               } else {
+                                       try {
+                                               binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), true, importReference.isStatic());
+                                       } catch (AbortCompilation e) {
+                                               // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+                                       }
+                               }
+                               if (binding != null) {
+                                       if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
+                                               // it is a type
+                                               return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
+                                       }
+                                       return null;
+                               }
+                       }
+               } else if (node instanceof AbstractMethodDeclaration) {
+                       AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
+                       IMethodBinding method = this.getMethodBinding(methodDeclaration.binding);
+                       if (method == null) return null;
+                       return method.getReturnType();
+               } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
+                       ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+                       if (typeBinding != null) {
+                               return typeBinding;
+                       }
+               } if (node instanceof JavadocSingleNameReference) {
+                       JavadocSingleNameReference singleNameReference = (JavadocSingleNameReference) node;
+                       LocalVariableBinding localVariable = (LocalVariableBinding)singleNameReference.binding;
+                       if (localVariable != null) {
+                               return this.getTypeBinding(localVariable.type);
+                       }
+               } if (node instanceof SingleNameReference) {
+                       SingleNameReference singleNameReference = (SingleNameReference) node;
+                       return this.getTypeBinding(singleNameReference.resolvedType);
+               } else if (node instanceof QualifiedSuperReference) {
+                       QualifiedSuperReference qualifiedSuperReference = (QualifiedSuperReference) node;
+                       return this.getTypeBinding(qualifiedSuperReference.qualification.resolvedType);
+               } else if (node instanceof LocalDeclaration) {
+                       IVariableBinding variable = this.getVariableBinding(((LocalDeclaration)node).binding);
+                       if (variable == null) return null;
+                       return variable.getType();
+               } else if (node instanceof JavadocFieldReference) {
+                       JavadocFieldReference fieldRef = (JavadocFieldReference) node;
+                       if (fieldRef.methodBinding != null) {
+                               return getMethodBinding(fieldRef.methodBinding).getReturnType();
+                       }
+                       return getTypeBinding(fieldRef.resolvedType);
+               } else if (node instanceof FieldReference) {
+                       return getTypeBinding(((FieldReference) node).resolvedType);
+               } else if (node instanceof SingleTypeReference) {
+                       SingleTypeReference singleTypeReference = (SingleTypeReference) node;
+                       net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding = singleTypeReference.resolvedType;
+                       if (binding != null) {
+                               return this.getTypeBinding(binding.leafComponentType());
+                       }
+               } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) node;
+                       IVariableBinding field = this.getVariableBinding(fieldDeclaration.binding);
+                       if (field == null) return null;
+                       return field.getType();
+               } else if (node instanceof MessageSend) {
+                       MessageSend messageSend = (MessageSend) node;
+                       IMethodBinding method = getMethodBinding(messageSend.binding);
+                       if (method == null) return null;
+                       return method.getReturnType();
+               } else if (node instanceof AllocationExpression) {
+                       AllocationExpression allocation = (AllocationExpression) node;
+                       return getTypeBinding(allocation.resolvedType);
+               } else if (node instanceof JavadocImplicitTypeReference) {
+                       JavadocImplicitTypeReference implicitRef = (JavadocImplicitTypeReference) node;
+                       return getTypeBinding(implicitRef.resolvedType);
+               } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) {
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeParameter typeParameter = (net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) node;
+                       return this.getTypeBinding(typeParameter.binding);
+               } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair) {
+                       net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair memberValuePair = (net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair) node;
+                       IMethodBinding method = getMethodBinding(memberValuePair.binding);
+                       if (method == null) return null;
+                       return method.getReturnType();
+               }
+               return null;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized IBinding resolveName(Name name) {
+               net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(name);
+               int index = name.index;
+               if (node instanceof QualifiedNameReference) {
+                       QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) node;
+                       final char[][] tokens = qualifiedNameReference.tokens;
+                       int indexOfFirstFieldBinding = qualifiedNameReference.indexOfFirstFieldBinding; // one-based
+                       if (index < indexOfFirstFieldBinding) {
+                               // an extra lookup is required
+                               BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+                               Binding binding = null;
+                               try {
+                                       if (internalScope == null) {
+                                               if (this.scope == null) return null;
+                                               binding = this.scope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+                                       } else {
+                                               binding = internalScope.getTypeOrPackage(CharOperation.subarray(tokens, 0, index));
+                                       }
+                               } catch (AbortCompilation e) {
+                                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+                                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+                               }
+                               if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
+                                       return this.getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding)binding);
+                               } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
+                                       // it is a type
+                                       return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
+                               }
+                       } else if (index == indexOfFirstFieldBinding) {
+                               if (qualifiedNameReference.isTypeReference()) {
+                                       return this.getTypeBinding(qualifiedNameReference.resolvedType);
+                               } else {
+                                       Binding binding = qualifiedNameReference.binding;
+                                       if (binding != null) {
+                                               if (binding.isValidBinding()) {
+                                                       return this.getVariableBinding((net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding) binding);
+                                               } else  if (binding instanceof ProblemFieldBinding) {
+                                                       ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
+                                                       switch(problemFieldBinding.problemId()) {
+                                                               case ProblemReasons.NotVisible :
+                                                               case ProblemReasons.NonStaticReferenceInStaticContext :
+                                                                       ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+                                                                       if (declaringClass != null) {
+                                                                               FieldBinding exactBinding = declaringClass.getField(tokens[tokens.length - 1], true /*resolve*/);
+                                                                               if (exactBinding != null) {
+                                                                                       if (exactBinding.type != null) {
+                                                                                               IVariableBinding variableBinding = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+                                                                                               if (variableBinding != null) {
+                                                                                                       return variableBinding;
+                                                                                               }
+                                                                                               variableBinding = new VariableBinding(this, exactBinding);
+                                                                                               this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding);
+                                                                                               return variableBinding;
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                                       break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       } else {
+                               /* This is the case for a name which is part of a qualified name that
+                                * cannot be resolved. See PR 13063.
+                                */
+                               if (qualifiedNameReference.otherBindings == null || (index - indexOfFirstFieldBinding - 1) < 0) {
+                                       return null;
+                               } else {
+                                       return this.getVariableBinding(qualifiedNameReference.otherBindings[index - indexOfFirstFieldBinding - 1]);
+                               }
+                       }
+               } else if (node instanceof QualifiedTypeReference) {
+                       QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) node;
+                       if (qualifiedTypeReference.resolvedType == null) {
+                               return null;
+                       }
+                       if (index == qualifiedTypeReference.tokens.length) {
+                               if (!qualifiedTypeReference.resolvedType.isValidBinding() && qualifiedTypeReference instanceof JavadocQualifiedTypeReference) {
+                                       JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) node;
+                                       if (typeRef.packageBinding != null) {
+                                               return getPackageBinding(typeRef.packageBinding);
+                                       }
+                               }
+                               return this.getTypeBinding(qualifiedTypeReference.resolvedType.leafComponentType());
+                       } else {
+                               if (index >= 0) {
+                                       BlockScope internalScope = (BlockScope) this.astNodesToBlockScope.get(name);
+                                       Binding binding = null;
+                                       try {
+                                               if (internalScope == null) {
+                                                       if (this.scope == null) return null;
+                                                       binding = this.scope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+                                               } else {
+                                                       binding = internalScope.getTypeOrPackage(CharOperation.subarray(qualifiedTypeReference.tokens, 0, index));
+                                               }
+                                       } catch (AbortCompilation e) {
+                                               // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+                                       }
+                                       if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
+                                               return this.getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding)binding);
+                                       } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
+                                               // it is a type
+                                               return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
+                                       } else {
+                                               return null;
+                                       }
+                               }
+                       }
+               } else if (node instanceof ImportReference) {
+                       ImportReference importReference = (ImportReference) node;
+                       int importReferenceLength = importReference.tokens.length;
+                       if (index >= 0) {
+                               Binding binding = null;
+                               if (this.scope == null) return null;
+                               if (importReferenceLength == index) {
+                                       try {
+                                               binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), (importReference.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.OnDemand) != 0, importReference.isStatic());
+                                       } catch (AbortCompilation e) {
+                                               // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+                                       }
+                               } else {
+                                       try {
+                                               binding = this.scope.getImport(CharOperation.subarray(importReference.tokens, 0, index), true, importReference.isStatic());
+                                       } catch (AbortCompilation e) {
+                                               // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+                                       }
+                               }
+                               if (binding != null) {
+                                       if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
+                                               return this.getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding)binding);
+                                       } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
+                                               // it is a type
+                                               return this.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding)binding);
+                                       } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding) {
+                                               // it is a type
+                                               return this.getVariableBinding((net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding)binding);
+                                       } else if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding) {
+                                               // it is a type
+                                               return this.getMethodBinding((net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding)binding);
+                                       } else {
+                                               return null;
+                                       }
+                               }
+                       }
+               } else if (node instanceof CompilationUnitDeclaration) {
+                       CompilationUnitDeclaration compilationUnitDeclaration = (CompilationUnitDeclaration) node;
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+                       if (types == null || types.length == 0) {
+                               return null;
+                       }
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration type = types[0];
+                       if (type != null) {
+                               ITypeBinding typeBinding = this.getTypeBinding(type.binding);
+                               if (typeBinding != null) {
+                                       return typeBinding.getPackage();
+                               }
+                       }
+               } else if (node instanceof AbstractMethodDeclaration) {
+                       AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) node;
+                       IMethodBinding methodBinding = this.getMethodBinding(methodDeclaration.binding);
+                       if (methodBinding != null) {
+                               return methodBinding;
+                       }
+               } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
+                       ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+                       if (typeBinding != null) {
+                               return typeBinding;
+                       }
+               } if (node instanceof SingleNameReference) {
+                       SingleNameReference singleNameReference = (SingleNameReference) node;
+                       if (singleNameReference.isTypeReference()) {
+                               return this.getTypeBinding(singleNameReference.resolvedType);
+                       } else {
+                               // this is a variable or a field
+                               Binding binding = singleNameReference.binding;
+                               if (binding != null) {
+                                       if (binding.isValidBinding()) {
+                                               return this.getVariableBinding((net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding) binding);
+                                       } else {
+                                               /*
+                                                * http://dev.eclipse.org/bugs/show_bug.cgi?id=24449
+                                                */
+                                               if (binding instanceof ProblemFieldBinding) {
+                                                       ProblemFieldBinding problemFieldBinding = (ProblemFieldBinding) binding;
+                                                       switch(problemFieldBinding.problemId()) {
+                                                               case ProblemReasons.NotVisible :
+                                                               case ProblemReasons.NonStaticReferenceInStaticContext :
+                                                               case ProblemReasons.NonStaticReferenceInConstructorInvocation :
+                                                                       ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
+                                                                       FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
+                                                                       if (exactBinding != null) {
+                                                                               if (exactBinding.type != null) {
+                                                                                       IVariableBinding variableBinding2 = (IVariableBinding) this.bindingTables.compilerBindingsToASTBindings.get(exactBinding);
+                                                                                       if (variableBinding2 != null) {
+                                                                                               return variableBinding2;
+                                                                                       }
+                                                                                       variableBinding2 = new VariableBinding(this, exactBinding);
+                                                                                       this.bindingTables.compilerBindingsToASTBindings.put(exactBinding, variableBinding2);
+                                                                                       return variableBinding2;
+                                                                               }
+                                                                       }
+                                                                       break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               } else if (node instanceof QualifiedSuperReference) {
+                       QualifiedSuperReference qualifiedSuperReference = (QualifiedSuperReference) node;
+                       return this.getTypeBinding(qualifiedSuperReference.qualification.resolvedType);
+               } else if (node instanceof LocalDeclaration) {
+                       return this.getVariableBinding(((LocalDeclaration)node).binding);
+               } else if (node instanceof JavadocFieldReference) {
+                       JavadocFieldReference fieldRef = (JavadocFieldReference) node;
+                       if (fieldRef.methodBinding != null) {
+                               return getMethodBinding(fieldRef.methodBinding);
+                       }
+                       return getVariableBinding(fieldRef.binding);
+               } else if (node instanceof FieldReference) {
+                       return getVariableBinding(((FieldReference) node).binding);
+               } else if (node instanceof SingleTypeReference) {
+                       if (node instanceof JavadocSingleTypeReference) {
+                               JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) node;
+                               if (typeRef.packageBinding != null) {
+                                       return getPackageBinding(typeRef.packageBinding);
+                               }
+                       }                       
+                       SingleTypeReference singleTypeReference = (SingleTypeReference) node;
+                       net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding = singleTypeReference.resolvedType;
+                       if (binding == null) {
+                               return null;
+                       }
+                       return this.getTypeBinding(binding.leafComponentType());
+               } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) node;
+                       return this.getVariableBinding(fieldDeclaration.binding);
+               } else if (node instanceof MessageSend) {
+                       MessageSend messageSend = (MessageSend) node;
+                       return getMethodBinding(messageSend.binding);
+               } else if (node instanceof AllocationExpression) {
+                       AllocationExpression allocation = (AllocationExpression) node;
+                       return getMethodBinding(allocation.binding);
+               } else if (node instanceof JavadocImplicitTypeReference) {
+                       JavadocImplicitTypeReference implicitRef = (JavadocImplicitTypeReference) node;
+                       return getTypeBinding(implicitRef.resolvedType);
+               } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) {
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeParameter typeParameter = (net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) node;
+                       return this.getTypeBinding(typeParameter.binding);
+               } else if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair) {
+                       net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair memberValuePair = (net.sourceforge.phpdt.internal.compiler.ast.MemberValuePair) node;
+                       return getMethodBinding(memberValuePair.binding);
+               }
+               return null;
+       }
+
+       /*
+        * @see BindingResolver#resolvePackage(PackageDeclaration)
+        */
+       synchronized IPackageBinding resolvePackage(PackageDeclaration pkg) {
+               if (this.scope == null) return null;
+               try {
+                       net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(pkg);
+                       if (node instanceof ImportReference) {
+                               ImportReference importReference = (ImportReference) node;
+                               Binding binding = this.scope.getTypeOrPackage(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length));
+                               if ((binding != null) && (binding.isValidBinding())) {
+                                       if (binding instanceof ReferenceBinding) {
+                                               // this only happens if a type name has the same name as its package
+                                               ReferenceBinding referenceBinding = (ReferenceBinding) binding;
+                                               binding = referenceBinding.fPackage;
+                                       }
+                                       if (binding instanceof net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) {
+                                               IPackageBinding packageBinding = this.getPackageBinding((net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding) binding);
+                                               if (packageBinding == null) {
+                                                       return null;
+                                               }
+                                               this.bindingsToAstNodes.put(packageBinding, pkg);
+                                               String key = packageBinding.getKey();
+                                               if (key != null) {
+                                                       this.bindingTables.bindingKeysToBindings.put(key, packageBinding);
+                                               }
+                                               return packageBinding;
+                                       }
+                               }
+                       }
+               } catch (AbortCompilation e) {
+                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53357
+                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see BindingResolver#resolveReference(MemberRef)
+     * @since 3.0
+        */
+       synchronized IBinding resolveReference(MemberRef ref) {
+               net.sourceforge.phpdt.internal.compiler.ast.Expression expression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
+               if (expression instanceof TypeReference) {
+                       return getTypeBinding(expression.resolvedType);
+               }
+               else if (expression instanceof JavadocFieldReference) {
+                       JavadocFieldReference fieldRef = (JavadocFieldReference) expression;
+                       if (fieldRef.methodBinding != null) {
+                               return getMethodBinding(fieldRef.methodBinding);
+                       }
+                       return getVariableBinding(fieldRef.binding);
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see BindingResolver#resolveMemberValuePair(MemberValuePair)
+     * @since 3.2
+        */
+       synchronized IMemberValuePairBinding resolveMemberValuePair(net.sourceforge.phpdt.core.dom.MemberValuePair memberValuePair) {
+               MemberValuePair valuePair = (MemberValuePair) this.newAstToOldAst.get(memberValuePair);
+               return getMemberValuePairBinding(valuePair.compilerElementPair);
+       }
+
+       /* (non-Javadoc)
+        * @see BindingResolver#resolveReference(MethodRef)
+     * @since 3.0
+        */
+       synchronized IBinding resolveReference(MethodRef ref) {
+               net.sourceforge.phpdt.internal.compiler.ast.Expression expression = (net.sourceforge.phpdt.internal.compiler.ast.Expression) this.newAstToOldAst.get(ref);
+               if (expression instanceof JavadocMessageSend) {
+                       return this.getMethodBinding(((JavadocMessageSend)expression).binding);
+               }
+               else if (expression instanceof JavadocAllocationExpression) {
+                       return this.getMethodBinding(((JavadocAllocationExpression)expression).binding);
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.BindingResolver#resolveType(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration)
+        */
+       ITypeBinding resolveType(AnnotationTypeDeclaration type) {
+               final Object node = this.newAstToOldAst.get(type);
+               if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
+                       ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+                       if (typeBinding == null) {
+                               return null;
+                       }
+                       this.bindingsToAstNodes.put(typeBinding, type);
+                       String key = typeBinding.getKey();
+                       if (key != null) {
+                               this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+                       }
+                       return typeBinding;
+               }
+               return null;
+       }
+       /*
+        * @see BindingResolver#resolveType(AnonymousClassDeclaration)
+        */
+       synchronized ITypeBinding resolveType(AnonymousClassDeclaration type) {
+               net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
+               if (node != null && (node.bits & net.sourceforge.phpdt.internal.compiler.ast.ASTNode.IsAnonymousType) != 0) {
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
+                       ITypeBinding typeBinding = this.getTypeBinding(anonymousLocalTypeDeclaration.binding);
+                       if (typeBinding == null) {
+                               return null;
+                       }
+                       this.bindingsToAstNodes.put(typeBinding, type);
+                       String key = typeBinding.getKey();
+                       if (key != null) {
+                               this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+                       }
+                       return typeBinding;
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.BindingResolver#resolveType(org.eclipse.jdt.core.dom.EnumDeclaration)
+        */
+       ITypeBinding resolveType(EnumDeclaration type) {
+               final Object node = this.newAstToOldAst.get(type);
+               if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
+                       ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+                       if (typeBinding == null) {
+                               return null;
+                       }
+                       this.bindingsToAstNodes.put(typeBinding, type);
+                       String key = typeBinding.getKey();
+                       if (key != null) {
+                               this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+                       }
+                       return typeBinding;
+               }
+               return null;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized ITypeBinding resolveType(Type type) {
+               // retrieve the old ast node
+               net.sourceforge.phpdt.internal.compiler.ast.ASTNode node = (net.sourceforge.phpdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
+               net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding = null;
+               if (node != null) {
+            if (node instanceof ParameterizedQualifiedTypeReference) {
+                               ParameterizedQualifiedTypeReference typeReference = (ParameterizedQualifiedTypeReference) node;
+                               net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding = typeReference.resolvedType;
+                               int index;
+                               if (type.isQualifiedType()) {
+                                       index = ((QualifiedType) type).index;
+                               } else if (type.isParameterizedType()) {
+                                       index = ((ParameterizedType) type).index;
+                               } else {
+                                       index = 1;
+                               }
+                               final int numberOfTypeArgumentsNotNull = getTypeArguments(typeReference);
+                               if (index != numberOfTypeArgumentsNotNull) {
+                                       int  i = numberOfTypeArgumentsNotNull;
+                                       while (i != index) {
+                                               typeBinding = typeBinding.enclosingType();
+                                               i --;
+                                       }
+                                       binding = typeBinding;
+                               } else {
+                                       binding = typeBinding;
+                               }
+            } else if (node instanceof TypeReference) {
+                               TypeReference typeReference = (TypeReference) node;
+                               binding = typeReference.resolvedType;
+                       } else if (node instanceof SingleNameReference && ((SingleNameReference)node).isTypeReference()) {
+                               binding = (((SingleNameReference)node).resolvedType);
+                       } else if (node instanceof QualifiedNameReference && ((QualifiedNameReference)node).isTypeReference()) {
+                               binding = (((QualifiedNameReference)node).resolvedType);
+                       } else if (node instanceof ArrayAllocationExpression) {
+                               binding = ((ArrayAllocationExpression) node).resolvedType;
+                       }
+                       if (binding != null) {
+                               if (type.isArrayType()) {
+                                       ArrayType arrayType = (ArrayType) type;
+                                       if (this.scope == null) return null;
+                                       if (binding.isArrayType()) {
+                                               ArrayBinding arrayBinding = (ArrayBinding) binding;
+                                               return getTypeBinding(this.scope.createArrayType(arrayBinding.leafComponentType, arrayType.getDimensions()));
+                                       } else {
+                                               return getTypeBinding(this.scope.createArrayType(binding, arrayType.getDimensions()));
+                                       }
+                               } else {
+                                       if (binding.isArrayType()) {
+                                               ArrayBinding arrayBinding = (ArrayBinding) binding;
+                                               return getTypeBinding(arrayBinding.leafComponentType);
+                                       } else {
+                                               return getTypeBinding(binding);
+                                       }
+                               }
+                       }
+               } else if (type.isPrimitiveType()) {
+                       /* Handle the void primitive type returned by getReturnType for a method declaration
+                        * that is a constructor declaration. It prevents null from being returned
+                        */
+                       if (((PrimitiveType) type).getPrimitiveTypeCode() == PrimitiveType.VOID) {
+                               return this.getTypeBinding(net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.VOID);
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized ITypeBinding resolveType(TypeDeclaration type) {
+               final Object node = this.newAstToOldAst.get(type);
+               if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration) node;
+                       ITypeBinding typeBinding = this.getTypeBinding(typeDeclaration.binding);
+                       if (typeBinding == null) {
+                               return null;
+                       }
+                       this.bindingsToAstNodes.put(typeBinding, type);
+                       String key = typeBinding.getKey();
+                       if (key != null) {
+                               this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+                       }
+                       return typeBinding;
+               }
+               return null;
+       }
+
+       synchronized ITypeBinding resolveTypeParameter(TypeParameter typeParameter) {
+               final Object node = this.newAstToOldAst.get(typeParameter);
+               if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) {
+                       net.sourceforge.phpdt.internal.compiler.ast.TypeParameter typeParameter2 = (net.sourceforge.phpdt.internal.compiler.ast.TypeParameter) node;
+                       ITypeBinding typeBinding = this.getTypeBinding(typeParameter2.binding);
+                       if (typeBinding == null) {
+                               return null;
+                       }
+                       this.bindingsToAstNodes.put(typeBinding, typeParameter);
+                       String key = typeBinding.getKey();
+                       if (key != null) {
+                               this.bindingTables.bindingKeysToBindings.put(key, typeBinding);
+                       }
+                       return typeBinding;
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.BindingResolver#resolveVariable(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
+        */
+       synchronized IVariableBinding resolveVariable(EnumConstantDeclaration enumConstant) {
+               final Object node = this.newAstToOldAst.get(enumConstant);
+               if (node instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) {
+                       net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) node;
+                       IVariableBinding variableBinding = this.getVariableBinding(fieldDeclaration.binding);
+                       if (variableBinding == null) {
+                               return null;
+                       }
+                       this.bindingsToAstNodes.put(variableBinding, enumConstant);
+                       String key = variableBinding.getKey();
+                       if (key != null) {
+                               this.bindingTables.bindingKeysToBindings.put(key, variableBinding);
+                       }
+                       return variableBinding;
+               }
+               return null;
+       }
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized IVariableBinding resolveVariable(VariableDeclaration variable) {
+               final Object node = this.newAstToOldAst.get(variable);
+               if (node instanceof AbstractVariableDeclaration) {
+                       AbstractVariableDeclaration abstractVariableDeclaration = (AbstractVariableDeclaration) node;
+                       IVariableBinding variableBinding = null;
+                       if (abstractVariableDeclaration instanceof net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) {
+                               net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration fieldDeclaration = (net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration) abstractVariableDeclaration;
+                               variableBinding = this.getVariableBinding(fieldDeclaration.binding, variable);
+                       } else {
+                               variableBinding = this.getVariableBinding(((LocalDeclaration) abstractVariableDeclaration).binding, variable);
+                       }
+                       if (variableBinding == null) {
+                               return null;
+                       }
+                       this.bindingsToAstNodes.put(variableBinding, variable);
+                       String key = variableBinding.getKey();
+                       if (key != null) {
+                               this.bindingTables.bindingKeysToBindings.put(key, variableBinding);
+                       }
+                       return variableBinding;
+               }
+               return null;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized ITypeBinding resolveWellKnownType(String name) {
+               if (this.scope == null) return null;
+               try {
+                       if (("boolean".equals(name))//$NON-NLS-1$
+                               || ("char".equals(name))//$NON-NLS-1$
+                               || ("byte".equals(name))//$NON-NLS-1$
+                               || ("short".equals(name))//$NON-NLS-1$
+                               || ("int".equals(name))//$NON-NLS-1$
+                               || ("long".equals(name))//$NON-NLS-1$
+                               || ("float".equals(name))//$NON-NLS-1$
+                               || ("double".equals(name))//$NON-NLS-1$
+                               || ("void".equals(name))) {//$NON-NLS-1$
+                               return this.getTypeBinding(Scope.getBaseType(name.toCharArray()));
+                       } else if ("java.lang.Object".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getJavaLangObject());
+                       } else if ("java.lang.String".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getJavaLangString());
+                       } else if ("java.lang.StringBuffer".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_STRINGBUFFER, 3));
+                       } else if ("java.lang.Throwable".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getJavaLangThrowable());
+                       } else if ("java.lang.Exception".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_EXCEPTION, 3));
+                       } else if ("java.lang.RuntimeException".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_RUNTIMEEXCEPTION, 3));
+                       } else if ("java.lang.Error".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_ERROR, 3));
+                       } else if ("java.lang.Class".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getJavaLangClass());
+                       } else if ("java.lang.Cloneable".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getJavaLangCloneable());
+                       } else if ("java.io.Serializable".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getJavaIoSerializable());
+                       } else if ("java.lang.Boolean".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_BOOLEAN, 3));
+                       } else if ("java.lang.Byte".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_BYTE, 3));
+                       } else if ("java.lang.Character".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_CHARACTER, 3));
+                       } else if ("java.lang.Double".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_DOUBLE, 3));
+                       } else if ("java.lang.Float".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_FLOAT, 3));
+                       } else if ("java.lang.Integer".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_INTEGER, 3));
+                       } else if ("java.lang.Long".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_LONG, 3));
+                       } else if ("java.lang.Short".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_SHORT, 3));
+                       } else if ("java.lang.Void".equals(name)) {//$NON-NLS-1$
+                               return this.getTypeBinding(this.scope.getType(TypeConstants.JAVA_LANG_VOID, 3));
+                       }
+               } catch (AbortCompilation e) {
+                       // ignore missing types
+               }
+               return null;
+       }
+
+       synchronized IAnnotationBinding resolveAnnotation(final Annotation domASTNode) {
+               Object oldNode = this.newAstToOldAst.get(domASTNode);
+               if (oldNode instanceof net.sourceforge.phpdt.internal.compiler.ast.Annotation) {
+                       net.sourceforge.phpdt.internal.compiler.ast.Annotation internalAstNode =
+                               (net.sourceforge.phpdt.internal.compiler.ast.Annotation) oldNode;
+
+                       IAnnotationBinding domAnnotation = this.getAnnotationInstance(internalAstNode.getCompilerAnnotation());
+                       if (domAnnotation == null)
+                               return null;
+                       this.bindingsToAstNodes.put(domAnnotation, domASTNode);
+                       return domAnnotation;
+               }
+               return null;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       public CompilationUnitScope scope() {
+               return this.scope;
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized void store(ASTNode node, net.sourceforge.phpdt.internal.compiler.ast.ASTNode oldASTNode) {
+               this.newAstToOldAst.put(node, oldASTNode);
+       }
+
+       /*
+        * Method declared on BindingResolver.
+        */
+       synchronized void updateKey(ASTNode node, ASTNode newNode) {
+               Object astNode = this.newAstToOldAst.remove(node);
+               if (astNode != null) {
+                       this.newAstToOldAst.put(newNode, astNode);
+               }
+       }
+
+       /**
+        * Answer an array type binding with the given type binding and the given
+        * dimensions.
+        *
+        * <p>If the given type binding is an array binding, then the resulting dimensions is the given dimensions
+        * plus the existing dimensions of the array binding. Otherwise the resulting dimensions is the given
+        * dimensions.</p>
+        *
+        * <p>
+        * The default implementation of this method returns <code>null</code>.
+        * Subclasses may reimplement.
+        * </p>
+        *
+        * @param typeBinding the given type binding
+        * @param dimensions the given dimensions
+        * @return an array type binding with the given type binding and the given
+        * dimensions
+        * @throws IllegalArgumentException if the type binding represents the <code>void</code> type binding
+        */
+       ITypeBinding resolveArrayType(ITypeBinding typeBinding, int dimensions) {
+               if (typeBinding instanceof RecoveredTypeBinding) throw new IllegalArgumentException("Cannot be called on a recovered type binding"); //$NON-NLS-1$
+               ITypeBinding leafComponentType = typeBinding;
+               int actualDimensions = dimensions;
+               if (typeBinding.isArray()) {
+                       leafComponentType = typeBinding.getElementType();
+                       actualDimensions += typeBinding.getDimensions();
+               }
+               net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding leafTypeBinding = null;
+               if (leafComponentType.isPrimitive()) {
+                       String name = leafComponentType.getBinaryName();
+                       switch(name.charAt(0)) {
+                               case 'I' :
+                                       leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.INT;
+                                       break;
+                               case 'B' :
+                                       leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.BYTE;
+                                       break;
+                               case 'Z' :
+                                       leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.BOOLEAN;
+                                       break;
+                               case 'C' :
+                                       leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.CHAR;
+                                       break;
+                               case 'J' :
+                                       leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.LONG;
+                                       break;
+                               case 'S' :
+                                       leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.SHORT;
+                                       break;
+                               case 'D' :
+                                       leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.DOUBLE;
+                                       break;
+                               case 'F' :
+                                       leafTypeBinding = net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.FLOAT;
+                                       break;
+                               case 'V' :
+                                       throw new IllegalArgumentException();
+                       }
+               } else {
+                       if (!(leafComponentType instanceof TypeBinding)) return null;
+                       leafTypeBinding = ((TypeBinding) leafComponentType).binding;
+               }
+               return this.getTypeBinding(this.lookupEnvironment().createArrayType(leafTypeBinding, actualDimensions));
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultCommentMapper.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultCommentMapper.java
new file mode 100644 (file)
index 0000000..94c479f
--- /dev/null
@@ -0,0 +1,644 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 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 net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+
+/**
+ * Internal class for associating comments with AST nodes.
+ * 
+ * @since 3.0
+ */
+class DefaultCommentMapper {
+       Comment[] comments;
+       Scanner scanner;
+       
+       // extended nodes storage
+       int leadingPtr;
+       ASTNode[] leadingNodes;
+       long[] leadingIndexes;
+       int trailingPtr, lastTrailingPtr;
+       ASTNode[] trailingNodes;
+       long[] trailingIndexes;
+       static final int STORAGE_INCREMENT = 16;
+
+       /**
+        * @param table the given table of comments
+        */
+       DefaultCommentMapper(Comment[] table) {
+               this.comments = table;
+       }
+
+       boolean hasSameTable(Comment[] table) {
+               return this.comments == table;
+       }
+
+       /**
+        * Get comment of the list which includes a given position
+        * 
+        * @param position The position belonging to the looked up comment
+        * @return comment which includes the given position or null if none was found
+        */
+       Comment getComment(int position) {
+
+               if (this.comments == null) {
+                       return null;
+               }
+               int size = this.comments.length;
+               if (size == 0) {
+                       return null;
+               }
+               int index = getCommentIndex(0, position, 0);
+               if (index<0) {
+                       return null;
+               }
+               return this.comments[index];
+       }
+
+       /*
+        * Get the index of comment which contains given position.
+        * If there's no matching comment, then return depends on exact parameter:
+        *              = 0: return -1
+        *              < 0: return index of the comment before the given position
+        *              > 0: return index of the comment after the given position
+        */
+       private int getCommentIndex(int start, int position, int exact) {
+               if (position == 0) {
+                       if (this.comments.length > 0 && this.comments[0].getStartPosition() == 0) {
+                               return 0;
+                       }
+                       return -1;
+               }
+               int bottom = start, top = this.comments.length - 1;
+               int i = 0, index = -1;
+               Comment comment = null;
+               while (bottom <= top) {
+                       i = bottom + (top - bottom) /2;
+                       comment = this.comments[i];
+                       int commentStart = comment.getStartPosition();
+                       if (position < commentStart) {
+                               top = i-1;
+                       } else if (position >=(commentStart+comment.getLength())) {
+                               bottom = i+1;
+                       } else {
+                               index = i;
+                               break;
+                       }
+               }
+               if (index<0 && exact!=0) {
+                       comment = this.comments[i];
+                       if (position < comment.getStartPosition()) {
+                               return exact<0 ? i-1 : i;
+                       } else {
+                               return exact<0 ? i : i+1;
+                       }
+               }
+               return index;
+       }
+
+       /**
+        * 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 (this.leadingPtr >= 0) {
+                       long range = -1;
+                       for (int i=0; range<0 && i<=this.leadingPtr; i++) {
+                               if (this.leadingNodes[i] == node) range = this.leadingIndexes[i];
+                       }
+                       if (range >= 0) {
+                               return  this.comments[(int)(range>>32)].getStartPosition() ;
+                       }
+               }
+               return node.getStartPosition();
+       }
+
+       /*
+        * Search the line number corresponding to a specific position
+        * between the given line range (inclusive)
+        * @param position int
+        * @parem lineRange size-2 int[]
+        * @return int
+        */
+       public final int getLineNumber(int position, int[] lineRange) {
+               int[] lineEnds = this.scanner.lineEnds;
+               int length = lineEnds.length;
+               return Util.getLineNumber(position, lineEnds, (lineRange[0] > length ? length : lineRange[0]) -1, (lineRange[1] > length ? length : lineRange[1]) - 1);
+       }
+
+       /*
+        * Returns the extended end position of the given node.
+        */
+       public int getExtendedEnd(ASTNode node) {
+               int end = node.getStartPosition() + node.getLength();
+               if (this.trailingPtr >= 0) {
+                       long range = -1;
+                       for (int i=0; range<0 && i<=this.trailingPtr; i++) {
+                               if (this.trailingNodes[i] == node) range = this.trailingIndexes[i];
+                       }
+                       if (range >= 0) {
+                               Comment lastComment = this.comments[(int) range];
+                               end = lastComment.getStartPosition() + lastComment.getLength();
+                       }
+               }
+               return end-1;
+       }
+
+       /**
+        * 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)
+        * @see #getExtendedEnd(ASTNode)
+        * @since 3.0
+        */
+       public int getExtendedLength(ASTNode node) {
+               return getExtendedEnd(node) - getExtendedStartPosition(node) + 1;
+       }
+
+       /**
+        * Return index of first leading comment of a given node.
+        * 
+        * @param node
+        * @return index of first leading comment or -1 if node has no leading comment
+        */
+       int firstLeadingCommentIndex(ASTNode node) {
+               if (this.leadingPtr >= 0) {
+                       for (int i=0; i<=this.leadingPtr; i++) {
+                               if (this.leadingNodes[i] == node) {
+                                       return (int) (this.leadingIndexes[i]>>32);
+                               }
+                       }
+               }
+               return -1;
+       }
+
+       /**
+        * Return index of last trailing comment of a given node.
+        * 
+        * @param node
+        * @return index of last trailing comment or -1 if node has no trailing comment
+        */
+       int lastTrailingCommentIndex(ASTNode node) {
+               if (this.trailingPtr >= 0) {
+                       for (int i=0; i<=this.trailingPtr; i++) {
+                               if (this.trailingNodes[i] == node) {
+                                       return (int) this.trailingIndexes[i];
+                               }
+                       }
+               }
+               return -1;
+       }
+
+       /*
+        * Initialize leading and trailing comments tables in whole nodes hierarchy of a compilation
+        * unit.
+        * Scanner is necessary to scan between nodes and comments and verify if there's
+        * nothing else than white spaces.
+        */
+       void initialize(CompilationUnit unit, Scanner sc) {
+
+               // Init array pointers
+               this.leadingPtr = -1;
+               this.trailingPtr = -1;
+       
+               // Init comments
+               this.comments = unit.optionalCommentTable;
+               if (this.comments == null) {
+                       return;
+               }
+               int size = this.comments.length;
+               if (size == 0) {
+                       return;
+               }
+
+               // Init scanner and start ranges computing
+               this.scanner = sc;
+               this.scanner.tokenizeWhiteSpace = true;
+
+               // Start unit visit
+               DefaultASTVisitor commentVisitor = new CommentMapperVisitor();
+               unit.accept(commentVisitor);
+               
+               // Reduce leading arrays if necessary
+               int leadingCount = this.leadingPtr + 1;
+               if (leadingCount > 0 && leadingCount < this.leadingIndexes.length) {
+                       System.arraycopy(this.leadingNodes, 0, this.leadingNodes = new ASTNode[leadingCount], 0, leadingCount);
+                       System.arraycopy(this.leadingIndexes, 0, this.leadingIndexes= new long[leadingCount], 0, leadingCount);
+               }
+               
+               // Reduce trailing arrays if necessary
+               if (this.trailingPtr >= 0) {
+                       // remove last remaining unresolved nodes
+                       while (this.trailingIndexes[this.trailingPtr] == -1) {
+                               this.trailingPtr--;
+                               if (this.trailingPtr < 0) {
+                                       this.trailingIndexes = null;
+                                       this.trailingNodes = null;
+                                       break;
+                               }
+                       }
+
+                       // reduce array size
+                       int trailingCount = this.trailingPtr + 1;
+                       if (trailingCount > 0 && trailingCount < this.trailingIndexes.length) {
+                               System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[trailingCount], 0, trailingCount);
+                               System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes= new long[trailingCount], 0, trailingCount);
+                       }
+               }
+
+               // Release scanner as it's only used during unit visit
+               this.scanner = null;
+       }
+
+       /**
+        * Search and store node leading comments. Comments are searched in position range
+        * from previous extended position to node start position. If one or several comment are found,
+        * returns first comment start position, otherwise returns node start position.
+        * <p>
+        * Starts to search for first comment before node start position and return if none was found...
+        *</p><p>
+        * When first comment is found before node, goes up in comment list until one of
+        * following conditions becomes true:
+        * <ol>
+        *      <li>comment end is before previous end</li>
+        *      <li>comment start and previous end is on the same line but not on same line of node start</li>
+        *      <li>there's other than white characters between current node and comment</li>
+        *      <li>there's more than 1 line between current node and comment</li>
+        * </ol>
+        * If some comment have been found, then no token should be on
+        * on the same line before, so remove all comments which do not verify this assumption.
+        * </p><p>
+        * If finally there's leading still comments, then stores indexes of the first and last one
+        * in leading comments table.
+        */
+       int storeLeadingComments(ASTNode node, int previousEnd, int[] parentLineRange) {
+               // Init extended position
+               int nodeStart = node.getStartPosition();
+               int extended = nodeStart;
+               
+               // Get line of node start position
+               int previousEndLine = getLineNumber(previousEnd, parentLineRange);
+               int nodeStartLine = getLineNumber(nodeStart, parentLineRange);
+               
+               // Find first comment index
+               int idx = getCommentIndex(0, nodeStart, -1);
+               if (idx == -1) {
+                       return nodeStart;
+               }
+               
+               // Look after potential comments
+               int startIdx = -1;
+               int endIdx = idx;
+               int previousStart = nodeStart;
+               while (idx >= 0 && previousStart  >= previousEnd) {
+                       // Verify for each comment that there's only white spaces between end and start of {following comment|node}
+                       Comment comment = this.comments[idx];
+                       int commentStart = comment.getStartPosition();
+                       int end = commentStart+comment.getLength()-1;
+                       int commentLine = getLineNumber(commentStart, parentLineRange);
+                       if (end <= previousEnd || (commentLine == previousEndLine && commentLine != nodeStartLine)) {
+                               // stop search on condition 1) and 2)
+                               break;
+                       } else if ((end+1) < previousStart) { // may be equals => then no scan is necessary
+                               this.scanner.resetTo(end+1, previousStart);
+                               try {
+                                       int token = this.scanner.getNextToken();
+                                       if (token != TerminalTokens.TokenNameWHITESPACE || this.scanner.currentPosition != previousStart) {
+                                               // stop search on condition 3)
+                                               // if first comment fails, then there's no extended position in fact
+                                               if (idx == endIdx) {
+                                                       return nodeStart;
+                                               }
+                                               break;
+                                       }
+                               } catch (InvalidInputException e) {
+                                       // Should not happen, but return no extended position...
+                                       return nodeStart;
+                               }
+                               // verify that there's no more than one line between node/comments
+                               char[] gap = this.scanner.getCurrentIdentifierSource();
+                               int nbrLine = 0;
+                               int pos = -1;
+                               while ((pos=CharOperation.indexOf('\n', gap,pos+1)) >= 0) {
+                                       nbrLine++;
+                               }
+                               if (nbrLine > 1) {
+                                       // stop search on condition 4)
+                                       break;
+                               }
+                       }
+                       // Store previous infos
+                       previousStart = commentStart;
+                       startIdx = idx--;
+               }
+               if (startIdx != -1) {
+                       // Verify that there's no token on the same line before first leading comment
+                       int commentStart = this.comments[startIdx].getStartPosition();
+                       if (previousEnd < commentStart && previousEndLine != nodeStartLine) {
+                               int lastTokenEnd = previousEnd;
+                               this.scanner.resetTo(previousEnd, commentStart);
+                               try {
+                                       while (this.scanner.currentPosition < commentStart) {
+                                               if (this.scanner.getNextToken() != TerminalTokens.TokenNameWHITESPACE) {
+                                                       lastTokenEnd =  this.scanner.getCurrentTokenEndPosition();
+                                               }
+                                       }
+                               } catch (InvalidInputException e) {
+                                       // do nothing
+                               }
+                               int lastTokenLine = getLineNumber(lastTokenEnd, parentLineRange);
+                               int length = this.comments.length;
+                               while (startIdx<length && lastTokenLine == getLineNumber(this.comments[startIdx].getStartPosition(), parentLineRange) && nodeStartLine != lastTokenLine) {
+                                       startIdx++;
+                               }
+                       }
+                       // Store leading comments indexes
+                       if (startIdx <= endIdx) {
+                               if (++this.leadingPtr == 0) {
+                                       this.leadingNodes = new ASTNode[STORAGE_INCREMENT];
+                                       this.leadingIndexes = new long[STORAGE_INCREMENT];
+                               } else if (this.leadingPtr == this.leadingNodes.length) {
+                                       int newLength = (this.leadingPtr*3/2)+STORAGE_INCREMENT;
+                                       System.arraycopy(this.leadingNodes, 0, this.leadingNodes = new ASTNode[newLength], 0, this.leadingPtr);
+                                       System.arraycopy(this.leadingIndexes, 0, this.leadingIndexes = new long[newLength], 0, this.leadingPtr);
+                               }
+                               this.leadingNodes[this.leadingPtr] = node;
+                               this.leadingIndexes[this.leadingPtr] = (((long)startIdx)<<32) + endIdx;
+                               extended = this.comments[endIdx].getStartPosition();
+                       }
+               }
+               return extended;
+       }
+
+       /**
+        * Search and store node trailing comments. Comments are searched in position range
+        * from node end position to specified next start. If one or several comment are found,
+        * returns last comment end position, otherwise returns node end position.
+        * <p>
+        * Starts to search for first comment after node end position and return if none was found...
+        *</p><p>
+        * When first comment is found after node, goes down in comment list until one of
+        * following conditions becomes true:
+        * <ol>
+        *      <li>comment start is after next start</li>
+        *      <li>there's other than white characters between current node and comment</li>
+        *      <li>there's more than 1 line between current node and comment</li>
+        *</ol>
+        * If at least potential comments have been found, then all of them has to be separated
+        * from following node. So, remove all comments which do not verify this assumption.
+        * Note that this verification is not applicable on last node.
+        * </p><p>
+        * If finally there's still trailing comments, then stores indexes of the first and last one
+        * in trailing comments table.
+        */
+       int storeTrailingComments(ASTNode node, int nextStart,  boolean lastChild, int[] parentLineRange) {
+
+               // Init extended position
+               int nodeEnd = node.getStartPosition()+node.getLength()-1;
+               if (nodeEnd == nextStart) {
+                       // special case for last child of its parent
+                       if (++this.trailingPtr == 0) {
+                               this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
+                               this.trailingIndexes = new long[STORAGE_INCREMENT];
+                               this.lastTrailingPtr = -1;
+                       } else if (this.trailingPtr == this.trailingNodes.length) {
+                               int newLength = (this.trailingPtr*3/2)+STORAGE_INCREMENT;
+                               System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr);
+                               System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr);
+                       }
+                       this.trailingNodes[this.trailingPtr] = node;
+                       this.trailingIndexes[this.trailingPtr] = -1;
+                       return nodeEnd;
+               }
+               int extended = nodeEnd;
+               
+               // Get line number
+               int nodeEndLine = getLineNumber(nodeEnd, parentLineRange);
+               
+               // Find comments range index
+               int idx = getCommentIndex(0, nodeEnd, 1);
+               if (idx == -1) {
+                       return nodeEnd;
+               }
+
+               // Look after potential comments
+               int startIdx = idx;
+               int endIdx = -1;
+               int length = this.comments.length;
+               int commentStart = extended+1;
+               int previousEnd = nodeEnd+1;
+               int sameLineIdx = -1;
+               while (idx<length && commentStart < nextStart) {
+                       // get comment and leave if next starting position has been reached
+                       Comment comment = this.comments[idx];
+                       commentStart = comment.getStartPosition();
+                       // verify that there's nothing else than white spaces between node/comments
+                       if (commentStart >= nextStart) {
+                               // stop search on condition 1)
+                               break;
+                       } else if (previousEnd < commentStart) {
+                               this.scanner.resetTo(previousEnd, commentStart);
+                               try {
+                                       int token = this.scanner.getNextToken();
+                                       if (token != TerminalTokens.TokenNameWHITESPACE || this.scanner.currentPosition != commentStart) {
+                                               // stop search on condition 2)
+                                               // if first index fails, then there's no extended position in fact...
+                                               if (idx == startIdx) {
+                                                       return nodeEnd;
+                                               }
+                                               // otherwise we get the last index of trailing comment => break
+                                               break;
+                                       }
+                               } catch (InvalidInputException e) {
+                                       // Should not happen, but return no extended position...
+                                       return nodeEnd;
+                               }
+                               // verify that there's no more than one line between node/comments
+                               char[] gap = this.scanner.getCurrentIdentifierSource();
+                               int nbrLine = 0;
+                               int pos = -1;
+                               while ((pos=CharOperation.indexOf('\n', gap,pos+1)) >= 0) {
+                                       nbrLine++;
+                               }
+                               if (nbrLine > 1) {
+                                       // stop search on condition 3)
+                                       break;
+                               }
+                       }
+                       // Store index if we're on the same line than node end
+                       int commentLine = getLineNumber(commentStart, parentLineRange);
+                       if (commentLine == nodeEndLine) {
+                               sameLineIdx = idx;
+                       }
+                       // Store previous infos
+                       previousEnd = commentStart+comment.getLength();
+                       endIdx = idx++;
+               }
+               if (endIdx != -1) {
+                       // Verify that following node start is separated
+                       if (!lastChild) {
+                               int nextLine = getLineNumber(nextStart, parentLineRange);
+                               int previousLine = getLineNumber(previousEnd, parentLineRange);
+                               if((nextLine - previousLine) <= 1) {
+                                       if (sameLineIdx == -1) return nodeEnd;
+                                       endIdx = sameLineIdx;
+                               }
+                       }
+                       // Store trailing comments indexes
+                       if (++this.trailingPtr == 0) {
+                               this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
+                               this.trailingIndexes = new long[STORAGE_INCREMENT];
+                               this.lastTrailingPtr = -1;
+                       } else if (this.trailingPtr == this.trailingNodes.length) {
+                               int newLength = (this.trailingPtr*3/2)+STORAGE_INCREMENT;
+                               System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr);
+                               System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr);
+                       }
+                       this.trailingNodes[this.trailingPtr] = node;
+                       long nodeRange = (((long)startIdx)<<32) + endIdx;
+                       this.trailingIndexes[this.trailingPtr] = nodeRange;
+                       // Compute new extended end
+                       extended = this.comments[endIdx].getStartPosition()+this.comments[endIdx].getLength()-1;
+                       // Look for children unresolved extended end
+                       ASTNode previousNode = node;
+                       int ptr = this.trailingPtr - 1; // children extended end were stored before
+                       while (ptr >= 0) {
+                               long range = this.trailingIndexes[ptr];
+                               if (range != -1) break; // there's no more unresolved nodes
+                               ASTNode unresolved = this.trailingNodes[ptr];
+                               if (previousNode != unresolved.getParent()) break; // we're no longer in node ancestor hierarchy
+                               this.trailingIndexes[ptr] = nodeRange;
+                               previousNode = unresolved;
+                               ptr--; // get previous node
+                       }
+                       // Remove remaining unresolved nodes
+                       if (ptr > this.lastTrailingPtr) {
+                               int offset = ptr - this.lastTrailingPtr;
+                               for (int i=ptr+1; i<=this.trailingPtr; i++) {
+                                       this.trailingNodes[i-offset] = this.trailingNodes[i];
+                                       this.trailingIndexes[i-offset] = this.trailingIndexes[i];
+                               }
+                               this.trailingPtr -= offset;
+                       }
+                       this.lastTrailingPtr = this.trailingPtr;
+               }
+               return extended;
+       }
+
+       class CommentMapperVisitor extends DefaultASTVisitor {
+
+               ASTNode topSiblingParent = null;
+               ASTNode[] siblings = new ASTNode[10];
+               int[][] parentLineRange = new int[10][];
+               int siblingPtr = -1;
+
+               protected boolean visitNode(ASTNode node) {
+
+                       // Get default previous end
+                       ASTNode parent = node.getParent();
+                       int previousEnd = parent.getStartPosition();
+                       
+                       // Look for sibling node
+                       ASTNode sibling = parent == this.topSiblingParent ? (ASTNode) this.siblings[this.siblingPtr] : null;
+                       if (sibling != null) {
+                               // Found one previous sibling, so compute its trailing comments using current node start position
+                               try {
+                                       previousEnd = storeTrailingComments(sibling, node.getStartPosition(), false, this.parentLineRange[this.siblingPtr]);
+                               } catch (Exception ex) {
+                                       // Give up extended ranges at this level if unexpected exception happens...
+                               }
+                       }
+
+                       // Stop visit for malformed node (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84049)
+                       if ((node.typeAndFlags & ASTNode.MALFORMED) != 0) {
+                               return false;
+                       }
+
+                       // Compute leading comments for current node
+                       int[] previousLineRange = this.siblingPtr > -1 ? this.parentLineRange[this.siblingPtr] : new int[] {1, DefaultCommentMapper.this.scanner.linePtr+1};
+                       try {
+                               storeLeadingComments(node, previousEnd, previousLineRange);
+                       } catch (Exception ex) {
+                               // Give up extended ranges at this level if unexpected exception happens...
+                       }
+                       
+                       // Store current node as waiting sibling for its parent
+                       if (this.topSiblingParent != parent) {
+                               if (this.siblings.length == ++this.siblingPtr) {
+                                       System.arraycopy(this.siblings, 0, this.siblings = new ASTNode[this.siblingPtr*2], 0, this.siblingPtr);
+                                       System.arraycopy(this.parentLineRange, 0, this.parentLineRange = new int[this.siblingPtr*2][], 0, this.siblingPtr);
+                               }
+                               if (this.topSiblingParent == null) {
+                                       // node is a CompilationUnit
+                                       this.parentLineRange[this.siblingPtr] = previousLineRange;
+                               } else {
+                                       int parentStart = parent.getStartPosition();
+                                       int firstLine = getLineNumber(parentStart, previousLineRange);
+                                       int lastLine = getLineNumber(parentStart + parent.getLength() - 1, previousLineRange);
+                                       if (this.parentLineRange[this.siblingPtr] == null) {
+                                               this.parentLineRange[this.siblingPtr] = new int[] {firstLine, lastLine};
+                                       } else {
+                                               int[] lineRange = this.parentLineRange[this.siblingPtr];
+                                               lineRange[0] = firstLine;
+                                               lineRange[1] = lastLine;
+                                       }
+                               }
+                               this.topSiblingParent = parent;
+                       }
+                       this.siblings[this.siblingPtr] = node;
+
+                       // We're always ok to visit sub-levels
+                       return true;
+               }
+               
+               protected void endVisitNode(ASTNode node) {
+
+                       // Look if a child node is waiting for trailing comments computing
+                       ASTNode sibling = this.topSiblingParent == node ? (ASTNode) this.siblings[this.siblingPtr] : null;
+                       if (sibling != null) {
+                               try {
+                                       storeTrailingComments(sibling, node.getStartPosition()+node.getLength()-1, true, this.parentLineRange[this.siblingPtr]);
+                               } catch (Exception ex) {
+                                       // Give up extended ranges at this level if unexpected exception happens...
+                               }
+                       }
+                       // Remove sibling if needed
+                       if (this.topSiblingParent != null /*not a CompilationUnit*/
+                                       && this.topSiblingParent == node) {
+                               this.siblingPtr--;
+                               this.topSiblingParent = node.getParent();
+                       }
+               }
+
+               public boolean visit ( CompilationUnit node) {
+                       // do nothing special, just go down in sub-levels
+                       return true;
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultValuePairBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DefaultValuePairBinding.java
new file mode 100644 (file)
index 0000000..450215f
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 BEA Systems, Inc.
+ * 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:
+ *    tyeung@bea.com - initial API and implementation
+ *    IBM Corporation - implemented methods from IBinding
+ *    IBM Corporation - renamed from ResolvedDefaultValuePair to DefaultValuePairBinding
+ *******************************************************************************/
+package net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.dom.BindingResolver;
+import net.sourceforge.phpdt.core.dom.IMethodBinding;
+
+/**
+ * Member value pair which compose of default values.
+ */
+class DefaultValuePairBinding extends MemberValuePairBinding {
+
+       private net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding method;
+
+       DefaultValuePairBinding(net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding binding, BindingResolver resolver) {
+               super(null, resolver);
+               this.method = binding;
+               this.value = MemberValuePairBinding.buildDOMValue(binding.getDefaultValue(), resolver);
+       }
+
+       public IMethodBinding getMethodBinding() {
+               return this.bindingResolver.getMethodBinding(this.method);
+       }
+
+       public String getName() {
+               return new String(this.method.selector);
+       }
+
+       public Object getValue() {
+               return this.value;
+       }
+
+       public boolean isDefault() {
+               return true;
+       }
+
+       public boolean isDeprecated() {
+               return this.method.isDeprecated();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DoStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DoStatement.java
new file mode 100644 (file)
index 0000000..4bf993e
--- /dev/null
@@ -0,0 +1,274 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Do statement AST node type.
+ *
+ * <pre>
+ * DoStatement:
+ *    <b>do</b> Statement <b>while</b> <b>(</b> Expression <b>)</b> <b>;</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class DoStatement extends Statement {
+
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(DoStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "body" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor BODY_PROPERTY = 
+               new ChildPropertyDescriptor(DoStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(3);
+               createPropertyList(DoStatement.class, properyList);
+               addProperty(EXPRESSION_PROPERTY, properyList);
+               addProperty(BODY_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 expression; lazily initialized; defaults to an unspecified, but 
+        * legal, expression.
+        */
+       private Expression expression = null;
+
+       /**
+        * The body statement; lazily initialized; defaults to an empty block.
+        */
+       private Statement body = null;
+
+       /**
+        * Creates a new unparented do statement node owned by the given 
+        * AST. By default, the expresssion is unspecified, but legal,
+        * and the body statement is an empty block.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       DoStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == BODY_PROPERTY) {
+                       if (get) {
+                               return getBody();
+                       } else {
+                               setBody((Statement) 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.
+        */
+       final int getNodeType0() {
+               return DO_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               DoStatement result = new DoStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setExpression((Expression) getExpression().clone(target));
+               result.setBody((Statement) getBody().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getBody());
+                       acceptChild(visitor, getExpression());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this do statement.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new SimpleName(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.expression;
+       }
+       
+       /**
+        * Sets the expression of this do statement.
+        * 
+        * @param expression the expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the body of this do statement.
+        * 
+        * @return the body statement node
+        */ 
+       public Statement getBody() {
+               if (this.body == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.body == null) {
+                                       preLazyInit();
+                                       this.body = new Block(this.ast);
+                                       postLazyInit(this.body, BODY_PROPERTY);
+                               }
+                       }
+               }
+               return this.body;
+       }
+       
+       /**
+        * Sets the body of this do statement.
+        * <p>
+        * Special note: The Java language does not allow a local variable declaration
+        * to appear as the body of a do statement (they may only appear within a
+        * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+        * as the body of a <code>DoStatement</code>. To get something that will
+        * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+        * inside a <code>Block</code>.
+        * </p>
+        * 
+        * @param statement the body statement node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setBody(Statement statement) {
+               if (statement == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.body;
+               preReplaceChild(oldChild, statement, BODY_PROPERTY);
+               this.body = statement;
+               postReplaceChild(oldChild, statement, BODY_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.expression == null ? 0 : getExpression().treeSize())
+                       + (this.body == null ? 0 : getBody().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DocCommentParser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/DocCommentParser.java
new file mode 100644 (file)
index 0000000..98c7b06
--- /dev/null
@@ -0,0 +1,742 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
+import net.sourceforge.phpdt.internal.compiler.parser.AbstractCommentParser;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.ScannerHelper;
+import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Internal parser used for decoding doc comments.
+ * 
+ * @since 3.0
+ */
+class DocCommentParser extends AbstractCommentParser {
+
+       private Javadoc docComment;
+       private AST ast;
+
+       DocCommentParser(AST ast, Scanner scanner, boolean check) {
+               super(null);
+               this.ast = ast;
+               this.scanner = scanner;
+               this.sourceLevel = this.ast.apiLevel() >= AST.JLS3 ? ClassFileConstants.JDK1_5 : ClassFileConstants.JDK1_3;
+               this.checkDocComment = check;
+               this.kind = DOM_PARSER | TEXT_PARSE;
+       }
+
+       /* (non-Javadoc)
+        * Returns true if tag @deprecated is present in annotation.
+        * 
+        * If annotation checking is enabled, will also construct an Annotation node, which will be stored into Parser.annotation
+        * slot for being consumed later on.
+        */
+       public Javadoc parse(int[] positions) {
+               return parse(positions[0], positions[1]-positions[0]);
+       }
+       public Javadoc parse(int start, int length) {
+
+               // Init
+               this.source = this.scanner.source;
+               this.lineEnds = this.scanner.lineEnds;
+               this.docComment = new Javadoc(this.ast);
+               
+               // Parse
+               if (this.checkDocComment) {
+                       this.javadocStart = start;
+                       this.javadocEnd = start+length-1;
+                       this.firstTagPosition = this.javadocStart;
+                       commentParse();
+               }
+               this.docComment.setSourceRange(start, length);
+               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                       setComment(start, length);  // backward compatibility
+               }
+               return this.docComment;
+       }
+
+       /**
+        * Sets the comment starting at the given position and with the given length.
+        * <p>
+        * Note the only purpose of this method is to hide deprecated warnings.
+        * @deprecated mark deprecated to hide deprecated usage
+        */
+       private void setComment(int start, int length) {
+               this.docComment.setComment(new String(this.source, start, length));
+       }
+
+       public String toString() {
+               StringBuffer buffer = new StringBuffer();
+               buffer.append("javadoc: ").append(this.docComment).append("\n");        //$NON-NLS-1$ //$NON-NLS-2$
+               buffer.append(super.toString());
+               return buffer.toString();
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createArgumentReference(char[], java.lang.Object, int)
+        */
+       protected Object createArgumentReference(char[] name, int dim, boolean isVarargs, Object typeRef, long[] dimPositions, long argNamePos) throws InvalidInputException {
+               try {
+                       MethodRefParameter argument = this.ast.newMethodRefParameter();
+                       ASTNode node = (ASTNode) typeRef;
+                       int argStart = node.getStartPosition();
+                       int argEnd = node.getStartPosition()+node.getLength()-1;
+                       if (dim > 0) argEnd = (int) dimPositions[dim-1];
+                       if (argNamePos >= 0) argEnd = (int) argNamePos;
+                       if (name.length != 0) {
+                               final SimpleName argName = new SimpleName(this.ast);
+                               argName.internalSetIdentifier(new String(name));
+                               argument.setName(argName);
+                               int argNameStart = (int) (argNamePos >>> 32);
+                               argName.setSourceRange(argNameStart, argEnd-argNameStart+1);
+                       }
+                       Type argType = null;
+                       if (node.getNodeType() == ASTNode.PRIMITIVE_TYPE) {
+                               argType = (PrimitiveType) node;
+//                             if (dim > 0) {
+//                                     argType = this.ast.newArrayType(argType, dim);
+//                                     argType.setSourceRange(argStart, ((int) dimPositions[dim-1])-argStart+1);
+//                             }
+                       } else {
+                               Name argTypeName = (Name) node;
+                               argType = this.ast.newSimpleType(argTypeName);
+                               argType.setSourceRange(argStart, node.getLength());
+                       }
+                       if (dim > 0 && !isVarargs) {
+                               for (int i=0; i<dim; i++) {
+                                       argType = this.ast.newArrayType(argType);
+                                       argType.setSourceRange(argStart, ((int) dimPositions[i])-argStart+1);
+                               }
+                       }
+                       argument.setType(argType);
+                       argument.setSourceRange(argStart, argEnd - argStart + 1);
+                       return argument;
+               }
+               catch (ClassCastException ex) {
+                               throw new InvalidInputException();
+               }
+       }
+/* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createFieldReference()
+        */
+       protected Object createFieldReference(Object receiver) throws InvalidInputException {
+               try {
+                       MemberRef fieldRef = this.ast.newMemberRef();
+                       SimpleName fieldName = new SimpleName(this.ast);
+                       fieldName.internalSetIdentifier(new String(this.identifierStack[0]));
+                       fieldRef.setName(fieldName);
+                       int start = (int) (this.identifierPositionStack[0] >>> 32);
+                       int end = (int) this.identifierPositionStack[0];
+                       fieldName.setSourceRange(start, end - start + 1);
+                       if (receiver == null) {
+                               start = this.memberStart;
+                               fieldRef.setSourceRange(start, end - start + 1);
+                       } else {
+                               Name typeRef = (Name) receiver;
+                               fieldRef.setQualifier(typeRef);
+                               start = typeRef.getStartPosition();
+                               end = fieldName.getStartPosition()+fieldName.getLength()-1;
+                               fieldRef.setSourceRange(start, end-start+1);
+                       }
+                       return fieldRef;
+               }
+               catch (ClassCastException ex) {
+                               throw new InvalidInputException();
+               }
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createMethodReference(java.lang.Object[])
+        */
+       protected Object createMethodReference(Object receiver, List arguments) throws InvalidInputException {
+               try {
+                       // Create method ref
+                       MethodRef methodRef = this.ast.newMethodRef();
+                       SimpleName methodName = new SimpleName(this.ast);
+                       int length = this.identifierLengthStack[0] - 1; // may be > 0 for member class constructor reference
+                       methodName.internalSetIdentifier(new String(this.identifierStack[length]));
+                       methodRef.setName(methodName);
+                       int start = (int) (this.identifierPositionStack[length] >>> 32);
+                       int end = (int) this.identifierPositionStack[length];
+                       methodName.setSourceRange(start, end - start + 1);
+                       // Set qualifier
+                       if (receiver == null) {
+                               start = this.memberStart;
+                               methodRef.setSourceRange(start, end - start + 1);
+                       } else {
+                               Name typeRef = (Name) receiver;
+                               methodRef.setQualifier(typeRef);
+                               start = typeRef.getStartPosition();
+                       }
+                       // Add arguments
+                       if (arguments != null) {
+                               Iterator parameters = arguments.listIterator();
+                               while (parameters.hasNext()) {
+                                       MethodRefParameter param = (MethodRefParameter) parameters.next();
+                                       methodRef.parameters().add(param);
+                               }
+                       }
+                       methodRef.setSourceRange(start, this.scanner.getCurrentTokenEndPosition()-start+1);
+                       return methodRef;
+               }
+               catch (ClassCastException ex) {
+                               throw new InvalidInputException();
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createTag()
+        */
+       protected void createTag() {
+               TagElement tagElement = this.ast.newTagElement();
+               int position = this.scanner.currentPosition;
+               this.scanner.resetTo(this.tagSourceStart, this.tagSourceEnd);
+               StringBuffer tagName = new StringBuffer();
+               int start = this.tagSourceStart;
+               this.scanner.getNextChar();
+               while (this.scanner.currentPosition <= (this.tagSourceEnd+1)) {
+                       tagName.append(this.scanner.currentCharacter);
+                       this.scanner.getNextChar();
+               }
+               tagElement.setTagName(tagName.toString());
+               if (this.inlineTagStarted) {
+                       start = this.inlineTagStart;
+                       TagElement previousTag = null;
+                       if (this.astPtr == -1) {
+                               previousTag = this.ast.newTagElement();
+                               previousTag.setSourceRange(start, this.tagSourceEnd-start+1);
+                               pushOnAstStack(previousTag, true);
+                       } else {
+                               previousTag = (TagElement) this.astStack[this.astPtr];
+                       }
+                       int previousStart = previousTag.getStartPosition();
+                       previousTag.fragments().add(tagElement);
+                       previousTag.setSourceRange(previousStart, this.tagSourceEnd-previousStart+1);
+               } else {
+                       pushOnAstStack(tagElement, true);
+               }
+               tagElement.setSourceRange(start, this.tagSourceEnd-start+1);
+               this.scanner.resetTo(position, this.javadocEnd);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createTypeReference()
+        */
+       protected Object createTypeReference(int primitiveToken) {
+               int size = this.identifierLengthStack[this.identifierLengthPtr];
+               String[] identifiers = new String[size];
+               int pos = this.identifierPtr - size + 1;
+               for (int i = 0; i < size; i++) {
+                       identifiers[i] = new String(this.identifierStack[pos+i]);
+               }
+               ASTNode typeRef = null;
+               if (primitiveToken == -1) {
+                       typeRef = this.ast.internalNewName(identifiers);
+               } else {
+                       switch (primitiveToken) {
+                               case TerminalTokens.TokenNamevoid :
+                                       typeRef = this.ast.newPrimitiveType(PrimitiveType.VOID);
+                                       break;
+                               case TerminalTokens.TokenNameboolean :
+                                       typeRef = this.ast.newPrimitiveType(PrimitiveType.BOOLEAN);
+                                       break;
+                               case TerminalTokens.TokenNamebyte :
+                                       typeRef = this.ast.newPrimitiveType(PrimitiveType.BYTE);
+                                       break;
+                               case TerminalTokens.TokenNamechar :
+                                       typeRef = this.ast.newPrimitiveType(PrimitiveType.CHAR);
+                                       break;
+                               case TerminalTokens.TokenNamedouble :
+                                       typeRef = this.ast.newPrimitiveType(PrimitiveType.DOUBLE);
+                                       break;
+                               case TerminalTokens.TokenNamefloat :
+                                       typeRef = this.ast.newPrimitiveType(PrimitiveType.FLOAT);
+                                       break;
+                               case TerminalTokens.TokenNameint :
+                                       typeRef = this.ast.newPrimitiveType(PrimitiveType.INT);
+                                       break;
+                               case TerminalTokens.TokenNamelong :
+                                       typeRef = this.ast.newPrimitiveType(PrimitiveType.LONG);
+                                       break;
+                               case TerminalTokens.TokenNameshort :
+                                       typeRef = this.ast.newPrimitiveType(PrimitiveType.SHORT);
+                                       break;
+                               default:
+                                       // should not happen
+                                       return null;
+                       }
+               }
+               // Update ref for whole name
+               int start = (int) (this.identifierPositionStack[pos] >>> 32);
+//             int end = (int) this.identifierPositionStack[this.identifierPtr];
+//             typeRef.setSourceRange(start, end-start+1);
+               // Update references of each simple name
+               if (size > 1) {
+                       Name name = (Name)typeRef;
+                       int nameIndex = size;
+                       for (int i=this.identifierPtr; i>pos; i--, nameIndex--) {
+                               int s = (int) (this.identifierPositionStack[i] >>> 32);
+                               int e = (int) this.identifierPositionStack[i];
+                               name.index = nameIndex;
+                               SimpleName simpleName = ((QualifiedName)name).getName();
+                               simpleName.index = nameIndex;
+                               simpleName.setSourceRange(s, e-s+1);
+                               name.setSourceRange(start, e-start+1);
+                               name =  ((QualifiedName)name).getQualifier();
+                       }
+                       int end = (int) this.identifierPositionStack[pos];
+                       name.setSourceRange(start, end-start+1);
+                       name.index = nameIndex;
+               } else {
+                       int end = (int) this.identifierPositionStack[pos];
+                       typeRef.setSourceRange(start, end-start+1);
+               }
+               return typeRef;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#parseIdentifierTag(boolean)
+        */
+       protected boolean parseIdentifierTag(boolean report) {
+               if (super.parseIdentifierTag(report)) {
+                       createTag();
+                       this.index = this.tagSourceEnd+1;
+                       this.scanner.resetTo(this.index, this.javadocEnd);
+                       return true;
+               }
+               return false;
+       }
+
+       /*
+        * Parse @return tag declaration
+        */
+       protected boolean parseReturn() {
+               createTag();
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#parseTag(int)
+        */
+       protected boolean parseTag(int previousPosition) throws InvalidInputException {
+               
+               // Read tag name
+               int currentPosition = this.index;
+               int token = readTokenAndConsume();
+               char[] tagName = CharOperation.NO_CHAR;
+               if (currentPosition == this.scanner.startPosition) {
+                       this.tagSourceStart = this.scanner.getCurrentTokenStartPosition();
+                       this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+                       tagName = this.scanner.getCurrentIdentifierSource();
+               } else {
+                       this.tagSourceEnd = currentPosition-1;
+               }
+
+               // Try to get tag name other than java identifier
+               // (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51660)
+               if (this.scanner.currentCharacter != ' ' && !ScannerHelper.isWhitespace(this.scanner.currentCharacter)) {
+                       tagNameToken: while (token != TerminalTokens.TokenNameEOF && this.index < this.scanner.eofPosition) {
+                               int length = tagName.length;
+                               // !, ", #, %, &, ', -, :, <, >, * chars and spaces are not allowed in tag names
+                               switch (this.scanner.currentCharacter) {
+                                       case '}':
+                                       case '*': // break for '*' as this is perhaps the end of comment (bug 65288)
+                                       case '!':
+                                       case '#':
+                                       case '%':
+                                       case '&':
+                                       case '\'':
+                                       case '"':
+                                       case ':':
+                                       case '<':
+                                       case '>':
+                                               break tagNameToken;
+                                       case '-': // allowed in tag names as this character is often used in doclets (bug 68087)
+                                               System.arraycopy(tagName, 0, tagName = new char[length+1], 0, length);
+                                               tagName[length] = this.scanner.currentCharacter;
+                                               break;
+                                       default:
+                                               if (this.scanner.currentCharacter == ' ' || ScannerHelper.isWhitespace(this.scanner.currentCharacter)) {
+                                                       break tagNameToken;
+                                               }
+                                               token = readTokenAndConsume();
+                                               char[] ident = this.scanner.getCurrentIdentifierSource();
+                                               System.arraycopy(tagName, 0, tagName = new char[length+ident.length], 0, length);
+                                               System.arraycopy(ident, 0, tagName, length, ident.length);
+                                               break;
+                               }
+                               this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+                               this.scanner.getNextChar();
+                               this.index = this.scanner.currentPosition;
+                       }
+               }
+               int length = tagName.length;
+               this.index = this.tagSourceEnd+1;
+               this.scanner.currentPosition = this.tagSourceEnd+1;
+               this.tagSourceStart = previousPosition;
+
+               // tage name may be empty (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=125903)
+               if (tagName.length == 0) {
+                       return false;
+               }
+
+               // Decide which parse to perform depending on tag name
+               this.tagValue = NO_TAG_VALUE;
+               boolean valid = true;
+               switch (token) {
+                       case TerminalTokens.TokenNameIdentifier :
+                               switch (tagName[0]) {
+                                       case 'c':
+                                               if (length == TAG_CATEGORY_LENGTH && CharOperation.equals(TAG_CATEGORY, tagName)) {
+                                                       this.tagValue = TAG_CATEGORY_VALUE;
+                                                       valid = parseIdentifierTag(false); // TODO (frederic) reconsider parameter value when @category will be significant in spec
+                                               } else {
+                                                       this.tagValue = TAG_OTHERS_VALUE;
+                                                       createTag();
+                                               }
+                                               break;
+                                       case 'd':
+                                               if (length == TAG_DEPRECATED_LENGTH && CharOperation.equals(TAG_DEPRECATED, tagName)) {
+                                                       this.deprecated = true;
+                                                       this.tagValue = TAG_DEPRECATED_VALUE;
+                                               } else {
+                                                       this.tagValue = TAG_OTHERS_VALUE;
+                                               }
+                                               createTag();
+                                       break;
+                                       case 'i':
+                                               if (length == TAG_INHERITDOC_LENGTH && CharOperation.equals(TAG_INHERITDOC, tagName)) {
+                                                       // inhibits inherited flag when tags have been already stored
+                                                       // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51606
+                                                       // Note that for DOM_PARSER, nodes stack may be not empty even no '@' tag
+                                                       // was encountered in comment. But it cannot be the case for COMPILER_PARSER
+                                                       // and so is enough as it is only this parser which signals the missing tag warnings...
+                                                       if (this.astPtr==-1) {
+                                                               this.inheritedPositions = (((long) this.tagSourceStart) << 32) + this.tagSourceEnd;
+                                                       }
+                                                       this.tagValue = TAG_INHERITDOC_VALUE;
+                                               } else {
+                                                       this.tagValue = TAG_OTHERS_VALUE;
+                                               }
+                                               createTag();
+                                       break;
+                                       case 'p':
+                                               if (length == TAG_PARAM_LENGTH && CharOperation.equals(TAG_PARAM, tagName)) {
+                                                       this.tagValue = TAG_PARAM_VALUE;
+                                                       valid = parseParam();
+                                               } else {
+                                                       this.tagValue = TAG_OTHERS_VALUE;
+                                                       createTag();
+                                               }
+                                       break;
+                                       case 'e':
+                                               if (length == TAG_EXCEPTION_LENGTH && CharOperation.equals(TAG_EXCEPTION, tagName)) {
+                                                       this.tagValue = TAG_EXCEPTION_VALUE;
+                                                       valid = parseThrows();
+                                               } else {
+                                                       this.tagValue = TAG_OTHERS_VALUE;
+                                                       createTag();
+                                               }
+                                       break;
+                                       case 's':
+                                               if (length == TAG_SEE_LENGTH && CharOperation.equals(TAG_SEE, tagName)) {
+                                                       this.tagValue = TAG_SEE_VALUE;
+                                                       if (this.inlineTagStarted) {
+                                                               // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+                                                               // Cannot have @see inside inline comment
+                                                               valid = false;
+                                                       } else {
+                                                               valid = parseReference();
+                                                       }
+                                               } else {
+                                                       this.tagValue = TAG_OTHERS_VALUE;
+                                                       createTag();
+                                               }
+                                       break;
+                                       case 'l':
+                                               if (length == TAG_LINK_LENGTH && CharOperation.equals(TAG_LINK, tagName)) {
+                                                       this.tagValue = TAG_LINK_VALUE;
+                                               } else if (length == TAG_LINKPLAIN_LENGTH && CharOperation.equals(TAG_LINKPLAIN, tagName)) {
+                                                       this.tagValue = TAG_LINKPLAIN_VALUE;
+                                               }
+                                               if (this.tagValue != NO_TAG_VALUE)  {
+                                                       if (this.inlineTagStarted) {
+                                                               valid = parseReference();
+                                                       } else {
+                                                               // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
+                                                               // Cannot have @link outside inline comment
+                                                               valid = false;
+                                                       }
+                                               } else {
+                                                       this.tagValue = TAG_OTHERS_VALUE;
+                                                       createTag();
+                                               }
+                                       break;
+                                       case 'v':
+                                               if (this.sourceLevel >= ClassFileConstants.JDK1_5 && length == TAG_VALUE_LENGTH && CharOperation.equals(TAG_VALUE, tagName)) {
+                                                       this.tagValue = TAG_VALUE_VALUE;
+                                                       if (this.inlineTagStarted) {
+                                                               valid = parseReference();
+                                                       } else {
+                                                               valid = false;
+                                                       }
+                                               } else {
+                                                       this.tagValue = TAG_OTHERS_VALUE;
+                                                       createTag();
+                                               }
+                                       break;
+                                       default:
+                                               this.tagValue = TAG_OTHERS_VALUE;
+                                               createTag();
+                               }
+                               break;
+                       case TerminalTokens.TokenNamereturn :
+                               this.tagValue = TAG_RETURN_VALUE;
+                               valid = parseReturn();
+                               break;
+                       case TerminalTokens.TokenNamethrows :
+                               this.tagValue = TAG_THROWS_VALUE;
+                               valid = parseThrows();
+                               break;
+                       case TerminalTokens.TokenNameabstract:
+                       case TerminalTokens.TokenNameassert:
+                       case TerminalTokens.TokenNameboolean:
+                       case TerminalTokens.TokenNamebreak:
+                       case TerminalTokens.TokenNamebyte:
+                       case TerminalTokens.TokenNamecase:
+                       case TerminalTokens.TokenNamecatch:
+                       case TerminalTokens.TokenNamechar:
+                       case TerminalTokens.TokenNameclass:
+                       case TerminalTokens.TokenNamecontinue:
+                       case TerminalTokens.TokenNamedefault:
+                       case TerminalTokens.TokenNamedo:
+                       case TerminalTokens.TokenNamedouble:
+                       case TerminalTokens.TokenNameelse:
+                       case TerminalTokens.TokenNameextends:
+                       case TerminalTokens.TokenNamefalse:
+                       case TerminalTokens.TokenNamefinal:
+                       case TerminalTokens.TokenNamefinally:
+                       case TerminalTokens.TokenNamefloat:
+                       case TerminalTokens.TokenNamefor:
+                       case TerminalTokens.TokenNameif:
+                       case TerminalTokens.TokenNameimplements:
+                       case TerminalTokens.TokenNameimport:
+                       case TerminalTokens.TokenNameinstanceof:
+                       case TerminalTokens.TokenNameint:
+                       case TerminalTokens.TokenNameinterface:
+                       case TerminalTokens.TokenNamelong:
+                       case TerminalTokens.TokenNamenative:
+                       case TerminalTokens.TokenNamenew:
+                       case TerminalTokens.TokenNamenull:
+                       case TerminalTokens.TokenNamepackage:
+                       case TerminalTokens.TokenNameprivate:
+                       case TerminalTokens.TokenNameprotected:
+                       case TerminalTokens.TokenNamepublic:
+                       case TerminalTokens.TokenNameshort:
+                       case TerminalTokens.TokenNamestatic:
+                       case TerminalTokens.TokenNamestrictfp:
+                       case TerminalTokens.TokenNamesuper:
+                       case TerminalTokens.TokenNameswitch:
+                       case TerminalTokens.TokenNamesynchronized:
+                       case TerminalTokens.TokenNamethis:
+                       case TerminalTokens.TokenNamethrow:
+                       case TerminalTokens.TokenNametransient:
+                       case TerminalTokens.TokenNametrue:
+                       case TerminalTokens.TokenNametry:
+                       case TerminalTokens.TokenNamevoid:
+                       case TerminalTokens.TokenNamevolatile:
+                       case TerminalTokens.TokenNamewhile:
+                               this.tagValue = TAG_OTHERS_VALUE;
+                               createTag();
+                               break;
+               }
+               this.textStart = this.index;
+               return valid;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushParamName(java.lang.Object)
+        */
+       protected boolean pushParamName(boolean isTypeParam) {
+               int idIndex = isTypeParam ? 1 : 0;
+               final SimpleName name = new SimpleName(this.ast);
+               name.internalSetIdentifier(new String(this.identifierStack[idIndex]));
+               int nameStart = (int) (this.identifierPositionStack[idIndex] >>> 32);
+               int nameEnd = (int) (this.identifierPositionStack[idIndex] & 0x00000000FFFFFFFFL);
+               name.setSourceRange(nameStart, nameEnd-nameStart+1);
+               TagElement paramTag = this.ast.newTagElement();
+               paramTag.setTagName(TagElement.TAG_PARAM);
+               if (isTypeParam) { // specific storage for @param <E> (see bug 79809)
+                       // '<' was stored in identifiers stack
+                       TextElement text = this.ast.newTextElement();
+                       text.setText(new String(this.identifierStack[0]));
+                       int txtStart = (int) (this.identifierPositionStack[0] >>> 32);
+                       int txtEnd = (int) (this.identifierPositionStack[0] & 0x00000000FFFFFFFFL);
+                       text.setSourceRange(txtStart, txtEnd-txtStart+1);
+                       paramTag.fragments().add(text);
+                       // add simple name
+                       paramTag.fragments().add(name);
+                       // '>' was stored in identifiers stack
+                       text = this.ast.newTextElement();
+                       text.setText(new String(this.identifierStack[2]));
+                       txtStart = (int) (this.identifierPositionStack[2] >>> 32);
+                       txtEnd = (int) (this.identifierPositionStack[2] & 0x00000000FFFFFFFFL);
+                       text.setSourceRange(txtStart, txtEnd-txtStart+1);
+                       paramTag.fragments().add(text);
+                       // set param tag source range
+                       paramTag.setSourceRange(this.tagSourceStart, txtEnd-this.tagSourceStart+1);
+               } else {
+                       paramTag.setSourceRange(this.tagSourceStart, nameEnd-this.tagSourceStart+1);
+                       paramTag.fragments().add(name);
+               }
+               pushOnAstStack(paramTag, true);
+               return true;
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushSeeRef(java.lang.Object)
+        */
+       protected boolean pushSeeRef(Object statement) {
+               TagElement seeTag = this.ast.newTagElement();
+               ASTNode node = (ASTNode) statement;
+               seeTag.fragments().add(node);
+               int end = node.getStartPosition()+node.getLength()-1;
+               if (this.inlineTagStarted) {
+                       seeTag.setSourceRange(this.inlineTagStart, end-this.inlineTagStart+1);
+                       switch (this.tagValue) {
+                               case TAG_LINK_VALUE:
+                                       seeTag.setTagName(TagElement.TAG_LINK);
+                               break;
+                               case TAG_LINKPLAIN_VALUE:
+                                       seeTag.setTagName(TagElement.TAG_LINKPLAIN);
+                               break;
+                               case TAG_VALUE_VALUE:
+                                       seeTag.setTagName(TagElement.TAG_VALUE);
+                               break;
+                       }
+                       TagElement previousTag = null;
+                       int previousStart = this.inlineTagStart;
+                       if (this.astPtr == -1) {
+                               previousTag = this.ast.newTagElement();
+                               pushOnAstStack(previousTag, true);
+                       } else {
+                               previousTag = (TagElement) this.astStack[this.astPtr];
+                               previousStart = previousTag.getStartPosition();
+                       }
+                       previousTag.fragments().add(seeTag);
+                       previousTag.setSourceRange(previousStart, end-previousStart+1);
+               } else {
+                       seeTag.setTagName(TagElement.TAG_SEE);
+                       seeTag.setSourceRange(this.tagSourceStart, end-this.tagSourceStart+1);
+                       pushOnAstStack(seeTag, true);
+               }
+               return true;
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushText(int, int)
+        */
+       protected void pushText(int start, int end) {
+
+               // Create text element
+               TextElement text = this.ast.newTextElement();
+               text.setText(new String( this.source, start, end-start));
+               text.setSourceRange(start, end-start);
+
+               // Search previous tag on which to add the text element
+               TagElement previousTag = null;
+               int previousStart = start;
+               if (this.astPtr == -1) {
+                       previousTag = this.ast.newTagElement();
+                       previousTag.setSourceRange(start, end-start);
+                       pushOnAstStack(previousTag, true);
+               } else {
+                       previousTag = (TagElement) this.astStack[this.astPtr];
+                       previousStart = previousTag.getStartPosition();
+               }
+
+               // If we're in a inline tag, then retrieve previous tag in its fragments
+               List fragments = previousTag.fragments();
+               if (this.inlineTagStarted) {
+                       int size = fragments.size();
+                       if (size == 0) {
+                               // no existing fragment => just add the element
+                               TagElement inlineTag = this.ast.newTagElement();
+                               fragments.add(inlineTag);
+                               previousTag = inlineTag;
+                       } else {
+                               // If last fragment is a tag, then use it as previous tag
+                               ASTNode lastFragment = (ASTNode) fragments.get(size-1);
+                               if (lastFragment.getNodeType() == ASTNode.TAG_ELEMENT) {
+                                       previousTag = (TagElement) lastFragment;
+                                       previousStart = previousTag.getStartPosition();
+                               }
+                       }
+               }
+
+               // Add the text
+               previousTag.fragments().add(text);
+               previousTag.setSourceRange(previousStart, end-previousStart);
+               this.textStart = -1;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushThrowName(java.lang.Object)
+        */
+       protected boolean pushThrowName(Object typeRef) {
+               TagElement throwsTag = this.ast.newTagElement();
+               switch (this.tagValue) {
+                       case TAG_THROWS_VALUE:
+                               throwsTag.setTagName(TagElement.TAG_THROWS);
+                       break;
+                       case TAG_EXCEPTION_VALUE:
+                               throwsTag.setTagName(TagElement.TAG_EXCEPTION);
+                       break;
+               }
+               throwsTag.setSourceRange(this.tagSourceStart, this.scanner.getCurrentTokenEndPosition()-this.tagSourceStart+1);
+               throwsTag.fragments().add(typeRef);
+               pushOnAstStack(throwsTag, true);
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#refreshInlineTagPosition(int)
+        */
+       protected void refreshInlineTagPosition(int previousPosition) {
+               if (this.astPtr != -1) {
+                       TagElement previousTag = (TagElement) this.astStack[this.astPtr];
+                       if (this.inlineTagStarted) {
+                               int previousStart = previousTag.getStartPosition();
+                               previousTag.setSourceRange(previousStart, previousPosition-previousStart+1);
+                               if (previousTag.fragments().size() > 0) {
+                                       ASTNode inlineTag = (ASTNode) previousTag.fragments().get(previousTag.fragments().size()-1);
+                                       if (inlineTag.getNodeType() == ASTNode.TAG_ELEMENT) {
+                                               int inlineStart = inlineTag.getStartPosition();
+                                               inlineTag.setSourceRange(inlineStart, previousPosition-inlineStart+1);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Add stored tag elements to associated comment.
+        */
+       protected void updateDocComment() {
+               for (int idx = 0; idx <= this.astPtr; idx++) {
+                       this.docComment.tags().add(this.astStack[idx]);
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EmptyStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EmptyStatement.java
new file mode 100644 (file)
index 0000000..fb82367
--- /dev/null
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Null statement AST node type.
+ *
+ * <pre>
+ * EmptyStatement:
+ *    <b>;</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class EmptyStatement extends Statement {
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(1);
+               createPropertyList(EmptyStatement.class, 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;
+       }
+                       
+       /**
+        * Creates a new unparented null statement node owned by the given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       EmptyStatement(AST ast) {
+               super(ast);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return EMPTY_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               EmptyStatement result = new EmptyStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EnhancedForStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EnhancedForStatement.java
new file mode 100644 (file)
index 0000000..98f5194
--- /dev/null
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Enhanced For statement AST node type (added in JLS3 API).
+ *
+ * <pre>
+ * EnhancedForStatement:
+ *    <b>for</b> <b>(</b> FormalParameter <b>:</b> Expression <b>)</b>
+ *                     Statement
+ * </pre>
+ * The FormalParameter is represented by a <code>SingleVariableDeclaration</code>
+ * (without an initializer).
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class EnhancedForStatement extends Statement {
+       
+       /**
+        * The "parameter" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor PARAMETER_PROPERTY = 
+               new ChildPropertyDescriptor(EnhancedForStatement.class, "parameter", SingleVariableDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "expression" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(EnhancedForStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "body" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor BODY_PROPERTY = 
+               new ChildPropertyDescriptor(EnhancedForStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(4);
+               createPropertyList(EnhancedForStatement.class, properyList);
+               addProperty(PARAMETER_PROPERTY, properyList);
+               addProperty(EXPRESSION_PROPERTY, properyList);
+               addProperty(BODY_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})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                       
+       /**
+        * The parameter; lazily initialized; defaults to a unspecified,
+        * legal node.
+        */
+       private SingleVariableDeclaration parameter = null;
+
+       /**
+        * The expression; lazily initialized; defaults to a unspecified, but legal,
+        * expression.
+        */
+       private Expression expression = null;
+
+       /**
+        * The body statement; lazily initialized; defaults to an empty block
+        * statement.
+        */
+       private Statement body = null;
+                       
+       /**
+        * Creates a new AST node for an enchanced for statement owned by the
+        * given AST. By default, the parameter and expression are unspecified
+        * but legal subtrees, and the body is an empty block.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       EnhancedForStatement(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == PARAMETER_PROPERTY) {
+                       if (get) {
+                               return getParameter();
+                       } else {
+                               setParameter((SingleVariableDeclaration) child);
+                               return null;
+                       }
+               }
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == BODY_PROPERTY) {
+                       if (get) {
+                               return getBody();
+                       } else {
+                               setBody((Statement) 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.
+        */
+       final int getNodeType0() {
+               return ENHANCED_FOR_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               EnhancedForStatement result = new EnhancedForStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setParameter((SingleVariableDeclaration) getParameter().clone(target));
+               result.setExpression((Expression) getExpression().clone(target));
+               result.setBody(
+                       (Statement) ASTNode.copySubtree(target, getBody()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getParameter());
+                       acceptChild(visitor, getExpression());
+                       acceptChild(visitor, getBody());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the formal parameter in this enhanced for statement.
+        * 
+        * @return the parameter
+        */ 
+       public SingleVariableDeclaration getParameter() {
+               if (this.parameter == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.parameter == null) {
+                                       preLazyInit();
+                                       this.parameter = this.ast.newSingleVariableDeclaration();
+                                       postLazyInit(this.parameter, PARAMETER_PROPERTY);
+                               }
+                       }
+               }
+               return this.parameter;
+       }
+
+       /**
+        * Sets the formal parameter in this enhanced for statement.
+        * 
+        * @param parameter the new parameter
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setParameter(SingleVariableDeclaration parameter) {
+               if (parameter == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.parameter;
+               preReplaceChild(oldChild, parameter, PARAMETER_PROPERTY);
+               this.parameter = parameter;
+               postReplaceChild(oldChild, parameter, PARAMETER_PROPERTY);
+       }
+       
+       /**
+        * Returns the expression of this enhanced for statement.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new SimpleName(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.expression;
+       }
+               
+       /**
+        * Sets the expression of this enhanced for statement.
+        * 
+        * @param expression the new expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the body of this enchanced for statement.
+        * 
+        * @return the body statement node
+        */ 
+       public Statement getBody() {
+               if (this.body == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.body == null) {
+                                       preLazyInit();
+                                       this.body = new Block(this.ast);
+                                       postLazyInit(this.body, BODY_PROPERTY);
+                               }
+                       }
+               }
+               return this.body;
+       }
+       
+       /**
+        * Sets the body of this enhanced for statement.
+        * 
+        * @param statement the body statement node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setBody(Statement statement) {
+               if (statement == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.body;
+               preReplaceChild(oldChild, statement, BODY_PROPERTY);
+               this.body = statement;
+               postReplaceChild(oldChild, statement, BODY_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.parameter == null ? 0 : getParameter().treeSize())
+                       + (this.expression == null ? 0 : getExpression().treeSize())
+                       + (this.body == null ? 0 : getBody().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EnumConstantDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EnumConstantDeclaration.java
new file mode 100644 (file)
index 0000000..011e820
--- /dev/null
@@ -0,0 +1,390 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Enumeration constant declaration AST node type (added in JLS3 API).
+ *
+ * <pre>
+ * EnumConstantDeclaration:
+ *     [ Javadoc ] { ExtendedModifier } Identifier
+ *         [ <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b> ]
+ *         [ AnonymousClassDeclaration ]
+ * </pre>
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the identifier. If there are class body declarations, the
+ * source range extends through the last character of the last character of
+ * the "}" token following the body declarations. If there are arguments but
+ * no class body declarations, the source range extends through the last
+ * character of the ")" token following the arguments. If there are no 
+ * arguments and no class body declarations, the source range extends through
+ * the last character of the identifier.
+ * </p>
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class EnumConstantDeclaration extends BodyDeclaration {
+       
+       /**
+        * The "javadoc" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
+               internalJavadocPropertyFactory(EnumConstantDeclaration.class);
+
+       /**
+        * The "modifiers" structural property of this node type).
+        */
+       public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
+               internalModifiers2PropertyFactory(EnumConstantDeclaration.class);
+       
+       /**
+        * The "name" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(EnumConstantDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "arguments" structural property of this node type.
+        */
+       public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(EnumConstantDeclaration.class, "arguments", Expression.class, NO_CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "anonymousClassDeclaration" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor ANONYMOUS_CLASS_DECLARATION_PROPERTY = 
+               new ChildPropertyDescriptor(EnumConstantDeclaration.class, "anonymousClassDeclaration", AnonymousClassDeclaration.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(6);
+               createPropertyList(EnumConstantDeclaration.class, properyList);
+               addProperty(JAVADOC_PROPERTY, properyList);
+               addProperty(MODIFIERS2_PROPERTY, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               addProperty(ARGUMENTS_PROPERTY, properyList);
+               addProperty(ANONYMOUS_CLASS_DECLARATION_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})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                       
+       /**
+        * The constant name; lazily initialized; defaults to a unspecified,
+        * legal Java class identifier.
+        */
+       private SimpleName constantName = null;
+
+       /**
+        * The list of argument expressions (element type: 
+        * <code>Expression</code>). Defaults to an empty list.
+        */
+       private ASTNode.NodeList arguments =
+               new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+                       
+       /**
+        * The optional anonymous class declaration; <code>null</code> for none; 
+        * defaults to none.
+        */
+       private AnonymousClassDeclaration optionalAnonymousClassDeclaration = null;
+       
+       /**
+        * Creates a new AST node for an enumeration constants declaration owned by
+        * the given AST. By default, the enumeration constant has an unspecified,
+        * but legal, name; no javadoc; an empty list of modifiers and annotations;
+        * an empty list of arguments; and does not declare an anonymous class.
+        * <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
+        */
+       EnumConstantDeclaration(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == JAVADOC_PROPERTY) {
+                       if (get) {
+                               return getJavadoc();
+                       } else {
+                               setJavadoc((Javadoc) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) child);
+                               return null;
+                       }
+               }
+               if (property == ANONYMOUS_CLASS_DECLARATION_PROPERTY) {
+                       if (get) {
+                               return getAnonymousClassDeclaration();
+                       } else {
+                               setAnonymousClassDeclaration((AnonymousClassDeclaration) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == MODIFIERS2_PROPERTY) {
+                       return modifiers();
+               }
+               if (property == ARGUMENTS_PROPERTY) {
+                       return arguments();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildPropertyDescriptor internalJavadocProperty() {
+               return JAVADOC_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildListPropertyDescriptor internalModifiers2Property() {
+               return MODIFIERS2_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final SimplePropertyDescriptor internalModifiersProperty() {
+               // this property will not be asked for (node type did not exist in JLS2)
+               return null;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return ENUM_CONSTANT_DECLARATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               EnumConstantDeclaration result = new EnumConstantDeclaration(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setJavadoc(
+                       (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+               result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+               result.setName((SimpleName) getName().clone(target));
+               result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+               result.setAnonymousClassDeclaration(
+                               (AnonymousClassDeclaration) ASTNode.copySubtree(target, getAnonymousClassDeclaration()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getJavadoc());
+                       acceptChildren(visitor, this.modifiers);
+                       acceptChild(visitor, getName());
+                       acceptChildren(visitor, this.arguments);
+                       acceptChild(visitor, getAnonymousClassDeclaration());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the name of the constant declared in this enum declaration.
+        * 
+        * @return the constant name node
+        */ 
+       public SimpleName getName() {
+               if (this.constantName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.constantName == null) {
+                                       preLazyInit();
+                                       this.constantName = new SimpleName(this.ast);
+                                       postLazyInit(this.constantName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.constantName;
+       }
+               
+       /**
+        * Sets the name of the constant declared in this enum declaration to the
+        * given name.
+        * 
+        * @param constantName the new constant name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName constantName) {
+               if (constantName == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.constantName;
+               preReplaceChild(oldChild, constantName, NAME_PROPERTY);
+               this.constantName = constantName;
+               postReplaceChild(oldChild, constantName, NAME_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of argument expressions in this enumeration
+        * constant declaration. Note that an empty list of arguments is equivalent
+        * to not explicitly specifying arguments.
+        * 
+        * @return the live list of argument expressions 
+        *    (element type: <code>Expression</code>)
+        */ 
+       public List arguments() {
+               return this.arguments;
+       }
+
+       /**
+        * Returns the anonymous class declaration introduced by this
+        * enum constant declaration, if it has one.
+        * 
+        * @return the anonymous class declaration, or <code>null</code> if none
+        */ 
+       public AnonymousClassDeclaration getAnonymousClassDeclaration() {
+               return this.optionalAnonymousClassDeclaration;
+       }
+       
+       /**
+        * Sets whether this enum constant declaration declares
+        * an anonymous class (that is, has class body declarations).
+        * 
+        * @param decl the anonymous class declaration, or <code>null</code> 
+        *    if none
+        */ 
+       public void setAnonymousClassDeclaration(AnonymousClassDeclaration decl) {
+               ASTNode oldChild = this.optionalAnonymousClassDeclaration;
+               preReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+               this.optionalAnonymousClassDeclaration = decl;
+               postReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
+       }
+       
+       /**
+        * Resolves and returns the binding for the constructor invoked by this
+        * enum constant.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the constructor binding, or <code>null</code> if the binding
+        *    cannot be resolved
+        */     
+       public IMethodBinding resolveConstructorBinding() {
+               return this.ast.getBindingResolver().resolveConstructor(this);
+       }
+
+       /**
+        * Resolves and returns the field binding for this enum constant.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public IVariableBinding resolveVariable() {
+               return this.ast.getBindingResolver().resolveVariable(this);
+       }
+               
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+                       + this.modifiers.listSize()
+                       + (this.constantName == null ? 0 : getName().treeSize())
+                       + this.arguments.listSize()
+                       + (this.optionalAnonymousClassDeclaration == null ? 0 : getAnonymousClassDeclaration().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EnumDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/EnumDeclaration.java
new file mode 100644 (file)
index 0000000..debd439
--- /dev/null
@@ -0,0 +1,335 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Enum declaration AST node type (added in JLS3 API).
+ *
+ * <pre>
+ * EnumDeclaration:
+ *     [ Javadoc ] { ExtendedModifier } <b>enum</b> Identifier
+ *         [ <b>implements</b> Type { <b>,</b> Type } ]
+ *         <b>{</b>
+ *         [ EnumConstantDeclaration { <b>,</b> EnumConstantDeclaration } ] [ <b>,</b> ]
+ *         [ <b>;</b> { ClassBodyDeclaration | <b>;</b> } ]
+ *         <b>}</b>
+ * </pre>
+ * The {@link #enumConstants()} list holds the enum constant declarations,
+ * while the {@link #bodyDeclarations()} list holds the class body declarations
+ * that appear after the semicolon.
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the first modifier or annotation (if present), or the
+ * first character of the "enum" keyword (if no
+ * modifiers or annotations). The source range extends through the last
+ * character of the "}" token following the body declarations.
+ * </p>
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class EnumDeclaration extends AbstractTypeDeclaration {
+       
+       /**
+        * The "javadoc" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
+               internalJavadocPropertyFactory(EnumDeclaration.class);
+
+       /**
+        * The "modifiers" structural property of this node type (added in JLS3 API).
+        */
+       public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
+               internalModifiers2PropertyFactory(EnumDeclaration.class);
+       
+       /**
+        * The "name" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               internalNamePropertyFactory(EnumDeclaration.class);
+
+       /**
+        * The "superInterfaceTypes" structural property of this node type.
+        */
+       public static final ChildListPropertyDescriptor SUPER_INTERFACE_TYPES_PROPERTY = 
+               new ChildListPropertyDescriptor(EnumDeclaration.class, "superInterfaceTypes", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "enumConstants" structural property of this node type.
+        */
+       public static final ChildListPropertyDescriptor ENUM_CONSTANTS_PROPERTY = 
+               new ChildListPropertyDescriptor(EnumDeclaration.class, "enumConstants", EnumConstantDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "bodyDeclarations" structural property of this node type.
+        */
+       public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY = 
+               internalBodyDeclarationPropertyFactory(EnumDeclaration.class);
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(6);
+               createPropertyList(EnumDeclaration.class, properyList);
+               addProperty(JAVADOC_PROPERTY, properyList);
+               addProperty(MODIFIERS2_PROPERTY, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               addProperty(SUPER_INTERFACE_TYPES_PROPERTY, properyList);
+               addProperty(ENUM_CONSTANTS_PROPERTY, properyList);
+               addProperty(BODY_DECLARATIONS_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})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                       
+       /**
+        * The superinterface types (element type: <code>Type</code>). 
+        * Defaults to an empty list.
+        */
+       private ASTNode.NodeList superInterfaceTypes =
+               new ASTNode.NodeList(SUPER_INTERFACE_TYPES_PROPERTY);
+
+       /**
+        * The enum constant declarations
+        * (element type: <code>EnumConstantDeclaration</code>).
+        * Defaults to an empty list.
+        */
+       private ASTNode.NodeList enumConstants = 
+               new ASTNode.NodeList(ENUM_CONSTANTS_PROPERTY);
+
+       /**
+        * Creates a new AST node for an enum declaration owned by the given 
+        * AST. By default, the enum declaration has an unspecified, but legal,
+        * name; no modifiers; no javadoc; no superinterfaces; 
+        * and empty lists of enum constants and body 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
+        */
+       EnumDeclaration(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == JAVADOC_PROPERTY) {
+                       if (get) {
+                               return getJavadoc();
+                       } else {
+                               setJavadoc((Javadoc) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == MODIFIERS2_PROPERTY) {
+                       return modifiers();
+               }
+               if (property == SUPER_INTERFACE_TYPES_PROPERTY) {
+                       return superInterfaceTypes();
+               }
+               if (property == ENUM_CONSTANTS_PROPERTY) {
+                       return enumConstants();
+               }
+               if (property == BODY_DECLARATIONS_PROPERTY) {
+                       return bodyDeclarations();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildPropertyDescriptor internalJavadocProperty() {
+               return JAVADOC_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildListPropertyDescriptor internalModifiers2Property() {
+               return MODIFIERS2_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final SimplePropertyDescriptor internalModifiersProperty() {
+               // this property will not be asked for (node type did not exist in JLS2)
+               return null;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on AbstractTypeDeclaration.
+        */
+       final ChildPropertyDescriptor internalNameProperty() {
+               return NAME_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on AbstractTypeDeclaration.
+        */
+       final ChildListPropertyDescriptor internalBodyDeclarationsProperty() {
+               return BODY_DECLARATIONS_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return ENUM_DECLARATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               EnumDeclaration result = new EnumDeclaration(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setJavadoc(
+                       (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+               result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+               result.setName((SimpleName) getName().clone(target));
+               result.superInterfaceTypes().addAll(
+                       ASTNode.copySubtrees(target, superInterfaceTypes()));
+               result.enumConstants().addAll(
+                               ASTNode.copySubtrees(target, enumConstants()));
+               result.bodyDeclarations().addAll(
+                       ASTNode.copySubtrees(target, bodyDeclarations()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getJavadoc());
+                       acceptChildren(visitor, this.modifiers);
+                       acceptChild(visitor, getName());
+                       acceptChildren(visitor, this.superInterfaceTypes);
+                       acceptChildren(visitor, this.enumConstants);
+                       acceptChildren(visitor, this.bodyDeclarations);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the live ordered list of superinterfaces of this enum
+        * declaration.
+        * 
+        * @return the live list of super interface types
+        *    (element type: <code>Type</code>)
+        */ 
+       public List superInterfaceTypes() {
+               return this.superInterfaceTypes;
+       }
+       
+       /**
+        * Returns the live ordered list of enum constant declarations
+        * of this enum declaration.
+        * 
+        * @return the live list of enum constant declarations
+        *    (element type: {@link EnumConstantDeclaration})
+        */ 
+       public List enumConstants() {
+               return enumConstants;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on AsbtractTypeDeclaration.
+        */
+       ITypeBinding internalResolveBinding() {
+               return this.ast.getBindingResolver().resolveType(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize()
+                       + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+                       + this.modifiers.listSize()
+                       + (this.typeName == null ? 0 : getName().treeSize())
+                       + this.superInterfaceTypes.listSize()
+                       + this.enumConstants.listSize()
+                       + this.bodyDeclarations.listSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Expression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Expression.java
new file mode 100644 (file)
index 0000000..4a5d868
--- /dev/null
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Abstract base class of AST nodes that represent expressions.
+ * There are several kinds of expressions.
+ * <p>
+ * <pre>
+ * Expression:
+ *    Name
+ *    IntegerLiteral (includes decimal, hex, and octal forms; and long)
+ *    FloatingPointLiteral (includes both float and double)
+ *    CharacterLiteral
+ *    NullLiteral
+ *    BooleanLiteral
+ *    StringLiteral
+ *    TypeLiteral
+ *    ThisExpression
+ *    SuperFieldAccess
+ *    FieldAccess
+ *    Assignment
+ *    ParenthesizedExpression
+ *    ClassInstanceCreation
+ *    ArrayCreation
+ *    ArrayInitializer
+ *    MethodInvocation
+ *    SuperMethodInvocation
+ *    ArrayAccess
+ *    InfixExpression
+ *    InstanceofExpression
+ *    ConditionalExpression
+ *    PostfixExpression
+ *    PrefixExpression
+ *    CastExpression
+ *    VariableDeclarationExpression
+ * </pre>
+ * </p>
+ * 
+ * @since 2.0
+ */
+public abstract class Expression extends ASTNode {
+       
+       /**
+        * Creates a new AST node for an expression owned by the given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       Expression(AST ast) {
+               super(ast);
+       }
+
+       /**
+        * Resolves and returns the compile-time constant expression value as 
+        * specified in JLS2 15.28, if this expression has one. Constant expression
+        * values are unavailable unless bindings are requested when the AST is
+        * being built. If the type of the value is a primitive type, the result
+        * is the boxed equivalent (i.e., int returned as an <code>Integer</code>);
+        * if the type of the value is <code>String</code>, the result is the string
+        * itself. If the expression does not have a compile-time constant expression
+        * value, the result is <code>null</code>.
+        * <p>
+        * Resolving constant expressions takes into account the value of simple
+        * and qualified names that refer to constant variables (JLS2 4.12.4).
+        * </p>
+        * <p>
+        * Note 1: enum constants are not considered constant expressions.
+        * The result is always <code>null</code> for these.
+        * </p>
+        * <p>
+        * Note 2: Compile-time constant expressions cannot denote <code>null</code>.
+        * So technically {@link NullLiteral} nodes are not constant expressions.
+        * The result is <code>null</code> for these nonetheless.
+        * </p>
+        * 
+        * @return the constant expression value, or <code>null</code> if this
+        * expression has no constant expression value or if bindings were not
+        * requested when the AST was created
+        * @since 3.1
+        */
+       public final Object resolveConstantExpressionValue() {
+               return this.ast.getBindingResolver().resolveConstantExpressionValue(this);
+       }
+
+       /**
+        * Resolves and returns the binding for the type of this expression.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding for the type of this expression, or
+        *    <code>null</code> if the type cannot be resolved
+        */     
+       public final ITypeBinding resolveTypeBinding() {
+               return this.ast.getBindingResolver().resolveExpressionType(this);
+       }
+
+       /**
+        * Returns whether this expression node is the site of a boxing
+        * conversion (JLS3 5.1.7). This information is available only
+        * when bindings are requested when the AST is being built.
+        * 
+        * @return <code>true</code> if this expression is the site of a
+        * boxing conversion, or <code>false</code> if either no boxing conversion
+        * is involved or if bindings were not requested when the AST was created
+        * @since 3.1
+        */
+       public final boolean resolveBoxing() {
+               return this.ast.getBindingResolver().resolveBoxing(this);
+       }
+       
+       /**
+        * Returns whether this expression node is the site of an unboxing
+        * conversion (JLS3 5.1.8). This information is available only
+        * when bindings are requested when the AST is being built.
+        * 
+        * @return <code>true</code> if this expression is the site of an
+        * unboxing conversion, or <code>false</code> if either no unboxing
+        * conversion is involved or if bindings were not requested when the
+        * AST was created
+        * @since 3.1
+        */
+       public final boolean resolveUnboxing() {
+               return this.ast.getBindingResolver().resolveUnboxing(this);
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ExpressionStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ExpressionStatement.java
new file mode 100644 (file)
index 0000000..e5f8178
--- /dev/null
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Expression statement AST node type.
+ * <p>
+ * This kind of node is used to convert an expression (<code>Expression</code>)
+ * into a statement (<code>Statement</code>) by wrapping it.
+ * </p>
+ * <pre>
+ * ExpressionStatement:
+ *    StatementExpression <b>;</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ExpressionStatement extends Statement {
+       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(ExpressionStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(2);
+               createPropertyList(ExpressionStatement.class, properyList);
+               addProperty(EXPRESSION_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 expression; lazily initialized; defaults to a unspecified, but legal,
+        * expression.
+        */
+       private Expression expression = null;
+
+       /**
+        * Creates a new unparented expression statement node owned by the given 
+        * AST. By default, the expression statement is unspecified, but legal,
+        * method invocation expression.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ExpressionStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) 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.
+        */
+       final int getNodeType0() {
+               return EXPRESSION_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ExpressionStatement result = new ExpressionStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setExpression((Expression) getExpression().clone(target));
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getExpression());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this expression statement.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new MethodInvocation(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.expression;
+       }
+               
+       /**
+        * Sets the expression of this expression statement.
+        * 
+        * @param expression the new expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.expression == null ? 0 : getExpression().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/FieldAccess.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/FieldAccess.java
new file mode 100644 (file)
index 0000000..d38f311
--- /dev/null
@@ -0,0 +1,313 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Field access expression AST node type.
+ *
+ * <pre>
+ * FieldAccess: 
+ *             Expression <b>.</b> Identifier
+ * </pre>
+ * 
+ * <p>
+ * Note that there are several kinds of expressions that resemble field access
+ * expressions: qualified names, this expressions, and super field access
+ * expressions. The following guidelines help with correct usage:
+ * <ul>
+ *   <li>An expression like "foo.this" can only be represented as a this
+ *   expression (<code>ThisExpression</code>) containing a simple name.
+ *   "this" is a keyword, and therefore invalid as an identifier.</li>
+ *   <li>An expression like "this.foo" can only be represented as a field
+ *   access expression (<code>FieldAccess</code>) containing a this expression
+ *   and a simple name. Again, this is because "this" is a keyword, and
+ *   therefore invalid as an identifier.</li>
+ *   <li>An expression with "super" can only be represented as a super field
+ *   access expression (<code>SuperFieldAccess</code>). "super" is a also
+ *   keyword, and therefore invalid as an identifier.</li>
+ *   <li>An expression like "foo.bar" can be represented either as a
+ *   qualified name (<code>QualifiedName</code>) or as a field access
+ *   expression (<code>FieldAccess</code>) containing simple names. Either
+ *   is acceptable, and there is no way to choose between them without
+ *   information about what the names resolve to
+ *   (<code>ASTParser</code> may return either).</li>
+ *   <li>Other expressions ending in an identifier, such as "foo().bar" can
+ *   only be represented as field access expressions
+ *   (<code>FieldAccess</code>).</li>
+ * </ul>
+ * </p>
+ * 
+ * @see QualifiedName
+ * @see ThisExpression
+ * @see SuperFieldAccess
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class FieldAccess extends Expression {
+       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(FieldAccess.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(FieldAccess.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(3);
+               createPropertyList(FieldAccess.class, properyList);
+               addProperty(EXPRESSION_PROPERTY, properyList);
+               addProperty(NAME_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 expression; lazily initialized; defaults to an unspecified,
+        * but legal, simple name.
+        */
+       private Expression expression = null;
+
+       /**
+        * The field; lazily initialized; defaults to an unspecified,
+        * but legal, simple field name.
+        */
+       private SimpleName fieldName = null;
+
+       /**
+        * Creates a new unparented node for a field access expression owned by the
+        * given AST. By default, the expression and field are both unspecified,
+        * but legal, names.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       FieldAccess(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) 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.
+        */
+       final int getNodeType0() {
+               return FIELD_ACCESS;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               FieldAccess result = new FieldAccess(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setExpression((Expression) getExpression().clone(target));
+               result.setName((SimpleName) getName().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getExpression());
+                       acceptChild(visitor, getName());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this field access expression.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new SimpleName(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.expression;
+       }
+               
+       /**
+        * Sets the expression of this field access expression.
+        * 
+        * @param expression the new expression
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the name of the field accessed in this field access expression.
+        * 
+        * @return the field name
+        */ 
+       public SimpleName getName() {
+               if (this.fieldName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.fieldName == null) {
+                                       preLazyInit();
+                                       this.fieldName = new SimpleName(this.ast);
+                                       postLazyInit(this.fieldName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.fieldName;
+       }
+               
+       /**
+        * Sets the name of the field accessed in this field access expression.
+        * 
+        * @param fieldName the field name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName fieldName) {
+               if (fieldName == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.fieldName;
+               preReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+               this.fieldName = fieldName;
+               postReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /**
+        * Resolves and returns the binding for the field accessed by this
+        * expression.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        *
+        * @return the variable binding, or <code>null</code> if the binding cannot
+        * be resolved
+        * @since 3.0
+        */
+       public IVariableBinding resolveFieldBinding() {
+               return this.ast.getBindingResolver().resolveField(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.expression == null ? 0 : getExpression().treeSize())
+                       + (this.fieldName == null ? 0 : getName().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/FieldDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/FieldDeclaration.java
new file mode 100644 (file)
index 0000000..6a6855b
--- /dev/null
@@ -0,0 +1,368 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Field declaration node type.
+ * <p>
+ * This kind of node collects several variable declaration fragments
+ * (<code>VariableDeclarationFragment</code>) into a single body declaration
+ * (<code>BodyDeclaration</code>), all sharing the same modifiers and base type.
+ * </p>
+ * <pre>
+ * FieldDeclaration:
+ *    [Javadoc] { ExtendedModifier } Type VariableDeclarationFragment
+ *         { <b>,</b> VariableDeclarationFragment } <b>;</b>
+ * </pre>
+ * <p>
+ * When a Javadoc comment is present, the source range begins with the first
+ * character of the "/**" comment delimiter. When there is no Javadoc comment,
+ * the source range begins with the first character of the initial modifier or
+ * type. The source range extends through the last character of the final ";".
+ * </p>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class FieldDeclaration extends BodyDeclaration {
+       
+       /**
+        * The "javadoc" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
+               internalJavadocPropertyFactory(FieldDeclaration.class);
+
+       /**
+        * The "modifiers" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor MODIFIERS_PROPERTY = 
+               internalModifiersPropertyFactory(FieldDeclaration.class);
+       
+       /**
+        * The "modifiers" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
+               internalModifiers2PropertyFactory(FieldDeclaration.class);
+       
+       /**
+        * The "type" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(FieldDeclaration.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "fragments" structural property of this node type).
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(FieldDeclaration.class, "fragments", VariableDeclarationFragment.class, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List properyList = new ArrayList(5);
+               createPropertyList(FieldDeclaration.class, properyList);
+               addProperty(JAVADOC_PROPERTY, properyList);
+               addProperty(MODIFIERS_PROPERTY, properyList);
+               addProperty(TYPE_PROPERTY, properyList);
+               addProperty(FRAGMENTS_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+               
+               properyList = new ArrayList(5);
+               createPropertyList(FieldDeclaration.class, properyList);
+               addProperty(JAVADOC_PROPERTY, properyList);
+               addProperty(MODIFIERS2_PROPERTY, properyList);
+               addProperty(TYPE_PROPERTY, properyList);
+               addProperty(FRAGMENTS_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_3_0 = 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The base type; lazily initialized; defaults to an unspecified,
+        * legal type.
+        */
+       private Type baseType = null;
+
+       /**
+        * The list of variable declaration fragments (element type: 
+        * <code VariableDeclarationFragment</code>).  Defaults to an empty list.
+        */
+       private ASTNode.NodeList variableDeclarationFragments = 
+               new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+       /**
+        * Creates a new unparented field declaration statement node owned 
+        * by the given AST.  By default, the field declaration has: no modifiers,
+        * an unspecified (but legal) type, and an empty list of variable 
+        * declaration fragments (which is syntactically illegal).
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       FieldDeclaration(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+               if (property == MODIFIERS_PROPERTY) {
+                       if (get) {
+                               return getModifiers();
+                       } else {
+                               internalSetModifiers(value);
+                               return 0;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetIntProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == JAVADOC_PROPERTY) {
+                       if (get) {
+                               return getJavadoc();
+                       } else {
+                               setJavadoc((Javadoc) child);
+                               return null;
+                       }
+               }
+               if (property == TYPE_PROPERTY) {
+                       if (get) {
+                               return getType();
+                       } else {
+                               setType((Type) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == MODIFIERS2_PROPERTY) {
+                       return modifiers();
+               }
+               if (property == FRAGMENTS_PROPERTY) {
+                       return fragments();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildPropertyDescriptor internalJavadocProperty() {
+               return JAVADOC_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final SimplePropertyDescriptor internalModifiersProperty() {
+               return MODIFIERS_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildListPropertyDescriptor internalModifiers2Property() {
+               return MODIFIERS2_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return FIELD_DECLARATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               FieldDeclaration result = new FieldDeclaration(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setJavadoc(
+                       (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                       result.internalSetModifiers(getModifiers());
+               }
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+               }
+               result.setType((Type) getType().clone(target));
+               result.fragments().addAll(
+                       ASTNode.copySubtrees(target, fragments()));
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getJavadoc());
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChildren(visitor, this.modifiers);
+                       }
+                       acceptChild(visitor, getType());
+                       acceptChildren(visitor, this.variableDeclarationFragments);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the base type declared in this field declaration.
+        * <p>
+        * N.B. The individual child variable declaration fragments may specify 
+        * additional array dimensions. So the type of the variable are not 
+        * necessarily exactly this type.
+        * </p>
+        * 
+        * @return the base type
+        */ 
+       public Type getType() {
+               if (this.baseType == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.baseType == null) {
+                                       preLazyInit();
+                                       this.baseType = this.ast.newPrimitiveType(PrimitiveType.INT);
+                                       postLazyInit(this.baseType, TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.baseType;
+       }
+
+       /**
+        * Sets the base type declared in this field declaration to the given type.
+        * 
+        * @param type the new base type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setType(Type type) {
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.baseType;
+               preReplaceChild(oldChild, type, TYPE_PROPERTY);
+               this.baseType = type;
+               postReplaceChild(oldChild, type, TYPE_PROPERTY);
+       }
+
+       /**
+        * Returns the live list of variable declaration fragments in this field 
+        * declaration. Adding and removing nodes from this list affects this node
+        * dynamically. All nodes in this list must be 
+        * <code>VariableDeclarationFragment</code>s; attempts to add any other 
+        * type of node will trigger an exception.
+        * 
+        * @return the live list of variable declaration fragments in this 
+        *    statement (element type: <code>VariableDeclarationFragment</code>)
+        */ 
+       public List fragments() {
+               return this.variableDeclarationFragments;
+       }
+               
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+                       + (this.modifiers == null ? 0 : this.modifiers.listSize())
+                       + (this.baseType == null ? 0 : getType().treeSize())
+                       + this.variableDeclarationFragments.listSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ForStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ForStatement.java
new file mode 100644 (file)
index 0000000..26987b0
--- /dev/null
@@ -0,0 +1,361 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * For statement AST node type.
+ *
+ * <pre>
+ * ForStatement:
+ *    <b>for</b> <b>(</b>
+ *                     [ ForInit ]<b>;</b>
+ *                     [ Expression ] <b>;</b>
+ *                     [ ForUpdate ] <b>)</b>
+ *                     Statement
+ * ForInit:
+ *             Expression { <b>,</b> Expression }
+ * ForUpdate:
+ *             Expression { <b>,</b> Expression }
+ * </pre>
+ * <p>
+ * Note: When variables are declared in the initializer
+ * of a for statement such as "<code>for (int a=1, b=2;;);</code>",
+ * they should be represented as a single
+ * <code>VariableDeclarationExpression</code>
+ * with two fragments, rather than being split up into a pair
+ * of expressions.
+ * </p>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ForStatement extends Statement {
+       
+       /**
+        * The "initializers" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor INITIALIZERS_PROPERTY = 
+               new ChildListPropertyDescriptor(ForStatement.class, "initializers", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(ForStatement.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "updaters" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor UPDATERS_PROPERTY = 
+               new ChildListPropertyDescriptor(ForStatement.class, "updaters", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "body" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor BODY_PROPERTY = 
+               new ChildPropertyDescriptor(ForStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(5);
+               createPropertyList(ForStatement.class, properyList);
+               addProperty(INITIALIZERS_PROPERTY, properyList);
+               addProperty(EXPRESSION_PROPERTY, properyList);
+               addProperty(UPDATERS_PROPERTY, properyList);
+               addProperty(BODY_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 list of initializer expressions (element type: 
+        * <code>Expression</code>). Defaults to an empty list.
+        */
+       private ASTNode.NodeList initializers =
+               new ASTNode.NodeList(INITIALIZERS_PROPERTY);
+
+       /**
+        * The condition expression; <code>null</code> for none; defaults to none.
+        */
+       private Expression optionalConditionExpression = null;
+       
+       /**
+        * The list of update expressions (element type: 
+        * <code>Expression</code>). Defaults to an empty list.
+        */
+       private ASTNode.NodeList updaters =
+               new ASTNode.NodeList(UPDATERS_PROPERTY);
+
+       /**
+        * The body statement; lazily initialized; defaults to an empty block
+        * statement.
+        */
+       private Statement body = null;
+                       
+       /**
+        * Creates a new AST node for a for statement owned by the given AST. 
+        * By default, there are no initializers, no condition expression, 
+        * no updaters, and the body is an empty block.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ForStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == BODY_PROPERTY) {
+                       if (get) {
+                               return getBody();
+                       } else {
+                               setBody((Statement) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == INITIALIZERS_PROPERTY) {
+                       return initializers();
+               }
+               if (property == UPDATERS_PROPERTY) {
+                       return updaters();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return FOR_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ForStatement result = new ForStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.initializers().addAll(ASTNode.copySubtrees(target, initializers()));
+               result.setExpression(
+                       (Expression) ASTNode.copySubtree(target, getExpression()));
+               result.updaters().addAll(ASTNode.copySubtrees(target, updaters()));
+               result.setBody(
+                       (Statement) ASTNode.copySubtree(target, getBody()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChildren(visitor, this.initializers);
+                       acceptChild(visitor, getExpression());
+                       acceptChildren(visitor, this.updaters);
+                       acceptChild(visitor, getBody());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the live ordered list of initializer expressions in this for
+        * statement.
+        * <p>
+        * The list should consist of either a list of so called statement 
+        * expressions (JLS2, 14.8), or a single <code>VariableDeclarationExpression</code>. 
+        * Otherwise, the for statement would have no Java source equivalent.
+        * </p>
+        * 
+        * @return the live list of initializer expressions 
+        *    (element type: <code>Expression</code>)
+        */ 
+       public List initializers() {
+               return this.initializers;
+       }
+       
+       /**
+        * Returns the condition expression of this for statement, or 
+        * <code>null</code> if there is none.
+        * 
+        * @return the condition expression node, or <code>null</code> if 
+        *     there is none
+        */ 
+       public Expression getExpression() {
+               return this.optionalConditionExpression;
+       }
+       
+       /**
+        * Sets or clears the condition expression of this return statement.
+        * 
+        * @param expression the condition expression node, or <code>null</code>
+        *    if there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               ASTNode oldChild = this.optionalConditionExpression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.optionalConditionExpression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of update expressions in this for
+        * statement.
+        * <p>
+        * The list should consist of so called statement expressions. Otherwise,
+        * the for statement would have no Java source equivalent.
+        * </p>
+        * 
+        * @return the live list of update expressions 
+        *    (element type: <code>Expression</code>)
+        */ 
+       public List updaters() {
+               return this.updaters;
+       }
+       
+       /**
+        * Returns the body of this for statement.
+        * 
+        * @return the body statement node
+        */ 
+       public Statement getBody() {
+               if (this.body == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.body == null) {
+                                       preLazyInit();
+                                       this.body = new Block(this.ast);
+                                       postLazyInit(this.body, BODY_PROPERTY);
+                               }
+                       }
+               }
+               return this.body;
+       }
+       
+       /**
+        * Sets the body of this for statement.
+        * <p>
+        * Special note: The Java language does not allow a local variable declaration
+        * to appear as the body of a for statement (they may only appear within a
+        * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+        * as the body of a <code>ForStatement</code>. To get something that will
+        * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+        * inside a <code>Block</code>.
+        * </p>
+        * 
+        * @param statement the body statement node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setBody(Statement statement) {
+               if (statement == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.body;
+               preReplaceChild(oldChild, statement, BODY_PROPERTY);
+               this.body = statement;
+               postReplaceChild(oldChild, statement, BODY_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 4 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + this.initializers.listSize()
+                       + this.updaters.listSize()
+                       + (this.optionalConditionExpression == null ? 0 : getExpression().treeSize())
+                       + (this.body == null ? 0 : getBody().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IAnnotationBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IAnnotationBinding.java
new file mode 100644 (file)
index 0000000..d10066c
--- /dev/null
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 BEA Systems, Inc.
+ * 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:
+ *    tyeung@bea.com - initial API and implementation
+ *    IBM Corporation - changed interface to extend IBinding
+ *    IBM Corporation - renamed from IResolvedAnnotation to IAnnotationBinding
+ *******************************************************************************/
+package net.sourceforge.phpdt.core.dom;
+
+/**
+ * Represents a resolved annotation. Resolved annotations are computed along with other
+ * bindings; they correspond to {@link Annotation} nodes.
+ * 
+ * @since 3.2
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IAnnotationBinding extends IBinding {
+
+       /**
+        * Returns the complete list of member value pairs for this annotation, including
+        * ones explicitly listed in the annotation as well as entries for 
+        * annotation type members with default values that are implied.
+        * 
+        * @return a possibly empty list of resolved member value pairs
+        */
+       IMemberValuePairBinding[] getAllMemberValuePairs();
+       
+       /**
+        * Returns the type of the annotation. The resulting type binding will always
+        * return <code>true</code>     to <code>ITypeBinding.isAnnotation()</code>.
+        * 
+        * @return the type of the annotation
+        */
+       ITypeBinding getAnnotationType();
+       
+       /**
+        * Returns the list of declared member value pairs for this annotation.
+        * Returns an empty list for a {@link MarkerAnnotation}, a one element
+        * list for a {@link SingleMemberAnnotation}, and one entry for each
+        * of the explicitly listed values in a {@link NormalAnnotation}.
+        * <p>
+        * Note that the list only includes entries for annotation type members that are
+        * explicitly mentioned in the annotation. The list does not include any 
+        * annotation type members with default values that are merely implied.
+        * Use {@link #getAllMemberValuePairs()} to get those as well.
+        * </p>
+        * 
+        * @return a possibly empty list of resolved member value pairs
+        */
+       IMemberValuePairBinding[] getDeclaredMemberValuePairs();
+       
+       /**
+        * Returns the name of the annotation type.
+        * 
+        * @return the name of the annotation type
+        */
+       public String getName();
+       
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IBinding.java
new file mode 100644 (file)
index 0000000..e74a703
--- /dev/null
@@ -0,0 +1,326 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.IAnnotation;
+import net.sourceforge.phpdt.core.IJavaElement;
+
+/**
+ * A binding represents a named entity in the Java language. The world of
+ * bindings provides an integrated picture of the structure of the program as
+ * seen from the compiler's point of view. This interface declare protocol
+ * common to the various different kinds of named entities in the Java language:
+ * packages, types, fields, methods, constructors, and local variables.
+ *
+ * @see IPackageBinding
+ * @see ITypeBinding
+ * @see IVariableBinding
+ * @see IMethodBinding
+ * @see IAnnotationBinding
+ * @see IMemberValuePairBinding
+ * @since 2.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IBinding {
+
+       /**
+        * Kind constant (value 1) indicating a package binding.
+        * Bindings of this kind can be safely cast to <code>IPackageBinding</code>.
+        *
+        * @see #getKind()
+        * @see IPackageBinding
+        */
+       public static final int PACKAGE = 1;
+
+       /**
+        * Kind constant (value 2) indicating a type binding.
+        * Bindings of this kind can be safely cast to <code>ITypeBinding</code>.
+        *
+        * @see #getKind()
+        * @see ITypeBinding
+        */
+       public static final int TYPE = 2;
+
+       /**
+        * Kind constant (value 3) indicating a field or local variable binding.
+        * Bindings of this kind can be safely cast to <code>IVariableBinding</code>.
+        *
+        * @see #getKind()
+        * @see IVariableBinding
+        */
+       public static final int VARIABLE = 3;
+
+       /**
+        * Kind constant (value 4) indicating a method or constructor binding.
+        * Bindings of this kind can be safely cast to <code>IMethodBinding</code>.
+        *
+        * @see #getKind()
+        * @see IMethodBinding
+        */
+       public static final int METHOD = 4;
+
+       /**
+        * Kind constant (value 5) indicating an annotation binding.
+        * Bindings of this kind can be safely cast to <code>IAnnotationBinding</code>.
+        *
+        * @see #getKind()
+        * @see IAnnotationBinding
+        * @since 3.2
+        */
+       public static final int ANNOTATION = 5;
+
+       /**
+        * Kind constant (value 6) indicating a member value pair binding.
+        * Bindings of this kind can be safely cast to <code>IMemberValuePairBinding</code>.
+        *
+        * @see #getKind()
+        * @see IMemberValuePairBinding
+        * @since 3.2
+        */
+       public static final int MEMBER_VALUE_PAIR = 6;
+
+       /**
+        * Return the resolved annotations associated with this binding.
+        * <ul>
+        * <li>Package bindings - these are annotations on a package declaration.
+        * </li>
+        * <li>Type bindings - these are annotations on a class, interface, enum,
+        * or annotation type declaration. The result is the same regardless of
+        * whether the type is parameterized.</li>
+        * <li>Method bindings - these are annotations on a method or constructor
+        * declaration. The result is the same regardless of whether the method is
+        * parameterized.</li>
+        * <li>Variable bindings - these are annotations on a field, enum constant,
+        * or formal parameter declaration.</li>
+        * <li>Annotation bindings - an empty array is always returned</li>
+        * <li>Member value pair bindings - an empty array is always returned<li>
+        * </ul>
+        *
+        * @return the list of resolved annotations, or the empty list if there are no
+        * annotations associated with the object
+        * @since 3.2
+        */
+       public IAnnotationBinding[] getAnnotations();
+
+       /**
+        * Returns the kind of bindings this is. That is one of the kind constants:
+        * <code>PACKAGE</code>,
+        *      <code>TYPE</code>,
+        *      <code>VARIABLE</code>,
+        *      <code>METHOD</code>,
+        *      <code>ANNOTATION</code>,
+        * or <code>MEMBER_VALUE_PAIR</code>.
+        * <p>
+        * Note that additional kinds might be added in the
+        * future, so clients should not assume this list is exhaustive and
+        * should program defensively, e.g. by having a reasonable default
+        * in a switch statement.
+        * </p>
+        * @return one of the kind constants
+        */
+       public int getKind();
+
+       /**
+        * Returns the name of this binding.
+        * Details of the name are specified with each specific kind of binding.
+        *
+        * @return the name of this binding
+        */
+       public String getName();
+
+       /**
+        * Returns the modifiers for this binding.
+        * <p>
+        * Note that deprecated is not included among the modifiers.
+        * Use <code>isDeprecated</code> to find out whether a binding is deprecated.
+        * </p>
+        *
+        * @return the bit-wise or of <code>Modifier</code> constants
+        * @see Modifier
+        */
+       public int getModifiers();
+
+       /**
+        * Return whether this binding is for something that is deprecated.
+        * A deprecated class, interface, field, method, or constructor is one that
+        * is marked with the 'deprecated' tag in its Javadoc comment.
+        *
+        * @return <code>true</code> if this binding is deprecated, and
+        *    <code>false</code> otherwise
+        */
+       public boolean isDeprecated();
+
+       /**
+        * Return whether this binding is created because the bindings recovery is enabled. This binding is considered
+        * to be incomplete. Its internal state might be incomplete.
+        *
+        * @return <code>true</code> if this binding is a recovered binding, and
+        *    <code>false</code> otherwise
+        * @since 3.3
+        */
+       public boolean isRecovered();
+
+       /**
+        * Returns whether this binding is synthetic. A synthetic binding is one that
+        * was made up by the compiler, rather than something declared in the
+        * source code. Note that default constructors (the 0-argument constructor that
+        * the compiler generates for class declarations with no explicit constructors
+        * declarations) are not generally considered synthetic (although they
+        * may be if the class itself is synthetic).
+        * But see {@link IMethodBinding#isDefaultConstructor() IMethodBinding.isDefaultConstructor}
+        * for cases where the compiled-generated default constructor can be recognized
+        * instead.
+        *
+        * @return <code>true</code> if this binding is synthetic, and
+        *    <code>false</code> otherwise
+        * @see IMethodBinding#isDefaultConstructor()
+        */
+       public boolean isSynthetic();
+
+       /**
+        * Returns the Java element that corresponds to this binding.
+        * Returns <code>null</code> if this binding has no corresponding
+        * Java element.
+        * <p>
+        * For array types, this method returns the Java element that corresponds
+        * to the array's element type. For raw and parameterized types, this method
+        * returns the Java element of the erasure. For annotations, this method
+        * returns the Java element of the annotation (i.e. an {@link IAnnotation}).
+        * </p>
+        * <p>
+        * Here are the cases where a <code>null</code> should be expected:
+        * <ul>
+        * <li>primitive types, including void</li>
+        * <li>null type</li>
+        * <li>wildcard types</li>
+        * <li>capture types</li>
+        * <li>array types of any of the above</li>
+        * <li>the "length" field of an array type</li>
+        * <li>the default constructor of a source class</li>
+        * <li>the constructor of an anonymous class</li>
+        * <li>member value pairs</li>
+        * </ul>
+        * For all other kind of type, method, variable, annotation and package bindings,
+        * this method returns non-<code>null</code>.
+        * </p>
+        *
+        * @return the Java element that corresponds to this binding,
+        *              or <code>null</code> if none
+        * @since 3.1
+        */
+       public IJavaElement getJavaElement();
+
+       /**
+        * Returns the key for this binding.
+        * <p>
+        * Within a connected cluster of bindings (for example, all bindings
+        * reachable from a given AST), each binding will have a distinct keys.
+        * The keys are generated in a manner that is predictable and as
+        * stable as possible. This last property makes these keys useful for
+        * comparing bindings between disconnected clusters of bindings (for example,
+        * the bindings between the "before" and "after" ASTs of the same
+        * compilation unit).
+        * </p>
+        * <p>
+        * The exact details of how the keys are generated is unspecified.
+        * However, it is a function of the following information:
+        * <ul>
+        * <li>packages - the name of the package (for an unnamed package,
+        *   some internal id)</li>
+        * <li>classes or interfaces - the VM name of the type and the key
+        *   of its package</li>
+        * <li>array types - the key of the component type and number of
+        *   dimensions</li>
+        * <li>primitive types - the name of the primitive type</li>
+        * <li>fields - the name of the field and the key of its declaring
+        *   type</li>
+        * <li>methods - the name of the method, the key of its declaring
+        *   type, and the keys of the parameter types</li>
+        * <li>constructors - the key of its declaring class, and the
+        *   keys of the parameter types</li>
+        * <li>local variables - the name of the local variable, the index of the
+        *   declaring block relative to its parent, the key of its method</li>
+        * <li>local types - the name of the type, the index of the declaring
+        *   block relative to its parent, the key of its method</li>
+        * <li>anonymous types - the occurence count of the anonymous
+        *   type relative to its declaring type, the key of its declaring type</li>
+        * <li>enum types - treated like classes</li>
+        * <li>annotation types - treated like interfaces</li>
+        * <li>type variables - the name of the type variable and
+        * the key of the generic type or generic method that declares that
+        * type variable</li>
+        * <li>wildcard types - the key of the optional wildcard type bound</li>
+     * <li>capture type bindings - the key of the wildcard captured</li>
+        * <li>generic type instances - the key of the generic type and the keys
+        * of the type arguments used to instantiate it, and whether the
+        * instance is explicit (a parameterized type reference) or
+        * implicit (a raw type reference)</li>
+        * <li>generic method instances - the key of the generic method and the keys
+        * of the type arguments used to instantiate it, and whether the
+        * instance is explicit (a parameterized method reference) or
+        * implicit (a raw method reference)</li>
+        * <li>members of generic type instances - the key of the generic type
+        * instance and the key of the corresponding member in the generic
+        * type</li>
+        * <li>annotations - the key of the annotated element and the key of
+        * the annotation type</li>
+        * </ul>
+        * </p>
+        * <p>Note that the key for member value pair bindings is
+        * not yet implemented. This returns <code>null</code> for this kind of bindings.<br>
+        * Recovered bindings have a unique key.
+        * </p>
+        *
+        * @return the key for this binding
+        */
+       public String getKey();
+
+       /**
+        * There is no special definition of equality for bindings; equality is
+        * simply object identity.  Within the context of a single cluster of
+        * bindings, each binding is represented by a distinct object. However,
+        * between different clusters of bindings, the binding objects may or may
+        * not be different; in these cases, the client should compare bindings
+        * using {@link #isEqualTo(IBinding)}, which checks their keys.
+        *
+        * @param obj {@inheritDoc}
+        * @return {@inheritDoc}
+        */
+       public boolean equals(Object obj);
+
+       /**
+        * Returns whether this binding has the same key as that of the given
+        * binding. Within the context of a single cluster of bindings, each
+        * binding is represented by a distinct object. However, between
+        * different clusters of bindings, the binding objects may or may
+        * not be different objects; in these cases, the binding keys
+        * are used where available.
+        *
+        * @param binding the other binding, or <code>null</code>
+        * @return <code>true</code> if the given binding is the identical
+        * object as this binding, or if the keys of both bindings are the
+        * same string; <code>false</code> if the given binding is
+        * <code>null</code>, or if the bindings do not have the same key,
+        * or if one or both of the bindings have no key
+        * @see #getKey()
+        * @since 3.1
+        */
+       public boolean isEqualTo(IBinding binding);
+
+       /**
+        * Returns a string representation of this binding suitable for debugging
+        * purposes only.
+        *
+        * @return a debug string
+        */
+       public String toString();
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IDocElement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IDocElement.java
new file mode 100644 (file)
index 0000000..e2f43e4
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Internal marker-type interface used to tag node types that can legitimately
+ * be included in {@link TagElement#fragments() TagElement.fragments()}.
+ *
+ * @since 3.0
+ */
+interface IDocElement {
+       // marker-type interfaces have no members
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IExtendedModifier.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IExtendedModifier.java
new file mode 100644 (file)
index 0000000..f523511
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Common interface for AST nodes that represent modifiers or
+ * annotations.
+ * <pre>
+ * ExtendedModifier:
+ *   Modifier
+ *   Annotation
+ * </pre>
+ * @since 3.1
+ */
+public interface IExtendedModifier {
+       
+       /**
+        * Returns whether this extended modifier is a standard modifier.
+        * 
+        * @return <code>true</code> if this is a standard modifier
+        * (instance of {@link Modifier}), and <code>false</code> otherwise
+        */ 
+       public boolean isModifier();
+       
+       /**
+        * Returns whether this extended modifier is an annotation.
+        * 
+        * @return <code>true</code> if this is an annotation
+        * (instance of a subclass of {@link Annotation}), and 
+        * <code>false</code> otherwise
+        */ 
+       public boolean isAnnotation();
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IMemberValuePairBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IMemberValuePairBinding.java
new file mode 100644 (file)
index 0000000..336995c
--- /dev/null
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 BEA Systems, Inc.
+ * 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:
+ *    tyeung@bea.com - initial API and implementation
+ *    IBM Corporation - changed interface to extend IBinding
+ *    IBM Corporation - renamed from IResolvedMemberValuePair to IMemberValuePairBinding
+ *******************************************************************************/
+package net.sourceforge.phpdt.core.dom;
+
+/**
+ * Represents a resolved instance of an annotation's member value pair.
+ * Resolved annotation are computed along with other bindings; these objects
+ * correspond to {@link MemberValuePair} nodes.
+ * 
+ * @since 3.2
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IMemberValuePairBinding extends IBinding {
+/**
+ * Returns the name of the annotation type member.
+ * 
+ * @return the name of the member
+ */
+public String getName();
+
+/**
+ * Returns the method binding corresponding to the named annotation type member.
+ * 
+ * @return the method binding for the annotation type member
+ */
+public IMethodBinding getMethodBinding();
+
+/**
+ * Returns the resolved value. Resolved values are represented as follows:
+ * <ul>
+ * <li>Primitive type - the equivalent boxed object</li>
+ * <li>java.lang.Class - the <code>ITypeBinding</code> for the class object</li>
+ * <li>java.lang.String - the string value itself</li>
+ * <li>enum type - the <code>IVariableBinding</code> for the enum constant</li>
+ * <li>annotation type - an <code>IAnnotationBinding</code></li>
+ * <li>array type - an <code>Object[]</code> whose elements are as per above
+ * (the language only allows single dimensional arrays in annotations)</li>
+ * </ul>
+ *     
+ * @return the resolved value, or <code>null</code> if none exists
+ */
+public Object getValue();
+
+/**
+ * @return <code>true</code> iff this member value pair's value is the default value.
+ *         Returns <code>false</code> otherwise.
+ */
+public boolean isDefault();
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IMethodBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IMethodBinding.java
new file mode 100644 (file)
index 0000000..d6a2e4f
--- /dev/null
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * A method binding represents a method or constructor of a class or interface.
+ * Method bindings usually correspond directly to method or
+ * constructor declarations found in the source code.
+ * However, in certain cases of references to a generic method,
+ * the method binding may correspond to a copy of a generic method
+ * declaration with substitutions for the method's type parameters
+ * (for these, <code>getTypeArguments</code> returns a non-empty
+ * list, and either <code>isParameterizedMethod</code> or
+ * <code>isRawMethod</code> returns <code>true</code>).
+ * And in certain cases of references to a method declared in a
+ * generic type, the method binding may correspond to a copy of a
+ * method declaration with substitutions for the type's type
+ * parameters (for these, <code>getTypeArguments</code> returns
+ * an empty list, and both <code>isParameterizedMethod</code> and
+ * <code>isRawMethod</code> return <code>false</code>).
+ *
+ * @see ITypeBinding#getDeclaredMethods()
+ * @since 2.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IMethodBinding extends IBinding {
+       
+       /**
+        * Returns whether this binding is for a constructor or a method.
+        * 
+        * @return <code>true</code> if this is the binding for a constructor,
+        *    and <code>false</code> if this is the binding for a method
+        */ 
+       public boolean isConstructor();
+
+       /**
+        * Returns whether this binding is known to be a compiler-generated 
+        * default constructor. 
+        * <p>
+        * This method returns <code>false</code> for:
+        * <ul>
+        * <li>methods</li>
+        * <li>constructors with more than one parameter</li>
+        * <li>0-argument constructors where the binding information was obtained
+        * from a Java source file containing an explicit 0-argument constructor
+        * declaration</li>
+        * <li>0-argument constructors where the binding information was obtained
+        * from a Java class file (it is not possible to determine from a
+        * class file whether a 0-argument constructor was present in the source
+        * code versus generated automatically by a Java compiler)</li>
+        * </ul>
+        * 
+        * @return <code>true</code> if this is known to be the binding for a 
+        * compiler-generated default constructor, and <code>false</code>
+        * otherwise
+        * @since 3.0
+        */ 
+       public boolean isDefaultConstructor();
+       
+       /**
+        * Returns the name of the method declared in this binding. The method name
+        * is always a simple identifier. The name of a constructor is always the
+        * same as the declared name of its declaring class.
+        * 
+        * @return the name of this method, or the declared name of this
+        *   constructor's declaring class
+        */
+       public String getName();
+       
+       /**
+        * Returns the type binding representing the class or interface
+        * that declares this method or constructor.
+        * 
+        * @return the binding of the class or interface that declares this method
+        *    or constructor
+        */
+       public ITypeBinding getDeclaringClass();
+
+       /**
+        * Returns the resolved default value of an annotation type member, 
+        * or <code>null</code> if the member has no default value, or if this
+        * is not the binding for an annotation type member.
+        * <p>
+        * Resolved values are represented as follows (same as for
+        * {@link IMemberValuePairBinding#getValue()}):
+        * <ul>
+        * <li>Primitive type - the equivalent boxed object</li>
+        * <li>java.lang.Class - the <code>ITypeBinding</code> for the class object</li>
+        * <li>java.lang.String - the string value itself</li>
+        * <li>enum type - the <code>IVariableBinding</code> for the enum constant</li>
+        * <li>annotation type - an <code>IAnnotationBinding</code></li>
+        * <li>array type - an <code>Object[]</code> whose elements are as per above
+        * (the language only allows single dimensional arrays in annotations)</li>
+        * </ul>
+        * 
+        * @return the default value of this annotation type member, or <code>null</code>
+        * if none or not applicable
+        * @since 3.2
+        */
+       public Object getDefaultValue();
+
+       /**
+        * Returns the resolved annotations of a parameter of this method.
+        * The result returned is the same regardless of whether 
+        * this is a parameterized method.
+        * 
+        * @param paramIndex the index of the parameter of interest
+        * @return the resolved annotations of the <code>paramIndex</code>th parameter,
+        * or an empty list if there are none
+        * @throws ArrayIndexOutOfBoundsException if <code>paramIndex</code> is 
+        * not a valid index
+        * @since 3.2
+        */
+       public IAnnotationBinding[] getParameterAnnotations(int paramIndex);
+
+       /**
+        * Returns a list of type bindings representing the formal parameter types,
+        * in declaration order, of this method or constructor. Returns an array of
+        * length 0 if this method or constructor does not takes any parameters.
+        * <p>
+        * Note that the binding for the last parameter type of a vararg method
+        * declaration like <code>void fun(Foo... args)</code> is always for
+        * an array type (i.e., <code>Foo[]</code>) reflecting the the way varargs
+        * get compiled. However, the type binding obtained directly from
+        * the <code>SingleVariableDeclaration</code> for the vararg parameter
+        * is always for the type as written; i.e., the type binding for
+        * <code>Foo</code>.
+        * </p>
+        * <p>
+        * Note: The result does not include synthetic parameters introduced by
+        * inner class emulation.
+        * </p>
+        * 
+        * @return a (possibly empty) list of type bindings for the formal
+        *   parameters of this method or constructor
+        */
+       public ITypeBinding[] getParameterTypes();
+
+       /**
+        * Returns the binding for the return type of this method. Returns the
+        * special primitive <code>void</code> return type for constructors.
+        * 
+        * @return the binding for the return type of this method, or the
+        *    <code>void</code> return type for constructors
+        */
+       public ITypeBinding getReturnType();
+
+       /**
+        * Returns a list of type bindings representing the types of the exceptions thrown
+        * by this method or constructor. Returns an array of length 0 if this method
+        * throws no exceptions. The resulting types are in no particular order.
+        * 
+        * @return a list of type bindings for exceptions
+        *   thrown by this method or constructor
+        */
+       public ITypeBinding[] getExceptionTypes();
+       
+       /**
+        * Returns the type parameters of this method or constructor binding.
+        * <p>
+        * Note that type parameters only occur on the binding of the
+        * declaring generic method. Type bindings corresponding to a raw or
+        * parameterized reference to a generic method do not carry type
+        * parameters (they instead have non-empty type arguments
+        * and non-trivial erasure).
+        * </p>
+        *
+        * @return the list of binding for the type variables for the type
+        * parameters of this method, or otherwise the empty list
+        * @see ITypeBinding#isTypeVariable()
+        * @since 3.1
+        */
+       public ITypeBinding[] getTypeParameters();
+
+       /**
+        * Returns whether this is the binding for an annotation type member.
+        * 
+        * @return <code>true</code> iff this is the binding for an annotation type member
+        *         and <code>false</code> otherwise
+        * @since 3.2
+        */
+       public boolean isAnnotationMember();
+
+       /**
+        * Returns whether this method binding represents a declaration of
+        * a generic method.
+        * <p>
+        * Note that type parameters only occur on the binding of the
+        * declaring generic method; e.g., <code>public &lt;T&gt; T identity(T t);</code>.
+        * Method bindings corresponding to a raw or parameterized reference to a generic
+        * method do not carry type parameters (they instead have non-empty type arguments
+        * and non-trivial erasure).
+        * This method is fully equivalent to <code>getTypeParameters().length &gt; 0)</code>.
+        * </p>
+        * <p>
+        * Note that {@link #isGenericMethod()},
+        * {@link #isParameterizedMethod()},
+        * and {@link #isRawMethod()} are mutually exclusive.
+        * </p>
+        *
+        * @return <code>true</code> if this method binding represents a 
+        * declaration of a generic method, and <code>false</code> otherwise
+        * @see #getTypeParameters()
+        * @since 3.1
+        */
+       public boolean isGenericMethod();
+       
+       /**
+        * Returns whether this method binding represents an instance of
+        * a generic method corresponding to a parameterized method reference.
+        * <p>
+        * Note that {@link #isGenericMethod()},
+        * {@link #isParameterizedMethod()},
+        * and {@link #isRawMethod()} are mutually exclusive.
+        * </p>
+        *
+        * @return <code>true</code> if this method binding represents a 
+        * an instance of a generic method corresponding to a parameterized
+        * method reference, and <code>false</code> otherwise
+        * @see #getMethodDeclaration()
+        * @see #getTypeArguments()
+        * @since 3.1
+        */
+       public boolean isParameterizedMethod();
+       
+       /**
+        * Returns the type arguments of this generic method instance, or the
+        * empty list for other method bindings.
+        * <p>
+        * Note that type arguments only occur on a method binding that represents
+        * an instance of a generic method corresponding to a raw or parameterized
+        * reference to a generic method. Do not confuse these with type parameters
+        * which only occur on the method binding corresponding directly to the
+        * declaration of a generic method.
+        * </p> 
+        *
+        * @return the list of type bindings for the type arguments used to
+        * instantiate the corrresponding generic method, or otherwise the empty list
+        * @see #getMethodDeclaration()
+        * @see #isParameterizedMethod()
+        * @see #isRawMethod()
+        * @since 3.1
+        */
+       public ITypeBinding[] getTypeArguments();
+       
+       /**
+        * Returns the binding for the method declaration corresponding to this
+        * method binding. For parameterized methods ({@link #isParameterizedMethod()})
+        * and raw methods ({@link #isRawMethod()}), this method returns the binding
+        * for the corresponding generic method. For other method bindings, this
+        * returns the same binding.
+        *
+        * <p>Note: The one notable exception is the method <code>Object.getClass()</code>, 
+        * which is declared to return <code>Class&lt;? extends Object&gt;</code>, but 
+        * when invoked its return type becomes <code>Class&lt;? extends 
+        * </code><em>R</em><code>&gt;</code>, where <em>R</em> is the compile type of 
+        * the receiver of the method invocation.</p>
+        *
+        * @return the method binding
+        * @since 3.1
+        */
+       public IMethodBinding getMethodDeclaration();
+       
+       /**
+        * Returns whether this method binding represents an instance of
+        * a generic method corresponding to a raw method reference.
+        * <p>
+        * Note that {@link #isGenericMethod()},
+        * {@link #isParameterizedMethod()},
+        * and {@link #isRawMethod()} are mutually exclusive.
+        * </p>
+        *
+        * @return <code>true</code> if this method binding represents a 
+        * an instance of a generic method corresponding to a raw
+        * method reference, and <code>false</code> otherwise
+        * @see #getMethodDeclaration()
+        * @see #getTypeArguments()
+        * @since 3.1
+        */
+       public boolean isRawMethod();
+       
+       /**
+        * Returns whether this method's signature is a subsignature of the given method as
+        * specified in section 8.4.2 of <em>The Java Language Specification, Third Edition</em> (JLS3). 
+        * 
+        * @return <code>true</code> if this method's signature is a subsignature of the given method
+        * @since 3.1
+        */
+       public boolean isSubsignature(IMethodBinding otherMethod);
+       
+       /**
+        * Returns whether this is a variable arity method.
+        * <p>
+        * Note: Variable arity ("varargs") methods were added in JLS3.
+        * </p>
+        * 
+        * @return <code>true</code> if this is a variable arity method,
+        *    and <code>false</code> otherwise
+        * @since 3.1
+        */ 
+       public boolean isVarargs();
+       
+       /**
+        * Returns whether this method overrides the given method,
+        * as specified in section 8.4.8.1 of <em>The Java Language 
+        * Specification, Third Edition</em> (JLS3).
+        * 
+        * @param method the method that is possibly overriden
+        * @return <code>true</code> if this method overrides the given method,
+        * and <code>false</code> otherwise
+        * @since 3.1
+        */
+       public boolean overrides(IMethodBinding method);
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IPackageBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IPackageBinding.java
new file mode 100644 (file)
index 0000000..9492d52
--- /dev/null
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * A package binding represents a named or unnamed package.
+ * 
+ * @since 2.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IPackageBinding extends IBinding {
+
+       /**
+        * Returns the name of the package represented by this binding. For named
+        * packages, this is the fully qualified package name (using "." for 
+        * separators). For unnamed packages, this is an empty string.
+        * 
+        * @return the name of the package represented by this binding, or
+        *    an empty string for an unnamed package
+        */
+       public String getName();
+       
+       /**
+        * Returns whether this package is an unnamed package.
+        * See <em>The Java Language Specification</em> section 7.4.2 for details.
+        *
+        * @return <code>true</code> if this is an unnamed package, and
+        *    <code>false</code> otherwise
+        */
+       public boolean isUnnamed();
+       
+       /**
+        * Returns the list of name component making up the name of the package
+        * represented by this binding. For example, for the package named
+        * "com.example.tool", this method returns {"com", "example", "tool"}.
+        * Returns the empty list for unnamed packages.
+        * 
+        * @return the name of the package represented by this binding, or the
+        *    empty list for unnamed packages
+        */
+       public String[] getNameComponents();
+       
+//     /**
+//      * Finds and returns the binding for the class or interface with the given
+//      * name declared in this package.
+//      * <p>
+//      * For top-level classes and interfaces, the name here is just the simple
+//      * name of the class or interface. For nested classes and interfaces, the
+//      * name is the VM class name (in other words, a name like 
+//      * <code>"Outer$Inner"</code> as used to name the class file; see
+//      * <code>ITypeBinding.getName</code>).
+//      * </p>
+//      *
+//      * @param name the name of a class or interface
+//      * @return the type binding for the class or interface with the
+//      *   given name declared in this package, or <code>null</code>
+//      *   if there is no such type
+//      */
+//     public ITypeBinding findTypeBinding(String name);
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ITypeBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ITypeBinding.java
new file mode 100644 (file)
index 0000000..5e9e93c
--- /dev/null
@@ -0,0 +1,931 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * A type binding represents fully-resolved type. There are a number of
+ * different kinds of type bindings:
+ * <ul>
+ * <li>a class - represents the class declaration;
+ * possibly with type parameters</li>
+ * <li>an interface - represents the class declaration;
+ * possibly with type parameters</li>
+ * <li>an enum - represents the enum declaration (enum types do not have
+ * have type parameters)</li>
+ * <li>an annotation - represents the annotation type declaration
+ * (annotation types do not have have type parameters)</li>
+ * <li>an array type - array types are referenced but not explicitly
+ * declared</li>
+ * <li>a primitive type (including the special return type <code>void</code>)
+ * - primitive types are referenced but not explicitly declared</li>
+ * <li>the null type - this is the special type of <code>null</code></li>
+ * <li>a type variable - represents the declaration of a type variable;
+ * possibly with type bounds</li>
+ * <li>a wildcard type - represents a wild card used as a type argument in
+ * a parameterized type reference</li>
+ * <li>a raw type - represents a legacy non-parameterized reference to
+ * a generic type</li>
+ * <li>a parameterized type - represents an copy of a type declaration
+ * with substitutions for its type parameters</li>
+ * <li>a capture - represents a capture binding</li>
+ * </ul>
+ *
+ * @see ITypeBinding#getDeclaredTypes()
+ * @since 2.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface ITypeBinding extends IBinding {
+
+
+       /**
+        * Answer an array type binding using the receiver and the given dimension.
+        *
+        * <p>If the receiver is an array binding, then the resulting dimension is the given dimension
+        * plus the dimension of the receiver. Otherwise the resulting dimension is the given
+        * dimension.</p>
+        *
+        * @param dimension the given dimension
+        * @return an array type binding
+        * @throws IllegalArgumentException:<ul>
+        * <li>if the receiver represents the void type</li>
+        * <li>if the resulting dimensions is lower than one or greater than 255</li>
+        * </ul>
+        * @since 3.3
+        */
+       public ITypeBinding createArrayType(int dimension);
+
+       /**
+        * Returns the binary name of this type binding.
+        * The binary name of a class is defined in the Java Language
+        * Specification 3rd edition, section 13.1.
+        * <p>
+        * Note that in some cases, the binary name may be unavailable.
+        * This may happen, for example, for a local type declared in
+        * unreachable code.
+        * </p>
+        *
+        * @return the binary name of this type, or <code>null</code>
+        * if the binary name is unknown
+        * @since 3.0
+        */
+       public String getBinaryName();
+
+       /**
+        * Returns the bound of this wildcard type if it has one.
+        * Returns <code>null</code> if this is not a wildcard type.
+        *
+        * @return the bound of this wildcard type, or <code>null</code> if none
+        * @see #isWildcardType()
+        * @see #isUpperbound()
+        * @since 3.1
+        */
+       public ITypeBinding getBound();
+
+       /**
+        * Returns the binding representing the component type of this array type,
+        * or <code>null</code> if this is not an array type binding. The component
+        * type of an array might be an array type.
+        * <p>This is subject to change before 3.2 release.</p>
+        *
+        * @return the component type binding, or <code>null</code> if this is
+        *   not an array type
+        * @since 3.2
+        */
+       public ITypeBinding getComponentType();
+
+       /**
+        * Returns a list of bindings representing all the fields declared
+        * as members of this class, interface, or enum type.
+        * 
+        * <p>These include public, protected, default (package-private) access,
+        * and private fields declared by the class, but excludes inherited fields.
+        * Synthetic fields may or may not be included. Fields from binary types that
+        * reference unresolvable types may not be included.</p>
+        *
+        * <p>Returns an empty list if the class, interface, or enum declares no fields,
+        * and for other kinds of type bindings that do not directly have members.</p>
+        *
+        * <p>The resulting bindings are in no particular order.</p>
+        *
+        * @return the list of bindings for the field members of this type,
+        *   or the empty list if this type does not have field members
+        */
+       public IVariableBinding[] getDeclaredFields();
+
+       /**
+        * Returns a list of method bindings representing all the methods and
+        * constructors declared for this class, interface, enum, or annotation
+        * type.
+        * <p>These include public, protected, default (package-private) access,
+        * and private methods Synthetic methods and constructors may or may not be
+        * included. Returns an empty list if the class, interface, or enum,
+        * type declares no methods or constructors, if the annotation type declares
+        * no members, or if this type binding represents some other kind of type
+        * binding. Methods from binary types that reference unresolvable types may
+        * not be included.</p>
+        * <p>The resulting bindings are in no particular order.</p>
+        *
+        * @return the list of method bindings for the methods and constructors
+        *   declared by this class, interface, enum type, or annotation type,
+        *   or the empty list if this type does not declare any methods or constructors
+        */
+       public IMethodBinding[] getDeclaredMethods();
+
+       /**
+        * Returns the declared modifiers for this class or interface binding
+        * as specified in the original source declaration of the class or
+        * interface. The result may not correspond to the modifiers in the compiled
+        * binary, since the compiler may change them (in particular, for inner
+        * class emulation). The <code>getModifiers</code> method should be used if
+        * the compiled modifiers are needed. Returns -1 if this type does not
+        * represent a class or interface.
+        *
+        * @return the bit-wise or of <code>Modifier</code> constants
+        * @see #getModifiers()
+        * @see Modifier
+        */
+       public int getDeclaredModifiers();
+
+       /**
+        * Returns a list of type bindings representing all the types declared as
+        * members of this class, interface, or enum type.
+        * These include public, protected, default (package-private) access,
+        * and private classes, interfaces, enum types, and annotation types
+        * declared by the type, but excludes inherited types. Returns an empty
+        * list if the type declares no type members, or if this type
+        * binding represents an array type, a primitive type, a type variable,
+        * a wildcard type, a capture, or the null type.
+        * The resulting bindings are in no particular order.
+        *
+        * @return the list of type bindings for the member types of this type,
+        *   or the empty list if this type does not have member types
+        */
+       public ITypeBinding[] getDeclaredTypes();
+
+       /**
+        * Returns the type binding representing the class, interface, or enum
+        * that declares this binding.
+        * <p>
+        * The declaring class of a member class, interface, enum, annotation
+        * type is the class, interface, or enum type of which it is a member.
+        * The declaring class of a local class or interface (including anonymous
+        * classes) is the innermost class or interface containing the expression
+        * or statement in which this type is declared.
+        * </p>
+        * <p>The declaring class of a type variable is the class in which the type
+        * variable is declared if it is declared on a type. It returns
+        * <code>null</code> otherwise.
+        * </p>
+        * <p>The declaring class of a capture binding is the innermost class or
+        * interface containing the expression or statement in which this capture is
+        * declared.
+        * </p>
+        * <p>Array types, primitive types, the null type, top-level types,
+        * wildcard types, recovered binding have no declaring class.
+        * </p>
+        *
+        * @return the binding of the type that declares this type, or
+        * <code>null</code> if none
+        */
+       public ITypeBinding getDeclaringClass();
+
+       /**
+        * Returns the method binding representing the method that declares this binding
+        * of a local type or type variable.
+        * <p>
+        * The declaring method of a local class or interface (including anonymous
+        * classes) is the innermost method containing the expression or statement in
+        * which this type is declared. Returns <code>null</code> if the type
+        * is declared in an initializer.
+        * </p>
+        * <p>
+        * The declaring method of a type variable is the method in which the type
+        * variable is declared if it is declared on a method. It
+        * returns <code>null</code> otherwise.
+        * </p>
+        * <p>Array types, primitive types, the null type, top-level types,
+        * wildcard types, capture bindings, and recovered binding have no
+        * declaring method.
+        * </p>
+        *
+        * @return the binding of the method that declares this type, or
+        * <code>null</code> if none
+        * @since 3.1
+        */
+       public IMethodBinding getDeclaringMethod();
+
+       /**
+        * Returns the dimensionality of this array type, or <code>0</code> if this
+        * is not an array type binding.
+        *
+        * @return the number of dimension of this array type binding, or
+        *   <code>0</code> if this is not an array type
+        */
+       public int getDimensions();
+
+       /**
+        * Returns the binding representing the element type of this array type,
+        * or <code>null</code> if this is not an array type binding. The element
+        * type of an array is never itself an array type.
+        *
+        * @return the element type binding, or <code>null</code> if this is
+        *   not an array type
+        */
+       public ITypeBinding getElementType();
+
+       /**
+        * Returns the erasure of this type binding.
+        * <ul>
+        * <li>For parameterized types ({@link #isParameterizedType()})
+        * - returns the binding for the corresponding generic type.</li>
+        * <li>For raw types ({@link #isRawType()})
+        * - returns the binding for the corresponding generic type.</li>
+        * <li>For wildcard types ({@link #isWildcardType()})
+        * - returns the binding for the upper bound if it has one and
+        * java.lang.Object in other cases.</li>
+        * <li>For type variables ({@link #isTypeVariable()})
+        * - returns the binding for the erasure of the leftmost bound
+        * if it has bounds and java.lang.Object if it does not.</li>
+        * <li>For captures ({@link #isCapture()})
+        * - returns the binding for the erasure of the leftmost bound
+        * if it has bounds and java.lang.Object if it does not.</li>
+        * <li>For array types ({@link #isArray()}) - returns an array type of
+        * the same dimension ({@link #getDimensions()}) as this type
+        * binding for which the element type is the erasure of the element type
+        * ({@link #getElementType()}) of this type binding.</li>
+        * <li>For all other type bindings - returns the identical binding.</li>
+        * </ul>
+        *
+        * @return the erasure type binding
+        * @since 3.1
+        */
+       public ITypeBinding getErasure();
+
+       /**
+        * Returns a list of type bindings representing the direct superinterfaces
+        * of the class, interface, or enum type represented by this type binding.
+        * <p>
+        * If this type binding represents a class or enum type, the return value
+        * is an array containing type bindings representing all interfaces
+        * directly implemented by this class. The number and order of the interface
+        * objects in the array corresponds to the number and order of the interface
+        * names in the <code>implements</code> clause of the original declaration
+        * of this type.
+        * </p>
+        * <p>
+        * If this type binding represents an interface, the array contains
+        * type bindings representing all interfaces directly extended by this
+        * interface. The number and order of the interface objects in the array
+        * corresponds to the number and order of the interface names in the
+        * <code>extends</code> clause of the original declaration of this interface.
+        * </p>
+        * <p>
+        * If the class or enum implements no interfaces, or the interface extends
+        * no interfaces, or if this type binding represents an array type, a
+        * primitive type, the null type, a type variable, an annotation type,
+        * a wildcard type, or a capture binding, this method returns an array of
+     * length 0.
+        * </p>
+        *
+        * @return the list of type bindings for the interfaces extended by this
+        *   class or enum, or interfaces extended by this interface, or otherwise
+        *   the empty list
+        */
+       public ITypeBinding[] getInterfaces();
+
+       /**
+        * Returns the compiled modifiers for this class, interface, enum,
+        * or annotation type binding.
+        * The result may not correspond to the modifiers as declared in the
+        * original source, since the compiler may change them (in particular,
+        * for inner class emulation). The <code>getDeclaredModifiers</code> method
+        * should be used if the original modifiers are needed.
+        * Returns 0 if this type does not represent a class, an interface, an enum, an annotation
+        * type or a recovered type.
+        *
+        * @return the compiled modifiers for this type binding or 0
+        * if this type does not represent a class, an interface, an enum, an annotation
+        * type or a recovered type.
+        * @see #getDeclaredModifiers()
+        */
+       public int getModifiers();
+
+       /**
+        * Returns the unqualified name of the type represented by this binding
+        * if it has one.
+        * <ul>
+        * <li>For top-level types, member types, and local types,
+        * the name is the simple name of the type.
+        * Example: <code>"String"</code> or <code>"Collection"</code>.
+        * Note that the type parameters of a generic type are not included.</li>
+        * <li>For primitive types, the name is the keyword for the primitive type.
+        * Example: <code>"int"</code>.</li>
+        * <li>For the null type, the name is the string "null".</li>
+        * <li>For anonymous classes, which do not have a name,
+        * this method returns an empty string.</li>
+        * <li>For array types, the name is the unqualified name of the component
+        * type (as computed by this method) followed by "[]".
+        * Example: <code>"String[]"</code>. Note that the component type is never an
+        * an anonymous class.</li>
+        * <li>For type variables, the name is just the simple name of the
+        * type variable (type bounds are not included).
+        * Example: <code>"X"</code>.</li>
+        * <li>For type bindings that correspond to particular instances of a generic
+        * type arising from a parameterized type reference,
+        * the name is the unqualified name of the erasure type (as computed by this method)
+        * followed by the names (again, as computed by this method) of the type arguments
+        * surrounded by "&lt;&gt;" and separated by ",".
+        * Example: <code>"Collection&lt;String&gt;"</code>.
+        * </li>
+        * <li>For type bindings that correspond to particular instances of a generic
+        * type arising from a raw type reference, the name is the unqualified name of
+        * the erasure type (as computed by this method).
+        * Example: <code>"Collection"</code>.</li>
+        * <li>For wildcard types, the name is "?" optionally followed by
+        * a single space followed by the keyword "extends" or "super"
+        * followed a single space followed by the name of the bound (as computed by
+        * this method) when present.
+        * Example: <code>"? extends InputStream"</code>.
+        * </li>
+     * <li>Capture types do not have a name. For these types,
+     * and array types thereof, this method returns an empty string.</li>
+        * </ul>
+        *
+        * @return the unqualified name of the type represented by this binding,
+        * or the empty string if it has none
+        * @see #getQualifiedName()
+        */
+       public String getName();
+
+       /**
+        * Returns the binding for the package in which this type is declared.
+        *
+        * <p>The package of a recovered type reference binding is either
+        * the package of the enclosing type, or, if the type name is the name of a
+        * {@linkplain AST#resolveWellKnownType(String) well-known type},
+        * the package of the matching well-known type.</p>
+        * 
+        * @return the binding for the package in which this class, interface,
+        * enum, or annotation type is declared, or <code>null</code> if this type
+        * binding represents a primitive type, an array type, the null type,
+        * a type variable, a wildcard type, a capture binding.
+        */
+       public IPackageBinding getPackage();
+
+       /**
+        * Returns the fully qualified name of the type represented by this
+        * binding if it has one.
+        * <ul>
+        * <li>For top-level types, the fully qualified name is the simple name of
+        * the type preceded by the package name (or unqualified if in a default package)
+        * and a ".".
+        * Example: <code>"java.lang.String"</code> or <code>"java.util.Collection"</code>.
+        * Note that the type parameters of a generic type are not included.</li>
+        * <li>For members of top-level types, the fully qualified name is the
+        * simple name of the type preceded by the fully qualified name of the
+        * enclosing type (as computed by this method) and a ".".
+        * Example: <code>"java.io.ObjectInputStream.GetField"</code>.
+        * If the binding is for a member type that corresponds to a particular instance
+        * of a generic type arising from a parameterized type reference, the simple
+        * name of the type is followed by the fully qualified names of the type arguments
+        * (as computed by this method) surrounded by "&lt;&gt;" and separated by ",".
+        * Example: <code>"pkg.Outer.Inner&lt;java.lang.String&gt;"</code>.
+        * </li>
+        * <li>For primitive types, the fully qualified name is the keyword for
+        * the primitive type.
+        * Example: <code>"int"</code>.</li>
+        * <li>For the null type, the fully qualified name is the string
+        * "null".</li>
+        * <li>Local types (including anonymous classes) and members of local
+        * types do not have a fully qualified name. For these types, and array
+        * types thereof, this method returns an empty string.</li>
+        * <li>For array types whose component type has a fully qualified name,
+        * the fully qualified name is the fully qualified name of the component
+        * type (as computed by this method) followed by "[]".
+        * Example: <code>"java.lang.String[]"</code>.</li>
+        * <li>For type variables, the fully qualified name is just the name of the
+        * type variable (type bounds are not included).
+        * Example: <code>"X"</code>.</li>
+        * <li>For type bindings that correspond to particular instances of a generic
+        * type arising from a parameterized type reference,
+        * the fully qualified name is the fully qualified name of the erasure
+        * type followed by the fully qualified names of the type arguments surrounded by "&lt;&gt;" and separated by ",".
+        * Example: <code>"java.util.Collection&lt;java.lang.String&gt;"</code>.
+        * </li>
+        * <li>For type bindings that correspond to particular instances of a generic
+        * type arising from a raw type reference,
+        * the fully qualified name is the fully qualified name of the erasure type.
+        * Example: <code>"java.util.Collection"</code>. Note that the
+        * the type parameters are omitted.</li>
+        * <li>For wildcard types, the fully qualified name is "?" optionally followed by
+        * a single space followed by the keyword "extends" or "super"
+        * followed a single space followed by the fully qualified name of the bound
+        * (as computed by this method) when present.
+        * Example: <code>"? extends java.io.InputStream"</code>.
+        * </li>
+    * <li>Capture types do not have a fully qualified name. For these types,
+    * and array types thereof, this method returns an empty string.</li>
+        * </ul>
+        *
+        * @return the fully qualified name of the type represented by this
+        *    binding, or the empty string if it has none
+        * @see #getName()
+        * @since 2.1
+        */
+       public String getQualifiedName();
+
+       /**
+        * Returns the type binding for the superclass of the type represented
+        * by this class binding.
+        * <p>
+        * If this type binding represents any class other than the class
+        * <code>java.lang.Object</code>, then the type binding for the direct
+        * superclass of this class is returned. If this type binding represents
+        * the class <code>java.lang.Object</code>, then <code>null</code> is
+        * returned.
+        * <p>
+        * Loops that ascend the class hierarchy need a suitable termination test.
+        * Rather than test the superclass for <code>null</code>, it is more
+        * transparent to check whether the class is <code>Object</code>, by
+        * comparing whether the class binding is identical to
+        * <code>ast.resolveWellKnownType("java.lang.Object")</code>.
+        * </p>
+        * <p>
+        * If this type binding represents an interface, an array type, a
+        * primitive type, the null type, a type variable, an enum type,
+        * an annotation type, a wildcard type, or a capture binding then
+        * <code>null</code> is returned.
+        * </p>
+        *
+        * @return the superclass of the class represented by this type binding,
+        *    or <code>null</code> if none
+        * @see AST#resolveWellKnownType(String)
+        */
+       public ITypeBinding getSuperclass();
+
+       /**
+        * Returns the type arguments of this generic type instance, or the
+        * empty list for other type bindings.
+        * <p>
+        * Note that type arguments only occur on a type binding that represents
+        * an instance of a generic type corresponding to a parameterized type
+        * reference (e.g., <code>Collection&lt;String&gt;</code>).
+        * Do not confuse these with type parameters which only occur on the
+        * type binding corresponding directly to the declaration of the
+        * generic class or interface (e.g., <code>Collection&lt;T&gt;</code>).
+        * </p>
+        *
+        * @return the list of type bindings for the type arguments used to
+        * instantiate the corresponding generic type, or otherwise the empty list
+        * @see #getTypeDeclaration()
+        * @see #isGenericType()
+        * @see #isParameterizedType()
+        * @see #isRawType()
+        * @since 3.1
+        */
+       public ITypeBinding[] getTypeArguments();
+
+       /**
+        * Returns the declared type bounds of this type variable or capture. If the
+        * variable or the capture had no explicit bound, then it returns an empty list.
+     * <p>
+     * Note that per construction, it can only contain one class or array type,
+     * at most, and then it is located in first position.
+     * </p>
+     * <p>
+     * Also note that array type bound may only occur in the case of a capture
+     * binding, e.g. <code>capture-of ? extends Object[]</code>
+     * </p>
+        *
+        * @return the list of type bindings for this type variable or capture,
+     * or otherwise the empty list
+        * @see #isCapture()
+        * @see #isTypeVariable()
+        * @since 3.1
+        */
+       public ITypeBinding[] getTypeBounds();
+
+       /**
+        * Returns the binding for the type declaration corresponding to this type
+        * binding.
+        * <p>For parameterized types ({@link #isParameterizedType()})
+        * and most raw types ({@link #isRawType()}), this method returns the binding
+        * for the corresponding generic type.</p>
+        * <p>For raw member types ({@link #isRawType()}, {@link #isMember()})
+        * of a raw declaring class, the type declaration is a generic or a non-generic
+        * type.</p>
+        * <p>A different non-generic binding will be returned when one of the declaring
+        * types/methods was parameterized.</p>
+        * <p>For other type bindings, this returns the same binding.</p>
+        *
+        * @return the type binding
+        * @since 3.1
+        */
+       public ITypeBinding getTypeDeclaration();
+
+       /**
+        * Returns the type parameters of this class or interface type binding.
+        * <p>
+        * Note that type parameters only occur on the binding of the
+        * declaring generic class or interface; e.g., <code>Collection&lt;T&gt;</code>.
+        * Type bindings corresponding to a raw or parameterized reference to a generic
+        * type do not carry type parameters (they instead have non-empty type arguments
+        * and non-trivial erasure).
+        * </p>
+        *
+        * @return the list of binding for the type variables for the type
+        * parameters of this type, or otherwise the empty list
+        * @see #isTypeVariable()
+        * @since 3.1
+        */
+       // TODO (jeem) - clarify whether binding for a generic type instance carries a copy of the generic type's type parameters as well as type arguments
+       public ITypeBinding[] getTypeParameters();
+
+       /**
+        * Returns the corresponding wildcard binding of this capture binding.
+     * Returns <code>null</code> if this type bindings does not represent
+     * a capture binding.
+        *
+        * @return the corresponding wildcard binding for a capture
+        * binding, <code>null</code> otherwise
+        * @since 3.1
+        */
+       public ITypeBinding getWildcard();
+
+       /**
+        * Returns whether this type binding represents an annotation type.
+        * <p>
+        * Note that an annotation type is always an interface.
+        * </p>
+        *
+        * @return <code>true</code> if this object represents an annotation type,
+        *    and <code>false</code> otherwise
+        * @since 3.1
+        */
+       public boolean isAnnotation();
+
+       /**
+        * Returns whether this type binding represents an anonymous class.
+        * <p>
+        * An anonymous class is a subspecies of local class, and therefore mutually
+        * exclusive with member types. Note that anonymous classes have no name
+        * (<code>getName</code> returns the empty string).
+        * </p>
+        *
+        * @return <code>true</code> if this type binding is for an anonymous class,
+        *   and <code>false</code> otherwise
+        */
+       public boolean isAnonymous();
+
+       /**
+        * Returns whether this type binding represents an array type.
+        *
+        * @return <code>true</code> if this type binding is for an array type,
+        *   and <code>false</code> otherwise
+        * @see #getElementType()
+        * @see #getDimensions()
+        */
+       public boolean isArray();
+
+       /**
+        * Returns whether an expression of this type can be assigned to a variable
+        * of the given type, as specified in section 5.2 of <em>The Java Language
+        * Specification, Third Edition</em> (JLS3).
+        *
+        * <p>If the receiver or the argument is a recovered type, the answer is always false,
+        * unless the two types are identical or the argument is <code>java.lang.Object</code>.</p>
+        *
+        * @param variableType the type of a variable to check compatibility against
+        * @return <code>true</code> if an expression of this type can be assigned to a
+        *   variable of the given type, and <code>false</code> otherwise
+        * @since 3.1
+        */
+       public boolean isAssignmentCompatible(ITypeBinding variableType);
+
+       /**
+        * Returns whether this type binding represents a capture binding.
+        * <p>
+        * Capture bindings result from capture conversion as specified
+        * in section 5.1.10 of <em>The Java Language Specification,
+        * Third Edition</em> (JLS3).
+        * </p>
+        * <p>
+        * A capture binding may have upper bounds and a lower bound.
+        * Upper bounds may be accessed using {@link #getTypeBounds()},
+        * the lower bound must be accessed indirectly through the associated
+        * wildcard {@link #getWildcard()} when it is a lower bound wildcard.
+        * </p>
+        * <p>
+        * Note that capture bindings are distinct from type variables
+     * (even though they are often depicted as synthetic type
+     * variables); as such, {@link #isTypeVariable()} answers
+     * <code>false</code> for capture bindings, and
+     * {@link #isCapture()} answers <code>false</code> for type variables.
+        * </p>
+     *
+        * @return <code>true</code> if this type binding is a capture,
+        *   and <code>false</code> otherwise
+        * @see #getTypeBounds()
+        * @see #getWildcard()
+        * @since 3.1
+        */
+       public boolean isCapture();
+
+       /**
+        * Returns whether this type is cast compatible with the given type,
+        * as specified in section 5.5 of <em>The Java Language
+        * Specification, Third Edition</em> (JLS3).
+        * <p>
+        * NOTE: The cast compatibility check performs backwards.
+        * When testing whether type B can be cast to type A, one would use:
+        * <code>A.isCastCompatible(B)</code>
+        * </p>
+        *
+        * <p>If the receiver or the argument is a recovered type, the answer is always false,
+        * unless the two types are identical or the argument is <code>java.lang.Object</code>.</p>
+        *
+        * @param type the type to check compatibility against
+        * @return <code>true</code> if this type is cast compatible with the
+        * given type, and <code>false</code> otherwise
+        * @since 3.1
+        */
+       public boolean isCastCompatible(ITypeBinding type);
+
+       /**
+        * Returns whether this type binding represents a class type or a recovered binding.
+        *
+        * @return <code>true</code> if this object represents a class or a recovered binding,
+        *    and <code>false</code> otherwise
+        */
+       public boolean isClass();
+
+       /**
+        * Returns whether this type binding represents an enum type.
+        *
+        * @return <code>true</code> if this object represents an enum type,
+        *    and <code>false</code> otherwise
+        * @since 3.1
+        */
+       public boolean isEnum();
+
+       /**
+        * Returns whether this type binding originated in source code.
+        * Returns <code>false</code> for all primitive types, the null type,
+        * array types, and for all classes, interfaces, enums, annotation
+        * types, type variables, parameterized type references,
+        * raw type references, wildcard types, and capture bindings
+     * whose information came from a pre-compiled binary class file.
+        *
+        * @return <code>true</code> if the type is in source code,
+        *    and <code>false</code> otherwise
+        */
+       public boolean isFromSource();
+
+       /**
+        * Returns whether this type binding represents a declaration of
+        * a generic class or interface.
+        * <p>
+        * Note that type parameters only occur on the binding of the
+        * declaring generic class or interface; e.g., <code>Collection&lt;T&gt;</code>.
+        * Type bindings corresponding to a raw or parameterized reference to a generic
+        * type do not carry type parameters (they instead have non-empty type arguments
+        * and non-trivial erasure).
+        * This method is fully equivalent to <code>getTypeParameters().length &gt; 0)</code>.
+        * </p>
+        * <p>
+        * Note that {@link #isGenericType()},
+        * {@link #isParameterizedType()},
+        * and {@link #isRawType()} are mutually exclusive.
+        * </p>
+        *
+        * @return <code>true</code> if this type binding represents a
+        * declaration of a generic class or interface, and <code>false</code> otherwise
+        * @see #getTypeParameters()
+        * @since 3.1
+        */
+       public boolean isGenericType();
+
+       /**
+        * Returns whether this type binding represents an interface type.
+        * <p>
+        * Note that an interface can also be an annotation type.
+        * </p>
+        *
+        * @return <code>true</code> if this object represents an interface,
+        *    and <code>false</code> otherwise
+        */
+       public boolean isInterface();
+
+       /**
+        * Returns whether this type binding represents a local class.
+        * <p>
+        * A local class is any nested class or enum type not declared as a member
+        * of another class or interface. A local class is a subspecies of nested
+        * type, and mutually exclusive with member types. Note that anonymous
+        * classes are a subspecies of local classes.
+        * </p>
+        * <p>
+        * Also note that interfaces and annotation types cannot be local.
+        * </p>
+        *
+        * @return <code>true</code> if this type binding is for a local class or
+        * enum type, and <code>false</code> otherwise
+        */
+       public boolean isLocal();
+
+       /**
+        * Returns whether this type binding represents a member class or
+        * interface.
+        * <p>
+        * A member type is any type declared as a member of
+        * another type. A member type is a subspecies of nested
+        * type, and mutually exclusive with local types.
+        * </p>
+        *
+        * @return <code>true</code> if this type binding is for a member class,
+        *   interface, enum, or annotation type, and <code>false</code> otherwise
+        */
+       public boolean isMember();
+
+       /**
+        * Returns whether this type binding represents a nested class, interface,
+        * enum, or annotation type.
+        * <p>
+        * A nested type is any type whose declaration occurs within
+        * the body of another. The set of nested types is disjoint from the set of
+        * top-level types. Nested types further subdivide into member types, local
+        * types, and anonymous types.
+        * </p>
+        *
+        * @return <code>true</code> if this type binding is for a nested class,
+        *   interface, enum, or annotation type, and <code>false</code> otherwise
+        */
+       public boolean isNested();
+
+       /**
+        * Returns whether this type binding represents the null type.
+        * <p>
+        * The null type is the type of a <code>NullLiteral</code> node.
+        * </p>
+        *
+        * @return <code>true</code> if this type binding is for the null type,
+        *   and <code>false</code> otherwise
+        */
+       public boolean isNullType();
+
+       /**
+        * Returns whether this type binding represents an instance of
+        * a generic type corresponding to a parameterized type reference.
+        * <p>
+        * For example, an AST type like
+        * <code>Collection&lt;String&gt;</code> typically resolves to a
+        * type binding whose type argument is the type binding for the
+        * class <code>java.lang.String</code> and whose erasure is the type
+        * binding for the generic type <code>java.util.Collection</code>.
+        * </p>
+        * <p>
+        * Note that {@link #isGenericType()},
+        * {@link #isParameterizedType()},
+        * and {@link #isRawType()} are mutually exclusive.
+        * </p>
+        *
+        * @return <code>true</code> if this type binding represents a
+        * an instance of a generic type corresponding to a parameterized
+        * type reference, and <code>false</code> otherwise
+        * @see #getTypeArguments()
+        * @see #getTypeDeclaration()
+        * @since 3.1
+        */
+       public boolean isParameterizedType();
+
+       /**
+        * Returns whether this type binding represents a primitive type.
+        * <p>
+        * There are nine predefined type bindings to represent the eight primitive
+        * types and <code>void</code>. These have the same names as the primitive
+        * types that they represent, namely boolean, byte, char, short, int,
+        * long, float, and double, and void.
+        * </p>
+        *
+        * @return <code>true</code> if this type binding is for a primitive type,
+        *   and <code>false</code> otherwise
+        */
+       public boolean isPrimitive();
+
+       /**
+        * Returns whether this type binding represents an instance of
+        * a generic type corresponding to a raw type reference.
+        * <p>
+        * For example, an AST type like
+        * <code>Collection</code> typically resolves to a
+        * type binding whose type argument is the type binding for
+        * the class <code>java.lang.Object</code> (the
+        * default bound for the single type parameter of
+        * <code>java.util.Collection</code>) and whose erasure is the
+        * type binding for the generic type
+        * <code>java.util.Collection</code>.
+        * </p>
+        * <p>
+        * Note that {@link #isGenericType()},
+        * {@link #isParameterizedType()},
+        * and {@link #isRawType()} are mutually exclusive.
+        * </p>
+        *
+        * @return <code>true</code> if this type binding represents a
+        * an instance of a generic type corresponding to a raw
+        * type reference, and <code>false</code> otherwise
+        * @see #getTypeDeclaration()
+        * @see #getTypeArguments()
+        * @since 3.1
+        */
+       public boolean isRawType();
+
+       /**
+        * Returns whether this type is subtype compatible with the given type,
+        * as specified in section 4.10 of <em>The Java Language
+        * Specification, Third Edition</em> (JLS3).
+        *
+        * <p>If the receiver or the argument is a recovered type, the answer is always false,
+        * unless the two types are identical or the argument is <code>java.lang.Object</code>.</p>
+        *
+        * @param type the type to check compatibility against
+        * @return <code>true</code> if this type is subtype compatible with the
+        * given type, and <code>false</code> otherwise
+        * @since 3.1
+        */
+       public boolean isSubTypeCompatible(ITypeBinding type);
+
+       /**
+        * Returns whether this type binding represents a top-level class,
+        * interface, enum, or annotation type.
+        * <p>
+        * A top-level type is any type whose declaration does not occur within the
+        * body of another type declaration. The set of top level types is disjoint
+        * from the set of nested types.
+        * </p>
+        *
+        * @return <code>true</code> if this type binding is for a top-level class,
+        *   interface, enum, or annotation type, and <code>false</code> otherwise
+        */
+       public boolean isTopLevel();
+
+       /**
+        * Returns whether this type binding represents a type variable.
+        * Type variables bindings carry the type variable's bounds.
+     * <p>
+     * Note that type variables are distinct from capture bindings
+     * (even though capture bindings are often depicted as synthetic
+     * type variables); as such, {@link #isTypeVariable()} answers
+     * <code>false</code> for capture bindings, and
+     * {@link #isCapture()} answers <code>false</code> for type variables.
+     * </p>
+        *
+        * @return <code>true</code> if this type binding is for a type variable,
+        *   and <code>false</code> otherwise
+        * @see #getName()
+        * @see #getTypeBounds()
+        * @since 3.1
+        */
+       public boolean isTypeVariable();
+
+       /**
+        * Returns whether this wildcard type is an upper bound
+        * ("extends") as opposed to a lower bound ("super").
+        * Note that this property is only relevant for wildcards
+        * that have a bound.
+        *
+        * @return <code>true</code> if this wildcard type has a bound that is
+        * an upper bound, and <code>false</code> in all other cases
+        * @see #isWildcardType()
+        * @see #getBound()
+        * @since 3.1
+        */
+       public boolean isUpperbound();
+
+       /**
+        * Returns whether this type binding represents a wildcard type. A wildcard
+        * type occus only as an argument to a parameterized type reference.
+        * <p>
+        * For example, a AST type like
+        * <code>Collection&lt;? extends Object&gt;</code> typically resolves to a
+        * parameterized type binding whose type argument is a wildcard type
+        * with upper type bound <code>java.util.Object</code>.
+        * </p>
+        *
+        * @return <code>true</code> if this object represents a wildcard type,
+        *    and <code>false</code> otherwise
+        * @since 3.1
+        * @see #getBound()
+        * @see #isUpperbound()
+        */
+       public boolean isWildcardType();
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IVariableBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IVariableBinding.java
new file mode 100644 (file)
index 0000000..48dbf61
--- /dev/null
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * A variable binding represents either a field of a class or interface, or 
+ * a local variable declaration (including formal parameters, local variables, 
+ * and exception variables).
+ *
+ * @see ITypeBinding#getDeclaredFields()
+ * @since 2.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IVariableBinding extends IBinding {
+       
+       /**
+        * Returns whether this binding is for a field.
+        * Note that this method returns <code>true</code> for constants,
+        * including enum constants. This method returns <code>false</code>
+        * for local variables.
+        * 
+        * @return <code>true</code> if this is the binding for a field,
+        *    and <code>false</code> otherwise
+        */ 
+       public boolean isField();
+       
+       /**
+        * Returns whether this binding is for an enum constant.
+        * Note that this method returns <code>false</code> for local variables
+        * and for fields other than enum constants.
+        * 
+        * @return <code>true</code> if this is the binding for an enum constant,
+        *    and <code>false</code> otherwise
+        * @since 3.1
+        */ 
+       public boolean isEnumConstant();
+       
+       /**
+        * Returns whether this binding corresponds to a parameter. 
+        * 
+        * @return <code>true</code> if this is the binding for a parameter,
+        *    and <code>false</code> otherwise
+        * @since 3.2
+        */
+       public boolean isParameter();
+
+       /**
+        * Returns the name of the field or local variable declared in this binding.
+        * The name is always a simple identifier.
+        * 
+        * @return the name of this field or local variable
+        */
+       public String getName();
+       
+       /**
+        * Returns the type binding representing the class or interface
+        * that declares this field.
+        * <p>
+        * The declaring class of a field is the class or interface of which it is
+        * a member. Local variables have no declaring class. The field length of an 
+        * array type has no declaring class.
+        * </p>
+        * 
+        * @return the binding of the class or interface that declares this field,
+        *   or <code>null</code> if none
+        */
+       public ITypeBinding getDeclaringClass();
+
+       /**
+        * Returns the binding for the type of this field or local variable.
+        * 
+        * @return the binding for the type of this field or local variable
+        */
+       public ITypeBinding getType();
+       
+       /**
+        * Returns a small integer variable id for this variable binding.
+        * <p>
+        * <b>Local variables inside methods:</b> Local variables (and parameters)
+        * declared within a single method are assigned ascending ids in normal
+        * code reading order; var1.getVariableId()&lt;var2.getVariableId() means that var1 is
+        * declared before var2.
+        * </p>
+        * <p>
+        * <b>Local variables outside methods:</b> Local variables declared in a
+        * type's static initializers (or initializer expressions of static fields)
+        * are assigned ascending ids in normal code reading order. Local variables
+        * declared in a type's instance initializers (or initializer expressions
+        * of non-static fields) are assigned ascending ids in normal code reading
+        * order. These ids are useful when checking definite assignment for
+        * static initializers (JLS 16.7) and instance initializers (JLS 16.8), 
+        * respectively.
+        * </p>
+        * <p>
+        * <b>Fields:</b> Fields declared as members of a type are assigned 
+        * ascending ids in normal code reading order; 
+        * field1.getVariableId()&lt;field2.getVariableId() means that field1 is declared before
+        * field2.
+        * </p>
+        * 
+        * @return a small non-negative variable id
+        */
+       public int getVariableId();
+       
+       /**
+        * Returns this binding's constant value if it has one.
+        * Some variables may have a value computed at compile-time. If the type of
+        * the value is a primitive type, the result is the boxed equivalent (i.e.,
+        * int returned as an <code>Integer</code>). If the type of the value is
+        * <code>String</code>, the result is the string itself. If the variable has
+        * no compile-time computed value, the result is <code>null</code>.
+        * (Note: compile-time constant expressions cannot denote <code>null</code>;
+        * JLS2 15.28.). The result is always <code>null</code> for enum constants.
+        * 
+        * @return the constant value, or <code>null</code> if none
+        * @since 3.0
+        */
+       public Object getConstantValue();
+       
+       /**
+        * Returns the method binding representing the method containing the scope
+        * in which this local variable is declared.
+        * <p>
+        * The declaring method of a method formal parameter is the method itself.
+        * For a local variable declared somewhere within the body of a method,
+        * the declaring method is the enclosing method. When local or anonymous
+        * classes are involved, the declaring method is the innermost such method.
+        * There is no declaring method for a field, or for a local variable
+        * declared in a static or instance initializer; this method returns
+        * <code>null</code> in those cases.
+        * </p>
+        * 
+        * @return the binding of the method or constructor that declares this
+        * local variable, or <code>null</code> if none
+        * @since 3.1
+        */
+       public IMethodBinding getDeclaringMethod();
+       
+       /**
+        * Returns the binding for the variable declaration corresponding to this
+        * variable binding. For a binding for a field declaration in an instance
+        * of a generic type, this method returns the binding for the corresponding
+        * field declaration in the generic type. For other variable bindings,
+        * including all ones for local variables and parameters, this method
+        * returns the same binding.
+        *
+        * @return the variable binding for the originating declaration
+        * @since 3.1
+        */
+       public IVariableBinding getVariableDeclaration();
+
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IfStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/IfStatement.java
new file mode 100644 (file)
index 0000000..9c29675
--- /dev/null
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * If statement AST node type.
+ * <pre>
+ * IfStatement:
+ *    <b>if</b> <b>(</b> Expression <b>)</b> Statement [ <b>else</b> Statement]
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class IfStatement extends Statement {
+       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(IfStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "thenStatement" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor THEN_STATEMENT_PROPERTY = 
+               new ChildPropertyDescriptor(IfStatement.class, "thenStatement", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "elseStatement" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor ELSE_STATEMENT_PROPERTY = 
+               new ChildPropertyDescriptor(IfStatement.class, "elseStatement", Statement.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(4);
+               createPropertyList(IfStatement.class, properyList);
+               addProperty(EXPRESSION_PROPERTY, properyList);
+               addProperty(THEN_STATEMENT_PROPERTY, properyList);
+               addProperty(ELSE_STATEMENT_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 expression; lazily initialized; defaults to an unspecified, but 
+        * legal, expression.
+        */
+       private Expression expression = null;
+
+       /**
+        * The then statement; lazily initialized; defaults to an unspecified, but 
+        * legal, statement.
+        */
+       private Statement thenStatement = null;
+
+       /**
+        * The else statement; <code>null</code> for none; defaults to none.
+        */
+       private Statement optionalElseStatement = null;
+
+       /**
+        * Creates a new unparented if statement node owned by the given 
+        * AST. By default, the expresssion is unspecified,
+        * but legal, the then statement is an empty block, and there is no else
+        * statement.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       IfStatement(AST ast) {
+               super(ast);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == THEN_STATEMENT_PROPERTY) {
+                       if (get) {
+                               return getThenStatement();
+                       } else {
+                               setThenStatement((Statement) child);
+                               return null;
+                       }
+               }
+               if (property == ELSE_STATEMENT_PROPERTY) {
+                       if (get) {
+                               return getElseStatement();
+                       } else {
+                               setElseStatement((Statement) 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.
+        */
+       final int getNodeType0() {
+               return IF_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               IfStatement result = new IfStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setExpression((Expression) getExpression().clone(target));
+               result.setThenStatement(
+                       (Statement) getThenStatement().clone(target));
+               result.setElseStatement(
+                       (Statement) ASTNode.copySubtree(target, getElseStatement()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getExpression());
+                       acceptChild(visitor, getThenStatement());
+                       acceptChild(visitor, getElseStatement());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this if statement.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new SimpleName(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.expression;
+       }
+       
+       /**
+        * Sets the condition of this if statement.
+        * 
+        * @param expression the expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the "then" part of this if statement.
+        * 
+        * @return the "then" statement node
+        */ 
+       public Statement getThenStatement() {
+               if (this.thenStatement == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.thenStatement == null) {
+                                       preLazyInit();
+                                       this.thenStatement = new Block(this.ast);
+                                       postLazyInit(this.thenStatement, THEN_STATEMENT_PROPERTY);
+                               }
+                       }
+               }
+               return this.thenStatement;
+       }
+       
+       /**
+        * Sets the "then" part of this if statement.
+        * <p>
+        * Special note: The Java language does not allow a local variable declaration
+        * to appear as the "then" part of an if statement (they may only appear within a
+        * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+        * as the thenStatement of a <code>IfStatement</code>. To get something that will
+        * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+        * inside a <code>Block</code>.
+        * </p>
+        * 
+        * @param statement the "then" statement node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setThenStatement(Statement statement) {
+               if (statement == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.thenStatement;
+               preReplaceChild(oldChild, statement, THEN_STATEMENT_PROPERTY);
+               this.thenStatement = statement;
+               postReplaceChild(oldChild, statement, THEN_STATEMENT_PROPERTY);
+       }
+
+       /**
+        * Returns the "else" part of this if statement, or <code>null</code> if
+        * this if statement has <b>no</b> "else" part.
+        * <p>
+        * Note that there is a subtle difference between having no else 
+        * statement and having an empty statement ("{}") or null statement (";").
+        * </p>
+        * 
+        * @return the "else" statement node, or <code>null</code> if none
+        */ 
+       public Statement getElseStatement() {
+               return this.optionalElseStatement;
+       }
+
+       /**
+        * Sets or clears the "else" part of this if statement.
+        * <p>
+        * Note that there is a subtle difference between having no else part
+        * (as in <code>"if(true){}"</code>) and having an empty block (as in
+        * "if(true){}else{}") or null statement (as in "if(true){}else;"). 
+        * </p>
+        * <p>
+        * Special note: The Java language does not allow a local variable declaration
+        * to appear as the "else" part of an if statement (they may only appear within a
+        * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+        * as the elseStatement of a <code>IfStatement</code>. To get something that will
+        * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+        * inside a <code>Block</code>.
+        * </p>
+        * 
+        * @param statement the "else" statement node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setElseStatement(Statement statement) {
+               ASTNode oldChild = this.optionalElseStatement;
+               preReplaceChild(oldChild, statement, ELSE_STATEMENT_PROPERTY);
+               this.optionalElseStatement = statement;
+               postReplaceChild(oldChild, statement, ELSE_STATEMENT_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.expression == null ? 0 : getExpression().treeSize())
+                       + (this.thenStatement == null ? 0 : getThenStatement().treeSize())
+                       + (this.optionalElseStatement == null ? 0 : getElseStatement().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ImportDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ImportDeclaration.java
new file mode 100644 (file)
index 0000000..0778aaf
--- /dev/null
@@ -0,0 +1,378 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Import declaration AST node type.
+ *
+ * For JLS2:
+ * <pre>
+ * ImportDeclaration:
+ *    <b>import</b> Name [ <b>.</b> <b>*</b> ] <b>;</b>
+ * </pre>
+ * For JLS3, static was added:
+ * <pre>
+ * ImportDeclaration:
+ *    <b>import</b> [ <b>static</b> ] Name [ <b>.</b> <b>*</b> ] <b>;</b>
+ * </pre>
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ImportDeclaration extends ASTNode {
+       
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(ImportDeclaration.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "onDemand" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor ON_DEMAND_PROPERTY = 
+               new SimplePropertyDescriptor(ImportDeclaration.class, "onDemand", boolean.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "static" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final SimplePropertyDescriptor STATIC_PROPERTY = 
+               new SimplePropertyDescriptor(ImportDeclaration.class, "static", boolean.class, MANDATORY); //$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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List properyList = new ArrayList(3);
+               createPropertyList(ImportDeclaration.class, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               addProperty(ON_DEMAND_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+               
+               properyList = new ArrayList(4);
+               createPropertyList(ImportDeclaration.class, properyList);
+               addProperty(STATIC_PROPERTY, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               addProperty(ON_DEMAND_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_3_0 = 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The import name; lazily initialized; defaults to a unspecified,
+        * legal Java identifier.
+        */
+       private Name importName = null;
+
+       /**
+        * On demand versus single type import; defaults to single type import.
+        */
+       private boolean onDemand = false;
+
+       /**
+        * Static versus regular; defaults to regular import.
+        * Added in JLS3; not used in JLS2.
+        * @since 3.1
+        */
+       private boolean isStatic = false;
+
+       /**
+        * Creates a new AST node for an import declaration owned by the
+        * given AST. The import declaration initially is a regular (non-static)
+        * single type import for an unspecified, but legal, Java type name.
+        * <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
+        */
+       ImportDeclaration(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+               if (property == ON_DEMAND_PROPERTY) {
+                       if (get) {
+                               return isOnDemand();
+                       } else {
+                               setOnDemand(value);
+                               return false;
+                       }
+               }
+               if (property == STATIC_PROPERTY) {
+                       if (get) {
+                               return isStatic();
+                       } else {
+                               setStatic(value);
+                               return false;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetBooleanProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((Name) 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.
+        */
+       final int getNodeType0() {
+               return IMPORT_DECLARATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ImportDeclaration result = new ImportDeclaration(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setOnDemand(isOnDemand());
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.setStatic(isStatic());
+               }
+               result.setName((Name) getName().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getName());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the name imported by this declaration.
+        * <p>
+        * For a regular on-demand import, this is the name of a package. 
+        * For a static on-demand import, this is the qualified name of
+        * a type. For a regular single-type import, this is the qualified name
+        * of a type. For a static single-type import, this is the qualified name
+        * of a static member of a type.
+        * </p>
+        * 
+        * @return the imported name node
+        */ 
+       public Name getName()  {
+               if (this.importName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.importName == null) {
+                                       preLazyInit();
+                                       this.importName =this.ast.newQualifiedName(
+                                                       new SimpleName(this.ast), new SimpleName(this.ast));
+                                       postLazyInit(this.importName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return importName;
+       }
+       
+       /**
+        * Sets the name of this import declaration to the given name.
+        * <p>
+        * For a regular on-demand import, this is the name of a package. 
+        * For a static on-demand import, this is the qualified name of
+        * a type. For a regular single-type import, this is the qualified name
+        * of a type. For a static single-type import, this is the qualified name
+        * of a static member of a type.
+        * </p>
+        * 
+        * @param name the new import name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(Name name) {
+               if (name == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.importName;
+               preReplaceChild(oldChild, name, NAME_PROPERTY);
+               this.importName = name;
+               postReplaceChild(oldChild, name, NAME_PROPERTY);
+       }
+               
+       /**
+        * Returns whether this import declaration is an on-demand or a 
+        * single-type import.
+        * 
+        * @return <code>true</code> if this is an on-demand import,
+        *    and <code>false</code> if this is a single type import
+        */ 
+       public boolean isOnDemand() {
+               return onDemand;
+       }
+               
+       /**
+        * Sets whether this import declaration is an on-demand or a 
+        * single-type import.
+        * 
+        * @param onDemand <code>true</code> if this is an on-demand import,
+        *    and <code>false</code> if this is a single type import
+        */ 
+       public void setOnDemand(boolean onDemand) {
+               preValueChange(ON_DEMAND_PROPERTY);
+               this.onDemand = onDemand;
+               postValueChange(ON_DEMAND_PROPERTY);
+       }
+       
+       /**
+        * Returns whether this import declaration is a static import (added in JLS3 API).
+        * 
+        * @return <code>true</code> if this is a static import,
+        *    and <code>false</code> if this is a regular import
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public boolean isStatic() {
+               unsupportedIn2();
+               return isStatic;
+       }
+               
+       /**
+        * Sets whether this import declaration is a static import (added in JLS3 API).
+        * 
+        * @param isStatic <code>true</code> if this is a static import,
+        *    and <code>false</code> if this is a regular import
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public void setStatic(boolean isStatic) {
+               unsupportedIn2();
+               preValueChange(STATIC_PROPERTY);
+               this.isStatic = isStatic;
+               postValueChange(STATIC_PROPERTY);
+       }
+       
+       /**
+        * Resolves and returns the binding for the package, type, field, or
+        * method named in this import declaration.
+        * <p>
+        * The name specified in a non-static single-type import can resolve
+        * to a type (only). The name specified in a non-static on-demand
+        * import can itself resolve to either a package or a type.
+        * For static imports (introduced in JLS3), the name specified in a
+        * static on-demand import can itself resolve to a type (only).
+        * The name specified in a static single import can resolve to a
+        * type, field, or method; in cases where the name could be resolved
+        * to more than one element with that name (for example, two
+        * methods both named "max", or a method and a field), this method
+        * returns one of the plausible bindings.
+        * </p>
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return a package, type, field, or method binding, or <code>null</code>
+        * if the binding cannot be resolved
+        */     
+       public IBinding resolveBinding() {
+               return this.ast.getBindingResolver().resolveImport(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (importName == null ? 0 : getName().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/InfixExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/InfixExpression.java
new file mode 100644 (file)
index 0000000..d672b4f
--- /dev/null
@@ -0,0 +1,538 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Infix expression AST node type.
+ * <pre>
+ * InfixExpression:
+ *    Expression InfixOperator Expression { InfixOperator Expression } 
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class InfixExpression extends Expression {
+
+       /**
+        * Infix operators (typesafe enumeration).
+        * <pre>
+        * InfixOperator:<code>
+        *    <b>*</b>  TIMES
+        *    <b>/</b>  DIVIDE
+        *    <b>%</b>  REMAINDER
+        *    <b>+</b>  PLUS
+        *    <b>-</b>  MINUS
+        *    <b>&lt;&lt;</b>  LEFT_SHIFT
+        *    <b>&gt;&gt;</b>  RIGHT_SHIFT_SIGNED
+        *    <b>&gt;&gt;&gt;</b>  RIGHT_SHIFT_UNSIGNED
+        *    <b>&lt;</b>  LESS
+        *    <b>&gt;</b>  GREATER
+        *    <b>&lt;=</b>  LESS_EQUALS
+        *    <b>&gt;=</b>  GREATER_EQUALS
+        *    <b>==</b>  EQUALS
+        *    <b>!=</b>  NOT_EQUALS
+        *    <b>^</b>  XOR
+        *    <b>&amp;</b>  AND
+        *    <b>|</b>  OR
+        *    <b>&amp;&amp;</b>  CONDITIONAL_AND
+        *    <b>||</b>  CONDITIONAL_OR</code>
+        * </pre>
+        */
+       public static class Operator {
+       
+               /**
+                * The token for the operator.
+                */
+               private String token;
+               
+               /**
+                * Creates a new infix operator with the given token.
+                * <p>
+                * Note: this constructor is private. The only instances
+                * ever created are the ones for the standard operators.
+                * </p>
+                * 
+                * @param token the character sequence for the operator
+                */
+               private Operator(String token) {
+                       this.token = token;
+               }
+               
+               /**
+                * Returns the character sequence for the operator.
+                * 
+                * @return the character sequence for the operator
+                */
+               public String toString() {
+                       return token;
+               }
+               
+               /** Multiplication "*" operator. */
+               public static final Operator TIMES = new Operator("*");//$NON-NLS-1$
+               /** Division "/" operator. */
+               public static final Operator DIVIDE = new Operator("/");//$NON-NLS-1$
+               /** Remainder "%" operator. */
+               public static final Operator REMAINDER = new Operator("%");//$NON-NLS-1$
+               /** Addition (or string concatenation) "+" operator. */
+               public static final Operator PLUS = new Operator("+");//$NON-NLS-1$
+               /** Subtraction "-" operator. */
+               public static final Operator MINUS = new Operator("-");//$NON-NLS-1$
+               /** Left shift "&lt;&lt;" operator. */
+               public static final Operator LEFT_SHIFT = new Operator("<<");//$NON-NLS-1$
+               /** Signed right shift "&gt;&gt;" operator. */
+               public static final Operator RIGHT_SHIFT_SIGNED = new Operator(">>");//$NON-NLS-1$
+               /** Unsigned right shift "&gt;&gt;&gt;" operator. */
+               public static final Operator RIGHT_SHIFT_UNSIGNED = 
+                       new Operator(">>>");//$NON-NLS-1$
+               /** Less than "&lt;" operator. */
+               public static final Operator LESS = new Operator("<");//$NON-NLS-1$
+               /** Greater than "&gt;" operator. */
+               public static final Operator GREATER = new Operator(">");//$NON-NLS-1$
+               /** Less than or equals "&lt;=" operator. */
+               public static final Operator LESS_EQUALS = new Operator("<=");//$NON-NLS-1$
+               /** Greater than or equals "&gt=;" operator. */
+               public static final Operator GREATER_EQUALS = new Operator(">=");//$NON-NLS-1$
+               /** Equals "==" operator. */
+               public static final Operator EQUALS = new Operator("==");//$NON-NLS-1$
+               /** Not equals "!=" operator. */
+               public static final Operator NOT_EQUALS = new Operator("!=");//$NON-NLS-1$
+               /** Exclusive OR "^" operator. */
+               public static final Operator XOR = new Operator("^");//$NON-NLS-1$
+               /** Inclusive OR "|" operator. */
+               public static final Operator OR = new Operator("|");//$NON-NLS-1$
+               /** AND "&amp;" operator. */
+               public static final Operator AND = new Operator("&");//$NON-NLS-1$
+               /** Conditional OR "||" operator. */
+               public static final Operator CONDITIONAL_OR = new Operator("||");//$NON-NLS-1$
+               /** Conditional AND "&amp;&amp;" operator. */
+               public static final Operator CONDITIONAL_AND = new Operator("&&");//$NON-NLS-1$
+               
+               /**
+                * Map from token to operator (key type: <code>String</code>;
+                * value type: <code>Operator</code>).
+                */
+               private static final Map CODES;
+               static {
+                       CODES = new HashMap(20);
+                       Operator[] ops = {
+                                       TIMES,
+                                       DIVIDE,
+                                       REMAINDER,
+                                       PLUS,
+                                       MINUS,
+                                       LEFT_SHIFT,
+                                       RIGHT_SHIFT_SIGNED,
+                                       RIGHT_SHIFT_UNSIGNED,
+                                       LESS,
+                                       GREATER,
+                                       LESS_EQUALS,
+                                       GREATER_EQUALS,
+                                       EQUALS,
+                                       NOT_EQUALS,
+                                       XOR,
+                                       OR,
+                                       AND,
+                                       CONDITIONAL_OR,
+                                       CONDITIONAL_AND,
+                               };
+                       for (int i = 0; i < ops.length; i++) {
+                               CODES.put(ops[i].toString(), ops[i]);
+                       }
+               }
+
+               /**
+                * Returns the infix operator corresponding to the given string,
+                * or <code>null</code> if none.
+                * <p>
+                * <code>toOperator</code> is the converse of <code>toString</code>:
+                * that is, <code>Operator.toOperator(op.toString()) == op</code> for 
+                * all operators <code>op</code>.
+                * </p>
+                * 
+                * @param token the character sequence for the operator
+                * @return the infix operator, or <code>null</code> if none
+                */
+               public static Operator toOperator(String token) {
+                       return (Operator) CODES.get(token);
+               }
+               
+       }
+       
+       /**
+        * The "leftOperand" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor LEFT_OPERAND_PROPERTY = 
+               new ChildPropertyDescriptor(InfixExpression.class, "leftOperand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "operator" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor OPERATOR_PROPERTY = 
+               new SimplePropertyDescriptor(InfixExpression.class, "operator", InfixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "rightOperand" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor RIGHT_OPERAND_PROPERTY = 
+               new ChildPropertyDescriptor(InfixExpression.class, "rightOperand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "extendedOperands" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor EXTENDED_OPERANDS_PROPERTY = 
+               new ChildListPropertyDescriptor(InfixExpression.class, "extendedOperands", Expression.class, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(5);
+               createPropertyList(InfixExpression.class, properyList);
+               addProperty(LEFT_OPERAND_PROPERTY, properyList);
+               addProperty(OPERATOR_PROPERTY, properyList);
+               addProperty(RIGHT_OPERAND_PROPERTY, properyList);
+               addProperty(EXTENDED_OPERANDS_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 infix operator; defaults to InfixExpression.Operator.PLUS.
+        */
+       private InfixExpression.Operator operator = InfixExpression.Operator.PLUS;
+
+       /**
+        * The left operand; lazily initialized; defaults to an unspecified,
+        * but legal, simple name.
+        */
+       private Expression leftOperand = null;
+
+       /**
+        * The right operand; lazily initialized; defaults to an unspecified,
+        * but legal, simple name.
+        */
+       private Expression rightOperand = null;
+
+       /**
+        * The list of extended operand expressions (element type: 
+        * <code>Expression</code>). Lazily initialized; defaults to an empty list.
+        */
+       private ASTNode.NodeList extendedOperands = null;
+
+       /**
+        * Creates a new AST node for an infix expression owned by the given 
+        * AST. By default, the node has unspecified (but legal) operator,
+        * left and right operands, and an empty list of additional operands.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       InfixExpression(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == OPERATOR_PROPERTY) {
+                       if (get) {
+                               return getOperator();
+                       } else {
+                               setOperator((Operator) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == LEFT_OPERAND_PROPERTY) {
+                       if (get) {
+                               return getLeftOperand();
+                       } else {
+                               setLeftOperand((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == RIGHT_OPERAND_PROPERTY) {
+                       if (get) {
+                               return getRightOperand();
+                       } else {
+                               setRightOperand((Expression) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == EXTENDED_OPERANDS_PROPERTY) {
+                       return extendedOperands();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return INFIX_EXPRESSION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               InfixExpression result = new InfixExpression(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setOperator(getOperator());
+               result.setLeftOperand((Expression) getLeftOperand().clone(target));
+               result.setRightOperand((Expression) getRightOperand().clone(target));
+               if (this.extendedOperands != null) {
+                       // be careful not to trigger lazy creation of list
+                       result.extendedOperands().addAll(
+                               ASTNode.copySubtrees(target, this.extendedOperands()));
+               }
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getLeftOperand());
+                       acceptChild(visitor, getRightOperand());
+                       if (this.extendedOperands != null) {
+                               // be careful not to trigger lazy creation of list
+                               acceptChildren(visitor, this.extendedOperands);
+                       }
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the operator of this infix expression.
+        * 
+        * @return the infix operator
+        */ 
+       public InfixExpression.Operator getOperator() {
+               return this.operator;
+       }
+
+       /**
+        * Sets the operator of this infix expression.
+        * 
+        * @param operator the infix operator
+        * @exception IllegalArgumentException if the argument is incorrect
+        */ 
+       public void setOperator(InfixExpression.Operator operator) {
+               if (operator == null) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(OPERATOR_PROPERTY);
+               this.operator = operator;
+               postValueChange(OPERATOR_PROPERTY);
+       }
+
+       /**
+        * Returns the left operand of this infix expression.
+        * 
+        * @return the left operand node
+        */ 
+       public Expression getLeftOperand() {
+               if (this.leftOperand  == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.leftOperand == null) {
+                                       preLazyInit();
+                                       this.leftOperand= new SimpleName(this.ast);
+                                       postLazyInit(this.leftOperand, LEFT_OPERAND_PROPERTY);
+                               }
+                       }
+               }
+               return this.leftOperand;
+       }
+               
+       /**
+        * Sets the left operand of this infix expression.
+        * 
+        * @param expression the left operand node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setLeftOperand(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.leftOperand;
+               preReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+               this.leftOperand = expression;
+               postReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+       }
+
+       /**
+        * Returns the right operand of this infix expression.
+        * 
+        * @return the right operand node
+        */ 
+       public Expression getRightOperand() {
+               if (this.rightOperand  == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.rightOperand  == null) {
+                                       preLazyInit();
+                                       this.rightOperand= new SimpleName(this.ast);
+                                       postLazyInit(this.rightOperand, RIGHT_OPERAND_PROPERTY);
+                               }
+                       }
+               }
+               return this.rightOperand;
+       }
+               
+       /**
+        * Sets the right operand of this infix expression.
+        * 
+        * @param expression the right operand node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setRightOperand(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.rightOperand;
+               preReplaceChild(oldChild, expression, RIGHT_OPERAND_PROPERTY);
+               this.rightOperand = expression;
+               postReplaceChild(oldChild, expression, RIGHT_OPERAND_PROPERTY);
+       }
+       
+       /**
+        * Returns where there are any extended operands.
+        * 
+        * @return <code>true</code> if there are one or more extended operands,
+        *    and <code>false</code> if there are no extended operands
+        */
+       public boolean hasExtendedOperands() {
+               return 
+                       (this.extendedOperands != null) && this.extendedOperands.size() > 0;
+       }
+       
+       /**
+        * Returns the live list of extended operands.
+        * <p>
+        * The extended operands is the preferred way of representing deeply nested
+        * expressions of the form <code>L op R op R2 op R3...</code> where
+        * the same operator appears between all the operands (the most 
+        * common case being lengthy string concatenation expressions). Using
+        * the extended operands keeps the trees from getting too deep; this
+        * decreases the risk is running out of thread stack space at runtime
+        * when traversing such trees.
+        * ((a + b) + c) + d would be translated to:
+        *      leftOperand: a
+        *      rightOperand: b
+        *      extendedOperands: {c, d}
+        *      operator: +
+        * </p>
+        * 
+        * @return the live list of extended operands
+        *   (element type: <code>Expression</code>)
+        */
+       public List extendedOperands() {
+               if (this.extendedOperands == null) {
+                       // lazily initialize
+                       this.extendedOperands = new ASTNode.NodeList(EXTENDED_OPERANDS_PROPERTY);
+               }
+               return this.extendedOperands;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Operator as free
+               return BASE_NODE_SIZE + 4 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.leftOperand == null ? 0 : getLeftOperand().treeSize())
+                       + (this.rightOperand == null ? 0 : getRightOperand().treeSize())
+                       + (this.extendedOperands == null ? 0 : extendedOperands.listSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Initializer.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Initializer.java
new file mode 100644 (file)
index 0000000..09058fd
--- /dev/null
@@ -0,0 +1,313 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Static or instance initializer AST node type.
+ * <pre>
+ * Initializer:
+ *     [ <b>static</b> ] Block
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class Initializer extends BodyDeclaration {
+       
+       /**
+        * The "javadoc" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
+               internalJavadocPropertyFactory(Initializer.class);
+
+       /**
+        * The "modifiers" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor MODIFIERS_PROPERTY = 
+               internalModifiersPropertyFactory(Initializer.class);
+       
+       /**
+        * The "modifiers" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
+               internalModifiers2PropertyFactory(Initializer.class);
+       
+       /**
+        * The "body" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor BODY_PROPERTY = 
+               new ChildPropertyDescriptor(Initializer.class, "body", Block.class, MANDATORY, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List properyList = new ArrayList(4);
+               createPropertyList(Initializer.class, properyList);
+               addProperty(JAVADOC_PROPERTY, properyList);
+               addProperty(MODIFIERS_PROPERTY, properyList);
+               addProperty(BODY_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+               
+               properyList = new ArrayList(4);
+               createPropertyList(Initializer.class, properyList);
+               addProperty(JAVADOC_PROPERTY, properyList);
+               addProperty(MODIFIERS2_PROPERTY, properyList);
+               addProperty(BODY_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_3_0 = 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The initializer body; lazily initialized; defaults to an empty block.
+        */
+       private Block body = null;
+
+       /**
+        * Creates a new AST node for an initializer declaration owned by the given 
+        * AST. By default, the initializer has no modifiers and an empty block.
+        * The javadoc comment is not used for initializers.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       Initializer(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+               if (property == MODIFIERS_PROPERTY) {
+                       if (get) {
+                               return getModifiers();
+                       } else {
+                               internalSetModifiers(value);
+                               return 0;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetIntProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == JAVADOC_PROPERTY) {
+                       if (get) {
+                               return getJavadoc();
+                       } else {
+                               setJavadoc((Javadoc) child);
+                               return null;
+                       }
+               }
+               if (property == BODY_PROPERTY) {
+                       if (get) {
+                               return getBody();
+                       } else {
+                               setBody((Block) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == MODIFIERS2_PROPERTY) {
+                       return modifiers();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildPropertyDescriptor internalJavadocProperty() {
+               return JAVADOC_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildListPropertyDescriptor internalModifiers2Property() {
+               return MODIFIERS2_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final SimplePropertyDescriptor internalModifiersProperty() {
+               return MODIFIERS_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return INITIALIZER;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               Initializer result = new Initializer(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                       result.internalSetModifiers(getModifiers());
+               }
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+               }
+               result.setJavadoc(
+                       (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+               result.setBody((Block) getBody().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getJavadoc());
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChildren(visitor, this.modifiers);
+                       }
+                       acceptChild(visitor, getBody());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the body of this initializer declaration.
+        * 
+        * @return the initializer body
+        */ 
+       public Block getBody() {
+               if (this.body == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.body == null) {
+                                       preLazyInit();
+                                       this.body= new Block(this.ast);
+                                       postLazyInit(this.body, BODY_PROPERTY);
+                               }
+                       }
+               }
+               return this.body;
+       }
+       
+       /**
+        * Sets the body of this initializer declaration.
+        * 
+        * @param body the block node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setBody(Block body) {
+               if (body == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.body;
+               preReplaceChild(oldChild, body, BODY_PROPERTY);
+               this.body = body;
+               postReplaceChild(oldChild, body, BODY_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+                       + (this.modifiers == null ? 0 : this.modifiers.listSize())
+                       + (this.body == null ? 0 : getBody().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/InstanceofExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/InstanceofExpression.java
new file mode 100644 (file)
index 0000000..e629564
--- /dev/null
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Instanceof expression AST node type.
+ * <pre>
+ * InstanceofExpression:
+ *    Expression <b>instanceof</b> Type
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class InstanceofExpression extends Expression {
+
+       /**
+        * The "leftOperand" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor LEFT_OPERAND_PROPERTY = 
+               new ChildPropertyDescriptor(InstanceofExpression.class, "leftOperand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "rightOperand" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor RIGHT_OPERAND_PROPERTY = 
+               new ChildPropertyDescriptor(InstanceofExpression.class, "rightOperand", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(3);
+               createPropertyList(InstanceofExpression.class, properyList);
+               addProperty(LEFT_OPERAND_PROPERTY, properyList);
+               addProperty(RIGHT_OPERAND_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 left operand; lazily initialized; defaults to an unspecified,
+        * but legal, simple name.
+        */
+       private Expression leftOperand = null;
+
+       /**
+        * The right operand; lazily initialized; defaults to an unspecified,
+        * but legal, simple type.
+        */
+       private Type rightOperand = null;
+
+       /**
+        * Creates a new AST node for an instanceof expression owned by the given 
+        * AST. By default, the node has unspecified (but legal) operator,
+        * left and right operands.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       InstanceofExpression(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == LEFT_OPERAND_PROPERTY) {
+                       if (get) {
+                               return getLeftOperand();
+                       } else {
+                               setLeftOperand((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == RIGHT_OPERAND_PROPERTY) {
+                       if (get) {
+                               return getRightOperand();
+                       } else {
+                               setRightOperand((Type) 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.
+        */
+       final int getNodeType0() {
+               return INSTANCEOF_EXPRESSION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               InstanceofExpression result = new InstanceofExpression(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setLeftOperand((Expression) getLeftOperand().clone(target));
+               result.setRightOperand((Type) getRightOperand().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getLeftOperand());
+                       acceptChild(visitor, getRightOperand());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the left operand of this instanceof expression.
+        * 
+        * @return the left operand node
+        */ 
+       public Expression getLeftOperand() {
+               if (this.leftOperand  == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.leftOperand == null) {
+                                       preLazyInit();
+                                       this.leftOperand= new SimpleName(this.ast);
+                                       postLazyInit(this.leftOperand, LEFT_OPERAND_PROPERTY);
+                               }
+                       }
+               }
+               return this.leftOperand;
+       }
+               
+       /**
+        * Sets the left operand of this instanceof expression.
+        * 
+        * @param expression the left operand node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setLeftOperand(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.leftOperand;
+               preReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+               this.leftOperand = expression;
+               postReplaceChild(oldChild, expression, LEFT_OPERAND_PROPERTY);
+       }
+
+       /**
+        * Returns the right operand of this instanceof expression.
+        * 
+        * @return the right operand node
+        */ 
+       public Type getRightOperand() {
+               if (this.rightOperand  == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.rightOperand == null) {
+                                       preLazyInit();
+                                       this.rightOperand= new SimpleType(this.ast);
+                                       postLazyInit(this.rightOperand, RIGHT_OPERAND_PROPERTY);
+                               }
+                       }
+               }
+               return this.rightOperand;
+       }
+               
+       /**
+        * Sets the right operand of this instanceof expression.
+        * 
+        * @param referenceType the right operand node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setRightOperand(Type referenceType) {
+               if (referenceType == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.rightOperand;
+               preReplaceChild(oldChild, referenceType, RIGHT_OPERAND_PROPERTY);
+               this.rightOperand = referenceType;
+               postReplaceChild(oldChild, referenceType, RIGHT_OPERAND_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Operator as free
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.leftOperand == null ? 0 : getLeftOperand().treeSize())
+                       + (this.rightOperand == null ? 0 : getRightOperand().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/InternalASTRewrite.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/InternalASTRewrite.java
new file mode 100644 (file)
index 0000000..a4beb82
--- /dev/null
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.TextUtilities;
+
+import net.sourceforge.phpdt.core.dom.SimplePropertyDescriptor;
+import net.sourceforge.phpdt.core.dom.StructuralPropertyDescriptor;
+import net.sourceforge.phpdt.core.dom.rewrite.TargetSourceRangeComputer;
+import net.sourceforge.phpdt.internal.core.dom.rewrite.ASTRewriteAnalyzer;
+import net.sourceforge.phpdt.internal.core.dom.rewrite.LineInformation;
+import net.sourceforge.phpdt.internal.core.dom.rewrite.ListRewriteEvent;
+import net.sourceforge.phpdt.internal.core.dom.rewrite.NodeInfoStore;
+import net.sourceforge.phpdt.internal.core.dom.rewrite.NodeRewriteEvent;
+import net.sourceforge.phpdt.internal.core.dom.rewrite.RewriteEventStore;
+import net.sourceforge.phpdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+import net.sourceforge.phpdt.internal.core.dom.rewrite.RewriteEventStore.PropertyLocation;
+
+/**
+ * Internal class: not intended to be used by client.
+ * When AST modifications recording is enabled, all changes are recorded by this class.
+ */
+class InternalASTRewrite extends NodeEventHandler {
+       
+       /** root node for the rewrite: Only nodes under this root are accepted */
+       private CompilationUnit root;
+
+       protected final RewriteEventStore eventStore;
+       protected final NodeInfoStore nodeStore;
+       protected final Hashtable clonedNodes;
+       
+       int cloneDepth = 0;
+       
+       /**
+        * Constructor
+        * @param root root node of the recorded ast.
+        */
+       public InternalASTRewrite(CompilationUnit root) {
+               this.root = root;
+               this.eventStore = new RewriteEventStore();
+               this.nodeStore = new NodeInfoStore(root.getAST());
+               this.clonedNodes = new Hashtable();
+       }
+
+       /**
+        * Performs the rewrite: The rewrite events are translated to the corresponding in text changes.
+        * @param document Document which describes the code of the AST that is passed in in the
+        * constructor. This document is accessed read-only.
+        * @param options options
+        * @throws IllegalArgumentException if the rewrite fails
+        * @return Returns the edit describing the text changes.
+        */
+       public TextEdit rewriteAST(IDocument document, Map options) {
+               TextEdit result = new MultiTextEdit();
+               
+               final CompilationUnit rootNode = getRootNode();
+               if (rootNode != null) {
+                       TargetSourceRangeComputer xsrComputer = new TargetSourceRangeComputer() {
+                               /** 
+                                * This implementation of
+                                * {@link TargetSourceRangeComputer#computeSourceRange(ASTNode)}
+                                * is specialized to work in the case of internal AST rewriting, where the
+                                * original AST has been modified from its original form. This means that
+                                * one cannot trust that the root of the given node is the compilation unit.
+                                */
+                               public SourceRange computeSourceRange(ASTNode node) {
+                                       int extendedStartPosition = rootNode.getExtendedStartPosition(node);
+                                       int extendedLength = rootNode.getExtendedLength(node);
+                                       return new SourceRange(extendedStartPosition, extendedLength);
+                               }
+                       };
+                       char[] content= document.get().toCharArray();
+                       LineInformation lineInfo= LineInformation.create(document);
+                       String lineDelim= TextUtilities.getDefaultLineDelimiter(document);
+                       List comments= rootNode.getCommentList();
+                       
+                       ASTRewriteAnalyzer visitor = new ASTRewriteAnalyzer(content, lineInfo, lineDelim, result, this.eventStore, this.nodeStore, comments, options, xsrComputer);
+                       rootNode.accept(visitor);
+               }
+               return result;
+       }
+       
+       private  void markAsMoveOrCopyTarget(ASTNode node, ASTNode newChild) {
+               ASTNode source = (ASTNode)this.clonedNodes.get(newChild);
+               if(source != null) {
+                       if(this.cloneDepth == 0) {
+                               PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(source, RewriteEventStore.ORIGINAL);
+                               CopySourceInfo sourceInfo =
+                                       this.eventStore.markAsCopySource(
+                                               propertyLocation.getParent(),
+                                               propertyLocation.getProperty(),
+                                               source,
+                                               false);
+                               this.nodeStore.markAsCopyTarget(newChild, sourceInfo);
+                       }
+               } else if((newChild.getFlags() & ASTNode.ORIGINAL) != 0) {
+                       PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(newChild, RewriteEventStore.ORIGINAL);
+                       CopySourceInfo sourceInfo =
+                               this.eventStore.markAsCopySource(
+                                       propertyLocation.getParent(),
+                                       propertyLocation.getProperty(),
+                                       newChild,
+                                       true);
+                       this.nodeStore.markAsCopyTarget(newChild, sourceInfo);
+               }
+       }
+
+       private CompilationUnit getRootNode() {
+               return this.root;
+       }
+
+       public String toString() {
+               StringBuffer buf = new StringBuffer();
+               buf.append("Events:\n"); //$NON-NLS-1$
+               buf.append(this.eventStore.toString());
+               return buf.toString();
+       }
+       
+       void preValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+               // force event creation
+               this.getNodeEvent(node, property);
+       }
+       
+       void postValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+               NodeRewriteEvent event = this.getNodeEvent(node, property);
+               event.setNewValue(node.getStructuralProperty(property));
+       }
+       
+       void preAddChildEvent(ASTNode node, ASTNode child,      StructuralPropertyDescriptor property) {
+               if(property.isChildProperty()) {
+                       NodeRewriteEvent event = this.getNodeEvent(node, property);
+                       event.setNewValue(child);
+                       if(child != null) {
+                               this.markAsMoveOrCopyTarget(node, child);
+                       }
+               } else if(property.isChildListProperty()) {
+                       // force event creation
+                       this.getListEvent(node, property);
+               }
+       }
+       
+       void postAddChildEvent(ASTNode node, ASTNode child,     StructuralPropertyDescriptor property) {
+               if(property.isChildListProperty()) {
+
+                       ListRewriteEvent event = this.getListEvent(node, property);
+                       List list = (List)node.getStructuralProperty(property);
+                       int i = list.indexOf(child);
+                       int s = list.size();
+                       int index;
+                       if(i + 1 < s) {
+                               ASTNode nextNode = (ASTNode)list.get(i + 1);
+                               index = event.getIndex(nextNode, ListRewriteEvent.NEW);
+                       } else {
+                               index = -1;
+                       }
+                       event.insert(child, index);
+                       if(child != null) {
+                               this.markAsMoveOrCopyTarget(node, child);
+                       }
+               }
+       }
+       
+       void preRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+               if(property.isChildProperty()) {
+                       NodeRewriteEvent event = getNodeEvent(node, property);
+                       event.setNewValue(null);
+               } else if(property.isChildListProperty()) {
+                       ListRewriteEvent event = this.getListEvent(node, property);
+                       int i = event.getIndex(child, ListRewriteEvent.NEW);
+                       NodeRewriteEvent nodeEvent = (NodeRewriteEvent)event.getChildren()[i];
+                       if(nodeEvent.getOriginalValue() == null) {
+                               event.revertChange(nodeEvent);
+                       } else {
+                               nodeEvent.setNewValue(null);
+                       }
+               }
+       }
+       
+       void preReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+               if(property.isChildProperty()) {
+                       NodeRewriteEvent event = getNodeEvent(node, property);
+                       event.setNewValue(newChild);
+                       if(newChild != null) {
+                               this.markAsMoveOrCopyTarget(node, newChild);
+                       }
+               } else if(property.isChildListProperty()) {
+                       ListRewriteEvent event = this.getListEvent(node, property);
+                       int i = event.getIndex(child, ListRewriteEvent.NEW);
+                       NodeRewriteEvent nodeEvent = (NodeRewriteEvent)event.getChildren()[i];
+                       nodeEvent.setNewValue(newChild);
+                       if(newChild != null) {
+                               this.markAsMoveOrCopyTarget(node, newChild);
+                       }
+               }
+       }
+       
+       
+       void preCloneNodeEvent(ASTNode node) {
+               this.cloneDepth++;
+       }
+       
+       
+       void postCloneNodeEvent(ASTNode node, ASTNode clone) {
+               if(node.ast == root.ast && clone.ast == root.ast) {
+                       if((node.getFlags() & ASTNode.ORIGINAL) != 0) {
+                               this.clonedNodes.put(clone, node);
+                       } else {
+                               // node can be a cloned node
+                               Object original = this.clonedNodes.get(node);
+                               if(original != null) {
+                                       this.clonedNodes.put(clone, original);
+                               }
+                       }
+               }
+               this.cloneDepth--;
+       }
+       
+       private NodeRewriteEvent getNodeEvent(ASTNode node, StructuralPropertyDescriptor property) {
+               return this.eventStore.getNodeEvent(node, property, true);
+       }
+       
+       private ListRewriteEvent getListEvent(ASTNode node, StructuralPropertyDescriptor property) {
+               return this.eventStore.getListEvent(node, property, true);
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Javadoc.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Javadoc.java
new file mode 100644 (file)
index 0000000..8a51251
--- /dev/null
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * AST node for a Javadoc-style doc comment.
+ * <pre>
+ * Javadoc:
+ *   <b>/** </b> { TagElement } <b>*</b><b>/</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class Javadoc extends Comment {
+       
+       /**
+        * The "comment" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        * @deprecated Replaced by {@link #TAGS_PROPERTY} in the JLS3 API.
+        */
+       public static final SimplePropertyDescriptor COMMENT_PROPERTY = 
+               new SimplePropertyDescriptor(Javadoc.class, "comment", String.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "tags" structural property of this node type.
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor TAGS_PROPERTY = 
+               new ChildListPropertyDescriptor(Javadoc.class, "tags", TagElement.class, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List properyList = new ArrayList(3);
+               createPropertyList(Javadoc.class, properyList);
+               addProperty(COMMENT_PROPERTY, properyList);
+               addProperty(TAGS_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+               
+               properyList = new ArrayList(2);
+               createPropertyList(Javadoc.class, properyList);
+               addProperty(TAGS_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_3_0 = 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+       
+       /**
+        * Canonical minimal doc comment.
+     * @since 3.0
+        */
+       private static final String MINIMAL_DOC_COMMENT = "/** */";//$NON-NLS-1$
+
+       /**
+        * The doc comment string, including opening and closing comment 
+        * delimiters; defaults to a minimal Javadoc comment.
+        * @deprecated The comment string was replaced in the 3.0 release
+        * by a representation of the structure of the doc comment.
+        * For backwards compatibility, it is still funcational as before.
+        */
+       private String comment = MINIMAL_DOC_COMMENT;
+       
+       /**
+        * The list of tag elements (element type: <code>TagElement</code>). 
+        * Defaults to an empty list.
+        * @since 3.0
+        */
+       private ASTNode.NodeList tags = 
+               new ASTNode.NodeList(TAGS_PROPERTY);
+
+       /**
+        * Creates a new AST node for a doc comment owned by the given AST.
+        * The new node has an empty list of tag elements (and, for backwards
+        * compatability, an unspecified, but legal, doc comment string).
+        * <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
+        */
+       Javadoc(AST ast) {
+               super(ast);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == COMMENT_PROPERTY) {
+                       if (get) {
+                               return getComment();
+                       } else {
+                               setComment((String) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == TAGS_PROPERTY) {
+                       return tags();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return JAVADOC;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               Javadoc result = new Javadoc(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                       result.setComment(getComment());
+               }
+               result.tags().addAll(ASTNode.copySubtrees(target, tags()));
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChildren(visitor, this.tags);
+               }
+               visitor.endVisit(this);
+       }
+
+       /**
+        * Returns the doc comment string, including the starting
+        * and ending comment delimiters, and any embedded line breaks.
+        * 
+        * @return the doc comment string
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @deprecated The comment string was replaced in the 3.0 release
+        * by a representation of the structure of the doc comment.
+        * See {@link #tags() tags}.
+        */
+       public String getComment() {
+           supportedOnlyIn2();
+               return this.comment;
+       }
+
+       /**
+        * Sets or clears the doc comment string. The documentation
+        * string must include the starting and ending comment delimiters,
+        * and any embedded line breaks.
+        * 
+        * @param docComment the doc comment string
+        * @exception IllegalArgumentException if the Java comment string is invalid
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @deprecated The comment string was replaced in the 3.0 release
+        * by a representation of the structure of the doc comment.
+        * See {@link #tags() tags}.
+        */
+       public void setComment(String docComment) {
+           supportedOnlyIn2();
+               if (docComment == null) {
+                       throw new IllegalArgumentException();
+               }
+               char[] source = docComment.toCharArray();
+               Scanner scanner = this.ast.scanner;
+               scanner.resetTo(0, source.length);
+               scanner.setSource(source);
+               try {
+                       int token;
+                       boolean onlyOneComment = false;
+                       while ((token = scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                               switch(token) {
+                                       case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+                                               if (onlyOneComment) {
+                                                       throw new IllegalArgumentException();
+                                               }
+                                               onlyOneComment = true;
+                                               break;
+                                       default:
+                                               onlyOneComment = false;
+                               }
+                       }
+                       if (!onlyOneComment) {
+                               throw new IllegalArgumentException();
+                       }
+               } catch (InvalidInputException e) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(COMMENT_PROPERTY);
+               this.comment = docComment;
+               postValueChange(COMMENT_PROPERTY);
+       }
+               
+       /**
+        * Returns the live list of tag elements that make up this doc 
+        * comment.
+        * <p>
+        * The tag elements cover everything except the starting and ending
+        * comment delimiters, and generally omit leading whitespace 
+        * (including a leading "*") and embedded line breaks.
+        * The first tag element of a typical doc comment represents
+        * all the material before the first explicit doc tag; this
+        * first tag element has a <code>null</code> tag name and
+        * generally contains 1 or more {@link TextElement}s,
+        * and possibly interspersed with tag elements for nested tags
+        * like "{@link String String}".
+        * Subsequent tag elements represent successive top-level doc
+        * tag (e.g., "@param", "@return", "@see").
+        * </p>
+        * <p>
+        * Adding and removing nodes from this list affects this node
+        * dynamically.
+        * </p>
+        * 
+        * @return the live list of tag elements in this doc comment
+        * (element type: <code>TagElement</code>)
+        * @since 3.0
+        */ 
+       public List tags() {
+               return this.tags;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               int size = super.memSize() + 2 * 4;
+               if (this.comment != MINIMAL_DOC_COMMENT) {
+                       // anything other than the default string takes space
+                       size += stringSize(this.comment);
+               }
+               return size;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize() + this.tags.listSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/LabeledStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/LabeledStatement.java
new file mode 100644 (file)
index 0000000..cd81eae
--- /dev/null
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Labeled statement AST node type.
+ *
+ * <pre>
+ * LabeledStatement:
+ *    Identifier <b>:</b> Statement
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class LabeledStatement extends Statement {
+                       
+       /**
+        * The "label" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor LABEL_PROPERTY = 
+               new ChildPropertyDescriptor(LabeledStatement.class, "label", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "body" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor BODY_PROPERTY = 
+               new ChildPropertyDescriptor(LabeledStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(LabeledStatement.class, propertyList);
+               addProperty(LABEL_PROPERTY, propertyList);
+               addProperty(BODY_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 label; lazily initialized; defaults to a unspecified,
+        * legal Java identifier.
+        */
+       private SimpleName labelName = null;
+
+       /**
+        * The body statement; lazily initialized; defaults to an unspecified, but 
+        * legal, statement.
+        */
+       private Statement body = null;
+
+       /**
+        * Creates a new AST node for a labeled statement owned by the given 
+        * AST. By default, the statement has an unspecified (but legal) label
+        * and an unspecified (but legal) statement.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       LabeledStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == LABEL_PROPERTY) {
+                       if (get) {
+                               return getLabel();
+                       } else {
+                               setLabel((SimpleName) child);
+                               return null;
+                       }
+               }
+               if (property == BODY_PROPERTY) {
+                       if (get) {
+                               return getBody();
+                       } else {
+                               setBody((Statement) 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.
+        */
+       final int getNodeType0() {
+               return LABELED_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               LabeledStatement result = new LabeledStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setLabel(
+                       (SimpleName) ASTNode.copySubtree(target, getLabel()));
+               result.setBody(
+                       (Statement) ASTNode.copySubtree(target, getBody()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getLabel());
+                       acceptChild(visitor, getBody());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the label of this labeled statement.
+        * 
+        * @return the variable name node
+        */ 
+       public SimpleName getLabel() {
+               if (this.labelName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.labelName == null) {
+                                       preLazyInit();
+                                       this.labelName= new SimpleName(this.ast);
+                                       postLazyInit(this.labelName, LABEL_PROPERTY);
+                               }
+                       }
+               }
+               return this.labelName;
+       }
+               
+       /**
+        * Sets the label of this labeled statement.
+        * 
+        * @param label the new label
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setLabel(SimpleName label) {
+               if (label == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.labelName;
+               preReplaceChild(oldChild, label, LABEL_PROPERTY);
+               this.labelName = label;
+               postReplaceChild(oldChild, label, LABEL_PROPERTY);
+       }
+       
+       /**
+        * Returns the body of this labeled statement.
+        * 
+        * @return the body statement node
+        */ 
+       public Statement getBody() {
+               if (this.body == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.body == null) {
+                                       preLazyInit();
+                                       this.body= new EmptyStatement(this.ast);
+                                       postLazyInit(this.body, BODY_PROPERTY);
+                               }
+                       }
+               }
+               return this.body;
+       }
+       
+       /**
+        * Sets the body of this labeled statement.
+        * <p>
+        * Special note: The Java language does not allow a local variable declaration
+        * to appear as the body of a labeled statement (they may only appear within a
+        * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+        * as the body of a <code>LabeledStatement</code>. To get something that will
+        * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+        * inside a <code>Block</code>.
+        * </p>
+        * 
+        * @param statement the body statement node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setBody(Statement statement) {
+               if (statement == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.body;
+               preReplaceChild(oldChild, statement, BODY_PROPERTY);
+               this.body = statement;
+               postReplaceChild(oldChild, statement, BODY_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.labelName == null ? 0 : getLabel().treeSize())
+                       + (this.body == null ? 0 : getBody().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/LineComment.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/LineComment.java
new file mode 100644 (file)
index 0000000..24076a1
--- /dev/null
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * End-of-line comment AST node type.
+ * <p>
+ * End-of-line comments begin with "//",
+ * must end with a line delimiter (as per JLS 3.7),
+ * and must not contain line breaks.
+ * </p>
+ * <p>
+ * Note that this node type is a comment placeholder, and is
+ * only useful for recording the source range where a comment
+ * was found in a source string. It is not useful for creating
+ * comments.
+ * </p>
+ * 
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class LineComment extends Comment {
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(1);
+               createPropertyList(LineComment.class, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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;
+       }
+                       
+       /**
+        * Creates a new line comment node owned by the given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       LineComment(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return LINE_COMMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               LineComment result = new LineComment(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize();
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MarkerAnnotation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MarkerAnnotation.java
new file mode 100644 (file)
index 0000000..c53330b
--- /dev/null
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Marker annotation node (added in JLS3 API). The marker annotation 
+ * "@foo" is equivalent to the normal annotation "@foo()".
+ * <p>
+ * <pre>
+ * MarkerAnnotation:
+ *   <b>@</b> TypeName
+ * </pre>
+ * </p>
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class MarkerAnnotation extends Annotation {
+
+       /**
+        * The "typeName" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor TYPE_NAME_PROPERTY = 
+               internalTypeNamePropertyFactory(MarkerAnnotation.class);
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(MarkerAnnotation.class, propertyList);
+               addProperty(TYPE_NAME_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+       
+       /**
+        * 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 AST.JLS* constants
+        * @return a list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+       
+       /**
+        * Creates a new unparented marker annotation node owned 
+        * by the given AST. By default, the annotation has an
+        * unspecified type name .
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       MarkerAnnotation(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == TYPE_NAME_PROPERTY) {
+                       if (get) {
+                               return getTypeName();
+                       } else {
+                               setTypeName((Name) child);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetChildProperty(property, get, child);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildPropertyDescriptor internalTypeNameProperty() {
+               return TYPE_NAME_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return MARKER_ANNOTATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               MarkerAnnotation result = new MarkerAnnotation(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setTypeName((Name) ASTNode.copySubtree(target, getTypeName()));
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getTypeName());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize();
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.typeName == null ? 0 : getTypeName().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MemberRef.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MemberRef.java
new file mode 100644 (file)
index 0000000..1f18312
--- /dev/null
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a member reference within a doc comment
+ * ({@link Javadoc}). The principal uses of these are in "@see" and "@link"
+ * tag elements, for references to field members (and occasionally to method
+ * and constructor members).
+ * <pre>
+ * MemberRef:
+ *             [ Name ] <b>#</b> Identifier
+ * </pre>
+ * 
+ * @see Javadoc
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MemberRef extends ASTNode implements IDocElement {
+       
+       /**
+        * The "qualifier" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor QUALIFIER_PROPERTY = 
+               new ChildPropertyDescriptor(MemberRef.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(MemberRef.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(MemberRef.class, propertyList);
+               addProperty(QUALIFIER_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 AST.JLS* constants
+        * @return a list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor})
+        * @since 3.0
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                       
+       /**
+        * The optional qualifier; <code>null</code> for none; defaults to none.
+        */
+       private Name optionalQualifier = null;
+
+       /**
+        * The member name; lazily initialized; defaults to a unspecified,
+        * legal Java method name.
+        */
+       private SimpleName memberName = null;
+       
+       /**
+        * Creates a new AST node for a member reference owned by the given 
+        * AST. By default, the method reference is for a member with an
+        * unspecified, but legal, name; and no qualifier.
+        * <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
+        */
+       MemberRef(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == QUALIFIER_PROPERTY) {
+                       if (get) {
+                               return getQualifier();
+                       } else {
+                               setQualifier((Name) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) 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.
+        */
+       final int getNodeType0() {
+               return MEMBER_REF;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               MemberRef result = new MemberRef(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+               result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getQualifier());
+                       acceptChild(visitor, getName());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the qualifier of this member reference, or 
+        * <code>null</code> if there is none.
+        * 
+        * @return the qualifier name node, or <code>null</code> if there is none
+        */ 
+       public Name getQualifier() {
+               return this.optionalQualifier;
+       }
+       
+       /**
+        * Sets or clears the qualifier of this member reference.
+        * 
+        * @param name the qualifier name node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setQualifier(Name name) {
+               ASTNode oldChild = this.optionalQualifier;
+               preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+               this.optionalQualifier = name;
+               postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+       }
+
+       /**
+        * Returns the name of the referenced member.
+        * 
+        * @return the member name node
+        */ 
+       public SimpleName getName() {
+               if (this.memberName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.memberName == null) {
+                                       preLazyInit();
+                                       this.memberName = new SimpleName(this.ast);
+                                       postLazyInit(this.memberName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.memberName;
+       }
+       
+       /**
+        * Sets the name of the referenced member to the given name.
+        * 
+        * @param name the new member name node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the name is <code>null</code></li>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName name) {
+               if (name == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.memberName;
+               preReplaceChild(oldChild, name, NAME_PROPERTY);
+               this.memberName = name;
+               postReplaceChild(oldChild, name, NAME_PROPERTY);
+       }
+
+       /**
+        * Resolves and returns the binding for the entity referred to by
+        * this member reference.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public final IBinding resolveBinding() {
+               return this.ast.getBindingResolver().resolveReference(this);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+                       + (this.memberName == null ? 0 : getName().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MemberValuePair.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MemberValuePair.java
new file mode 100644 (file)
index 0000000..31ca574
--- /dev/null
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Member value pair node (added in JLS3 API). Member value pairs appear in annotations.
+ * <p>
+ * <pre>
+ * MemberValuePair:
+ *   SimpleName <b>=</b> Expression
+ * </pre>
+ * Within annotations, only certain kinds of expressions are meaningful,
+ * including other annotations.
+ * </p>
+ *
+ * @see NormalAnnotation
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MemberValuePair extends ASTNode {
+       
+       /**
+        * The "name" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(MemberValuePair.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "value" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor VALUE_PROPERTY = 
+               new ChildPropertyDescriptor(MemberValuePair.class, "value", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(MemberValuePair.class, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               addProperty(VALUE_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 AST.JLS* constants
+        * @return a list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                                               
+       /**
+        * The member name; lazily initialized; defaults to a unspecified,
+        * legal name.
+        */
+       private SimpleName name = null;
+
+       /**
+        * The value; lazily initialized; defaults to a unspecified,
+        * legal expression.
+        */
+       private Expression value = null;
+       
+       /**
+        * Creates a new AST node for a member value pair owned by the given 
+        * AST. By default, the node has an unspecified (but legal) member
+        * name and value.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       MemberValuePair(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) child);
+                               return null;
+                       }
+               }
+               if (property == VALUE_PROPERTY) {
+                       if (get) {
+                               return getValue();
+                       } else {
+                               setValue((Expression) 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.
+        */
+       final int getNodeType0() {
+               return MEMBER_VALUE_PAIR;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               MemberValuePair result = new MemberValuePair(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+               result.setValue((Expression) ASTNode.copySubtree(target, getValue()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getName());
+                       acceptChild(visitor, getValue());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the member name.
+        * 
+        * @return the member name node
+        */ 
+       public SimpleName getName() {
+               if (this.name == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.name == null) {
+                                       preLazyInit();
+                                       this.name = new SimpleName(this.ast);
+                                       postLazyInit(this.name, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.name;
+       }
+       
+       /**
+        * Resolves and returns the member value pair binding for this member value pair.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        * @since 3.2
+        */     
+       public final IMemberValuePairBinding resolveMemberValuePairBinding() {
+               return this.ast.getBindingResolver().resolveMemberValuePair(this);
+       }
+
+       /**
+        * Sets the member name.
+        * 
+        * @param name the member name node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName name) {
+               if (name == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.name;
+               preReplaceChild(oldChild, name, NAME_PROPERTY);
+               this.name = name;
+               postReplaceChild(oldChild, name, NAME_PROPERTY);
+       }
+
+       /**
+        * Returns the value expression.
+        * 
+        * @return the value expression
+        */ 
+       public Expression getValue() {
+               if (this.value == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.value == null) {
+                                       preLazyInit();
+                                       this.value= new SimpleName(this.ast);
+                                       postLazyInit(this.value, VALUE_PROPERTY);
+                               }
+                       }
+               }
+               return this.value;
+       }
+
+       /**
+        * Sets the value of this pair.
+        * 
+        * @param value the new value
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setValue(Expression value) {
+               if (value == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.value;
+               preReplaceChild(oldChild, value, VALUE_PROPERTY);
+               this.value = value;
+               postReplaceChild(oldChild, value, VALUE_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.name == null ? 0 : getName().treeSize())
+                       + (this.value == null ? 0 : getValue().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MemberValuePairBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MemberValuePairBinding.java
new file mode 100644 (file)
index 0000000..0c15c4d
--- /dev/null
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 BEA Systems, Inc.
+ * 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:
+ *    tyeung@bea.com - initial API and implementation
+ *    IBM Corporation - implemented methods from IBinding
+ *    IBM Corporation - renamed from ResolvedMemberValuePair to MemberValuePairBinding
+ *    jgarms@bea.com - Fix for IllegalStateException
+ *******************************************************************************/
+package net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.lookup.ElementValuePair;
+import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeIds;
+
+/**
+ * Internal class.
+ */
+class MemberValuePairBinding implements IMemberValuePairBinding {
+       static final MemberValuePairBinding[] NoPair = new MemberValuePairBinding[0];
+       private static final Object NoValue = new Object();
+       private static final Object[] EmptyArray = new Object[0];
+
+       private ElementValuePair internalPair;
+       protected Object value = null;
+       protected BindingResolver bindingResolver;
+
+       static void appendValue(Object value, StringBuffer buffer) {
+               if (value instanceof Object[]) {
+                       Object[] values = (Object[]) value;
+                       buffer.append('{');
+                       for (int i = 0, l = values.length; i < l; i++) {
+                               if (i != 0)
+                                       buffer.append(", "); //$NON-NLS-1$
+                               appendValue(values[i], buffer);
+                       }
+                       buffer.append('}');
+               } else if (value instanceof ITypeBinding) {
+                       buffer.append(((ITypeBinding) value).getName());
+                       buffer.append(".class"); //$NON-NLS-1$
+               } else {
+                       buffer.append(value);
+               }
+       }
+
+       static Object buildDOMValue(final Object internalObject, BindingResolver resolver) {
+               if (internalObject == null)
+                       return null;
+
+               if (internalObject instanceof Constant) {
+                       Constant constant = (Constant) internalObject;
+                       switch (constant.typeID()) {
+                               case TypeIds.T_boolean:
+                                       return Boolean.valueOf(constant.booleanValue());
+                               case TypeIds.T_byte:
+                                       return new Byte(constant.byteValue());
+                               case TypeIds.T_char:
+                                       return new Character(constant.charValue());
+                               case TypeIds.T_double:
+                                       return new Double(constant.doubleValue());
+                               case TypeIds.T_float:
+                                       return new Float(constant.floatValue());
+                               case TypeIds.T_int:
+                                       return new Integer(constant.intValue());
+                               case TypeIds.T_long:
+                                       return new Long(constant.longValue());
+                               case TypeIds.T_short:
+                                       return new Short(constant.shortValue());
+                               case TypeIds.T_JavaLangString:
+                                       return constant.stringValue();
+                       }
+               } else if (internalObject instanceof net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) {
+                       return resolver.getTypeBinding((net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) internalObject);
+               } else if (internalObject instanceof net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding) {
+                       return resolver.getAnnotationInstance((net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding) internalObject);
+               } else if (internalObject instanceof net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding) {
+                       return resolver.getVariableBinding((net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding) internalObject);
+               } else if (internalObject instanceof Object[]) {
+                       Object[] elements = (Object[]) internalObject;
+                       int length = elements.length;
+                       Object[] values = length == 0 ? EmptyArray : new Object[length];
+                       for (int i = 0; i < length; i++)
+                               values[i] = buildDOMValue(elements[i], resolver);
+                       return values;
+               }
+               return null;
+       }
+
+       MemberValuePairBinding(ElementValuePair pair, BindingResolver resolver) {
+               this.internalPair = pair;
+               this.bindingResolver = resolver;
+       }
+
+       public IAnnotationBinding[] getAnnotations() {
+               return AnnotationBinding.NoAnnotations;
+       }
+
+       public IJavaElement getJavaElement() {
+               return null;
+       }
+
+       public String getKey() {
+               // TODO when implementing, update spec in IBinding
+               return null;
+       }
+
+       public int getKind() {
+               return IBinding.MEMBER_VALUE_PAIR;
+       }
+
+       public IMethodBinding getMethodBinding() {
+               return this.bindingResolver.getMethodBinding(this.internalPair.getMethodBinding());
+       }
+
+       public int getModifiers() {
+               return Modifier.NONE;
+       }
+
+       public String getName() {
+               if (this.internalPair == null)
+                       return null;
+               final char[] membername = this.internalPair.getName();
+               return membername == null ? null : new String(membername);
+       }
+
+       public Object getValue() {
+               if (value == null)
+                       init();
+               return value == NoValue ? null : this.value;
+       }
+
+       private void init() {
+               this.value = buildDOMValue(this.internalPair.getValue(), this.bindingResolver);
+               if (this.value == null)
+                       this.value = NoValue;
+       }
+
+       char[] internalName() {
+               return this.internalPair == null ? null : this.internalPair.getName();
+       }
+
+       public boolean isDefault() {
+               Object value2 = getValue();
+               Object defaultValue = getMethodBinding().getDefaultValue();
+               if (value2 instanceof IBinding) {
+                       if (defaultValue instanceof IBinding) {
+                               return ((IBinding) value2).isEqualTo((IBinding) defaultValue);
+                       }
+                       return false;
+               }
+               if (defaultValue == null) return false;
+               return defaultValue.equals(value2);
+       }
+
+       public boolean isDeprecated() {
+               MethodBinding methodBinding = this.internalPair.getMethodBinding();
+               return methodBinding == null ? false : methodBinding.isDeprecated();
+       }
+
+       public boolean isEqualTo(IBinding binding) {
+               if (this == binding)
+                       return true;
+               if (binding.getKind() != IBinding.MEMBER_VALUE_PAIR)
+                       return false;
+               IMemberValuePairBinding other = (IMemberValuePairBinding) binding;
+               if (!getMethodBinding().isEqualTo(other.getMethodBinding())) {
+                       return false;
+               }
+               Object otherValue = other.getValue();
+               Object currentValue = getValue();
+               if (currentValue == null) {
+                       return otherValue == null;
+               }
+               if (currentValue instanceof IBinding) {
+                       if (otherValue instanceof IBinding) {
+                               return ((IBinding) currentValue).isEqualTo((IBinding) otherValue);
+                       }
+                       return false;
+               }
+               return currentValue.equals(otherValue);
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.IBinding#isRecovered()
+        */
+       public boolean isRecovered() {
+               return false;
+       }
+
+       public boolean isSynthetic() {
+               return false;
+       }
+
+       public String toString() {
+               StringBuffer buffer = new StringBuffer();
+               buffer.append(getName());
+               buffer.append(" = "); //$NON-NLS-1$
+               appendValue(getValue(), buffer);
+               return buffer.toString();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Message.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Message.java
new file mode 100644 (file)
index 0000000..95ca93d
--- /dev/null
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Error message used to report potential errors found during the AST parsing
+ * or name resolution. Instances of this class are immutable.
+ *
+ * @since 2.0
+ */
+public class Message {
+       
+       /**
+        * The message.
+        */
+       private String message;
+       
+       /**
+        * The character index into the original source string, or -1 if none.
+        */
+       private int startPosition;
+       
+       /**
+        * The length in characters of the original source file indicating
+        * where the source fragment corresponding to this message ends.
+        */
+       private int length;
+       
+       /**
+        * Creates a message.
+        * 
+        * @param message the localized message reported by the compiler
+        * @param startPosition the 0-based character index into the 
+        *    original source file, or <code>-1</code> if no source position
+        *    information is to be recorded for this message
+        * @throws IllegalArgumentException if the message is null
+        * @throws IllegalArgumentException if the startPosition is lower than -1. 
+        */
+       public Message(String message, int startPosition) {
+               if (message == null) {
+                       throw new IllegalArgumentException();
+               }
+               if (startPosition < -1) {
+                       throw new IllegalArgumentException();
+               }
+               this.message = message;
+               this.startPosition = startPosition;
+               this.length = 0;
+       }
+
+       /**
+        * Creates a message.
+        * 
+        * @param message the localized message reported by the compiler
+        * @param startPosition the 0-based character index into the 
+        *    original source file, or <code>-1</code> if no source position
+        *    information is to be recorded for this message
+        * @param length the length in character of the original source file indicating
+        *        where the source fragment corresponding to this message ends. 0 or a negative number 
+        *    if none. A negative number will be converted to a 0-length.
+        * @throws IllegalArgumentException if the message is null
+        * @throws IllegalArgumentException if the startPosition is lower than -1. 
+        */
+       public Message(String message, int startPosition, int length) {
+               if (message == null) {
+                       throw new IllegalArgumentException();
+               }
+               if (startPosition < -1) {
+                       throw new IllegalArgumentException();
+               }
+               this.message = message;
+               this.startPosition = startPosition;
+               if (length <= 0) {
+                       this.length = 0;
+               } else {
+                       this.length = length;
+               }
+       }
+       
+       /**
+        * Returns the localized message.
+        * 
+        * @return the localized message
+        */
+       public String getMessage() {
+               return message;
+       }
+       
+       /**
+        * Returns the character index into the original source file.
+        * 
+        * @return the 0-based character index, or <code>-1</code>
+        *    if no source position information is recorded for this
+        *    message
+        * @deprecated Use {@link #getStartPosition()} instead.
+        * @see #getLength()
+        */
+       public int getSourcePosition() {
+               return getStartPosition();
+       }
+
+       /**
+        * Returns the character index into the original source file.
+        * 
+        * @return the 0-based character index, or <code>-1</code>
+        *    if no source position information is recorded for this
+        *    message
+        * @see #getLength()
+        */
+       public int getStartPosition() {
+               return startPosition;
+       }
+       
+       /**
+        * Returns the length in characters of the original source file indicating
+        * where the source fragment corresponding to this message ends.
+        * 
+        * @return a length, or <code>0</code>
+        *    if no source length information is recorded for this message
+        * @see #getStartPosition()
+        */
+       public int getLength() {
+               return length;
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodBinding.java
new file mode 100644 (file)
index 0000000..dc1ce40
--- /dev/null
@@ -0,0 +1,442 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import net.sourceforge.phpdt.internal.compiler.lookup.LookupEnvironment;
+import net.sourceforge.phpdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.RawTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeVariableBinding;
+import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
+import net.sourceforge.phpdt.internal.core.JavaElement;
+import net.sourceforge.phpdt.internal.core.util.Util;
+
+/**
+ * Internal implementation of method bindings.
+ */
+class MethodBinding implements IMethodBinding {
+
+       private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+               Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED | Modifier.NATIVE |
+               Modifier.STRICTFP;
+       private static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
+       private net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding binding;
+       private BindingResolver resolver;
+       private ITypeBinding[] parameterTypes;
+       private ITypeBinding[] exceptionTypes;
+       private String name;
+       private ITypeBinding declaringClass;
+       private ITypeBinding returnType;
+       private String key;
+       private ITypeBinding[] typeParameters;
+       private ITypeBinding[] typeArguments;
+       private IAnnotationBinding[] annotations;
+       private IAnnotationBinding[][] parameterAnnotations;
+
+       MethodBinding(BindingResolver resolver, net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding binding) {
+               this.resolver = resolver;
+               this.binding = binding;
+       }
+
+       public boolean isAnnotationMember() {
+               return getDeclaringClass().isAnnotation();
+       }
+
+       /**
+        * @see IMethodBinding#isConstructor()
+        */
+       public boolean isConstructor() {
+               return this.binding.isConstructor();
+       }
+
+       /**
+        * @see IMethodBinding#isDefaultConstructor()
+        * @since 3.0
+        */
+       public boolean isDefaultConstructor() {
+               final ReferenceBinding declaringClassBinding = this.binding.declaringClass;
+               if (declaringClassBinding.isRawType()) {
+                       RawTypeBinding rawTypeBinding = (RawTypeBinding) declaringClassBinding;
+                       if (rawTypeBinding.genericType().isBinaryBinding()) {
+                               return false;
+                       }
+                       return (this.binding.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0;
+               }
+               if (declaringClassBinding.isBinaryBinding()) {
+                       return false;
+               }
+               return (this.binding.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0;
+       }
+
+       /**
+        * @see IBinding#getName()
+        */
+       public String getName() {
+               if (name == null) {
+                       if (this.binding.isConstructor()) {
+                               name = this.getDeclaringClass().getName();
+                       } else {
+                               name = new String(this.binding.selector);
+                       }
+               }
+               return name;
+       }
+
+       public IAnnotationBinding[] getAnnotations() {
+               if (this.annotations != null) {
+                       return this.annotations;
+               }
+               net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = this.binding.getAnnotations();
+               int length = internalAnnotations == null ? 0 : internalAnnotations.length;
+               if (length != 0) {
+                       IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
+                       int convertedAnnotationCount = 0;
+                       for (int i = 0; i < length; i++) {
+                               net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
+                               final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
+                               if (annotationInstance == null) {
+                                       continue;
+                               }
+                               tempAnnotations[convertedAnnotationCount++] = annotationInstance;
+                       }
+                       if (convertedAnnotationCount != length) {
+                               if (convertedAnnotationCount == 0) {
+                                       return this.annotations = AnnotationBinding.NoAnnotations;
+                               }
+                               System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
+                       }
+                       return this.annotations = tempAnnotations;
+               }
+               return this.annotations = AnnotationBinding.NoAnnotations;
+       }
+
+       /**
+        * @see IMethodBinding#getDeclaringClass()
+        */
+       public ITypeBinding getDeclaringClass() {
+               if (this.declaringClass == null) {
+                       this.declaringClass = this.resolver.getTypeBinding(this.binding.declaringClass);
+               }
+               return declaringClass;
+       }
+
+       public IAnnotationBinding[] getParameterAnnotations(int index) {
+               if (getParameterTypes() == NO_TYPE_BINDINGS) {
+                       return AnnotationBinding.NoAnnotations;
+               }
+               if (this.parameterAnnotations != null) {
+                       return this.parameterAnnotations[index];
+               }
+               net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[][] bindingAnnotations = this.binding.getParameterAnnotations();
+               if (bindingAnnotations == null) return AnnotationBinding.NoAnnotations;
+
+               int length = bindingAnnotations.length;
+               IAnnotationBinding[][] domAnnotations = new IAnnotationBinding[length][];
+               for (int i = 0; i < length; i++) {
+                       net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[] paramBindingAnnotations = bindingAnnotations[i];
+                       int pLength = paramBindingAnnotations.length;
+                       domAnnotations[i] = new AnnotationBinding[pLength];
+                       for (int j=0; j<pLength; j++) {
+                               IAnnotationBinding domAnnotation = this.resolver.getAnnotationInstance(paramBindingAnnotations[j]);
+                               if (domAnnotation == null) {
+                                       domAnnotations[i] = AnnotationBinding.NoAnnotations;
+                                       break;
+                               }
+                               domAnnotations[i][j] = domAnnotation;
+                       }
+               }
+               this.parameterAnnotations = domAnnotations;
+               
+               return this.parameterAnnotations[index];
+       }
+
+       /**
+        * @see IMethodBinding#getParameterTypes()
+        */
+       public ITypeBinding[] getParameterTypes() {
+               if (this.parameterTypes != null) {
+                       return parameterTypes;
+               }
+               net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] parameters = this.binding.parameters;
+               int length = parameters == null ? 0 : parameters.length;
+               if (length == 0) {
+                       return this.parameterTypes = NO_TYPE_BINDINGS;
+               } else {
+                       ITypeBinding[] paramTypes = new ITypeBinding[length];
+                       for (int i = 0; i < length; i++) {
+                               final TypeBinding parameterBinding = parameters[i];
+                               if (parameterBinding != null) {
+                                       ITypeBinding typeBinding = this.resolver.getTypeBinding(parameterBinding);
+                                       if (typeBinding == null) {
+                                               return this.parameterTypes = NO_TYPE_BINDINGS;
+                                       }
+                                       paramTypes[i] = typeBinding;
+                               } else {
+                                       // log error
+                                       StringBuffer message = new StringBuffer("Report method binding where a parameter is null:\n");  //$NON-NLS-1$
+                                       message.append(this.toString());
+                                       Util.log(new IllegalArgumentException(), message.toString());
+                                       // report no binding since one or more parameter has no binding
+                                       return this.parameterTypes = NO_TYPE_BINDINGS;
+                               }
+                       }
+                       return this.parameterTypes = paramTypes;
+               }
+       }
+
+       /**
+        * @see IMethodBinding#getReturnType()
+        */
+       public ITypeBinding getReturnType() {
+               if (this.returnType == null) {
+                       this.returnType = this.resolver.getTypeBinding(this.binding.returnType);
+               }
+               return this.returnType;
+       }
+
+       public Object getDefaultValue() {
+               if (isAnnotationMember())
+                       return MemberValuePairBinding.buildDOMValue(this.binding.getDefaultValue(), this.resolver);
+               return null;
+       }
+
+       /**
+        * @see IMethodBinding#getExceptionTypes()
+        */
+       public ITypeBinding[] getExceptionTypes() {
+               if (this.exceptionTypes != null) {
+                       return exceptionTypes;
+               }
+               net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] exceptions = this.binding.thrownExceptions;
+               int length = exceptions == null ? 0 : exceptions.length;
+               if (length == 0) {
+                       return this.exceptionTypes = NO_TYPE_BINDINGS;
+               }
+               ITypeBinding[] exTypes = new ITypeBinding[length];
+               for (int i = 0; i < length; i++) {
+                       ITypeBinding typeBinding = this.resolver.getTypeBinding(exceptions[i]);
+                       if (typeBinding == null) {
+                               return this.exceptionTypes = NO_TYPE_BINDINGS;
+                       }
+                       exTypes[i] = typeBinding;
+               }
+               return this.exceptionTypes = exTypes;
+       }
+
+       public IJavaElement getJavaElement() {
+               JavaElement element = getUnresolvedJavaElement();
+               if (element == null)
+                       return null;
+               return element.resolved(this.binding);
+       }
+
+       private JavaElement getUnresolvedJavaElement() {
+               if (!(this.resolver instanceof DefaultBindingResolver)) return null;
+               
+               DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
+               return Util.getUnresolvedJavaElement(
+                               this.binding,
+                               defaultBindingResolver.workingCopyOwner,
+                               defaultBindingResolver.getBindingsToNodesMap());
+       }
+
+       /**
+        * @see IBinding#getKind()
+        */
+       public int getKind() {
+               return IBinding.METHOD;
+       }
+
+       /**
+        * @see IBinding#getModifiers()
+        */
+       public int getModifiers() {
+               return this.binding.getAccessFlags() & VALID_MODIFIERS;
+       }
+
+       /**
+        * @see IBinding#isDeprecated()
+        */
+       public boolean isDeprecated() {
+               return this.binding.isDeprecated();
+       }
+
+       /**
+        * @see IBinding#isRecovered()
+        */
+       public boolean isRecovered() {
+               return false;
+       }
+
+       /**
+        * @see IBinding#isSynthetic()
+        */
+       public boolean isSynthetic() {
+               return this.binding.isSynthetic();
+       }
+
+       /**
+        * @see org.eclipse.jdt.core.dom.IMethodBinding#isVarargs()
+        * @since 3.1
+        */
+       public boolean isVarargs() {
+               return this.binding.isVarargs();
+       }
+
+       /**
+        * @see IBinding#getKey()
+        */
+       public String getKey() {
+               if (this.key == null) {
+                       this.key = new String(this.binding.computeUniqueKey());
+               }
+               return this.key;
+       }
+
+       /**
+        * @see IBinding#isEqualTo(IBinding)
+        * @since 3.1
+        */
+       public boolean isEqualTo(IBinding other) {
+               if (other == this) {
+                       // identical binding - equal (key or no key)
+                       return true;
+               }
+               if (other == null) {
+                       // other binding missing
+                       return false;
+               }
+               if (!(other instanceof MethodBinding)) {
+                       return false;
+               }
+               net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding otherBinding = ((MethodBinding) other).binding;
+               return BindingComparator.isEqual(this.binding, otherBinding);
+       }
+
+       /**
+        * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeParameters()
+        */
+       public ITypeBinding[] getTypeParameters() {
+               if (this.typeParameters != null) {
+                       return this.typeParameters;
+               }
+               TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+               int typeVariableBindingsLength = typeVariableBindings == null ? 0 : typeVariableBindings.length;
+               if (typeVariableBindingsLength == 0) {
+                       return this.typeParameters = NO_TYPE_BINDINGS;
+               }
+               ITypeBinding[] tParameters = new ITypeBinding[typeVariableBindingsLength];
+               for (int i = 0; i < typeVariableBindingsLength; i++) {
+                       ITypeBinding typeBinding = this.resolver.getTypeBinding(typeVariableBindings[i]);
+                       if (typeBinding == null) {
+                               return this.typeParameters = NO_TYPE_BINDINGS;
+                       }
+                       tParameters[i] = typeBinding;
+               }
+               return this.typeParameters = tParameters;
+       }
+
+       /**
+        * @see org.eclipse.jdt.core.dom.IMethodBinding#isGenericMethod()
+        * @since 3.1
+        */
+       public boolean isGenericMethod() {
+               // equivalent to return getTypeParameters().length > 0;
+               if (this.typeParameters != null) {
+                       return this.typeParameters.length > 0;
+               }
+               TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+               return (typeVariableBindings != null && typeVariableBindings.length > 0);
+       }
+
+       /**
+        * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeArguments()
+        */
+       public ITypeBinding[] getTypeArguments() {
+               if (this.typeArguments != null) {
+                       return this.typeArguments;
+               }
+
+               if (this.binding instanceof ParameterizedGenericMethodBinding) {
+                       ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) this.binding;
+                       net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] typeArgumentsBindings = genericMethodBinding.typeArguments;
+                       int typeArgumentsLength = typeArgumentsBindings == null ? 0 : typeArgumentsBindings.length;
+                       if (typeArgumentsLength != 0) {
+                               ITypeBinding[] tArguments = new ITypeBinding[typeArgumentsLength];
+                               for (int i = 0; i < typeArgumentsLength; i++) {
+                                       ITypeBinding typeBinding = this.resolver.getTypeBinding(typeArgumentsBindings[i]);
+                                       if (typeBinding == null) {
+                                               return this.typeArguments = NO_TYPE_BINDINGS;
+                                       }
+                                       tArguments[i] = typeBinding;
+                               }
+                               return this.typeArguments = tArguments;
+                       }
+               }
+               return this.typeArguments = NO_TYPE_BINDINGS;
+       }
+
+       /**
+        * @see org.eclipse.jdt.core.dom.IMethodBinding#isParameterizedMethod()
+        */
+       public boolean isParameterizedMethod() {
+               return (this.binding instanceof ParameterizedGenericMethodBinding)
+                       && !((ParameterizedGenericMethodBinding) this.binding).isRaw;
+       }
+
+       /**
+        * @see org.eclipse.jdt.core.dom.IMethodBinding#isRawMethod()
+        */
+       public boolean isRawMethod() {
+               return (this.binding instanceof ParameterizedGenericMethodBinding)
+                       && ((ParameterizedGenericMethodBinding) this.binding).isRaw;
+       }
+
+       public boolean isSubsignature(IMethodBinding otherMethod) {
+               try {
+                       LookupEnvironment lookupEnvironment = this.resolver.lookupEnvironment();
+                       return lookupEnvironment != null
+                               && lookupEnvironment.methodVerifier().isMethodSubsignature(this.binding, ((MethodBinding) otherMethod).binding);
+               } catch (AbortCompilation e) {
+                       // don't surface internal exception to clients
+                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+                       return false;
+               }
+       }
+
+       /**
+        * @see org.eclipse.jdt.core.dom.IMethodBinding#getMethodDeclaration()
+        */
+       public IMethodBinding getMethodDeclaration() {
+               return this.resolver.getMethodBinding(this.binding.original());
+       }
+
+       /**
+        * @see IMethodBinding#overrides(IMethodBinding)
+        */
+       public boolean overrides(IMethodBinding otherMethod) {
+                       LookupEnvironment lookupEnvironment = this.resolver.lookupEnvironment();
+                       return lookupEnvironment != null
+                               && lookupEnvironment.methodVerifier().doesMethodOverride(this.binding, ((MethodBinding) otherMethod).binding);
+       }
+
+       /**
+        * For debugging purpose only.
+        * @see java.lang.Object#toString()
+        */
+       public String toString() {
+               return this.binding.toString();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodDeclaration.java
new file mode 100644 (file)
index 0000000..3e9f828
--- /dev/null
@@ -0,0 +1,907 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Method declaration AST node type. A method declaration
+ * is the union of a method declaration and a constructor declaration.
+ * For JLS2:
+ * <pre>
+ * MethodDeclaration:
+ *    [ Javadoc ] { Modifier } ( Type | <b>void</b> ) Identifier <b>(</b>
+ *        [ FormalParameter 
+ *                  { <b>,</b> FormalParameter } ] <b>)</b> {<b>[</b> <b>]</b> }
+ *        [ <b>throws</b> TypeName { <b>,</b> TypeName } ] ( Block | <b>;</b> )
+ * ConstructorDeclaration:
+ *    [ Javadoc ] { Modifier } Identifier <b>(</b>
+ *               [ FormalParameter
+ *                      { <b>,</b> FormalParameter } ] <b>)</b>
+ *        [<b>throws</b> TypeName { <b>,</b> TypeName } ] Block
+ * </pre>
+ * For JLS3, type parameters and reified modifiers
+ * (and annotations) were added:
+ * <pre>
+ * MethodDeclaration:
+ *    [ Javadoc ] { ExtendedModifier }
+ *               [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
+ *        ( Type | <b>void</b> ) Identifier <b>(</b>
+ *        [ FormalParameter 
+ *                  { <b>,</b> FormalParameter } ] <b>)</b> {<b>[</b> <b>]</b> }
+ *        [ <b>throws</b> TypeName { <b>,</b> TypeName } ] ( Block | <b>;</b> )
+ * ConstructorDeclaration:
+ *    [ Javadoc ] { ExtendedModifier }
+ *               [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
+ *        Identifier <b>(</b>
+ *               [ FormalParameter
+ *                      { <b>,</b> FormalParameter } ] <b>)</b>
+ *        [<b>throws</b> TypeName { <b>,</b> TypeName } ] Block
+ * </pre>
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the first modifier keyword (if modifiers), or the
+ * first character of the "&lt;" token (method, no modifiers, type parameters), 
+ * or the first character of the return type (method, no modifiers, no type
+ * parameters), or the first character of the identifier (constructor, 
+ * no modifiers). The source range extends through the last character of the
+ * ";" token (if no body), or the last character of the block (if body).
+ * </p>
+ *
+ * @since 2.0 
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MethodDeclaration extends BodyDeclaration {
+       
+       /**
+        * The "javadoc" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
+               internalJavadocPropertyFactory(MethodDeclaration.class);
+
+       /**
+        * The "modifiers" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor MODIFIERS_PROPERTY = 
+               internalModifiersPropertyFactory(MethodDeclaration.class);
+       
+       /**
+        * The "modifiers" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
+               internalModifiers2PropertyFactory(MethodDeclaration.class);
+       
+       /**
+        * The "constructor" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor CONSTRUCTOR_PROPERTY = 
+               new SimplePropertyDescriptor(MethodDeclaration.class, "constructor", boolean.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(MethodDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "returnType" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor RETURN_TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(MethodDeclaration.class, "returnType", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "returnType2" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildPropertyDescriptor RETURN_TYPE2_PROPERTY = 
+               new ChildPropertyDescriptor(MethodDeclaration.class, "returnType2", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "extraDimensions" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor EXTRA_DIMENSIONS_PROPERTY = 
+               new SimplePropertyDescriptor(MethodDeclaration.class, "extraDimensions", int.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "typeParameters" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor TYPE_PARAMETERS_PROPERTY = 
+               new ChildListPropertyDescriptor(MethodDeclaration.class, "typeParameters", TypeParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "parameters" structural property of this node type).
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor PARAMETERS_PROPERTY = 
+               new ChildListPropertyDescriptor(MethodDeclaration.class, "parameters", SingleVariableDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "thrownExceptions" structural property of this node type).
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor THROWN_EXCEPTIONS_PROPERTY = 
+               new ChildListPropertyDescriptor(MethodDeclaration.class, "thrownExceptions", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "body" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor BODY_PROPERTY = 
+               new ChildPropertyDescriptor(MethodDeclaration.class, "body", Block.class, OPTIONAL, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List propertyList = new ArrayList(10);
+               createPropertyList(MethodDeclaration.class, propertyList);
+               addProperty(JAVADOC_PROPERTY, propertyList);
+               addProperty(MODIFIERS_PROPERTY, propertyList);
+               addProperty(CONSTRUCTOR_PROPERTY, propertyList);
+               addProperty(RETURN_TYPE_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               addProperty(PARAMETERS_PROPERTY, propertyList);
+               addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+               addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
+               addProperty(BODY_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+               
+               propertyList = new ArrayList(11);
+               createPropertyList(MethodDeclaration.class, propertyList);
+               addProperty(JAVADOC_PROPERTY, propertyList);
+               addProperty(MODIFIERS2_PROPERTY, propertyList);
+               addProperty(CONSTRUCTOR_PROPERTY, propertyList);
+               addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
+               addProperty(RETURN_TYPE2_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               addProperty(PARAMETERS_PROPERTY, propertyList);
+               addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+               addProperty(THROWN_EXCEPTIONS_PROPERTY, propertyList);
+               addProperty(BODY_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 AST.JLS* constants
+        * @return a list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor})
+        * @since 3.0
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * <code>true</code> for a constructor, <code>false</code> for a method.
+        * Defaults to method.
+        */
+       private boolean isConstructor = false;
+       
+       /**
+        * The method name; lazily initialized; defaults to an unspecified,
+        * legal Java identifier.
+        */
+       private SimpleName methodName = null;
+
+       /**
+        * The parameter declarations 
+        * (element type: <code>SingleVariableDeclaration</code>).
+        * Defaults to an empty list.
+        */
+       private ASTNode.NodeList parameters =
+               new ASTNode.NodeList(PARAMETERS_PROPERTY);
+       
+       /**
+        * The return type.
+        * JLS2 behevior: lazily initialized; defaults to void.
+        * JLS3 behavior; lazily initialized; defaults to void; null allowed.
+        * Note that this field is ignored for constructor declarations.
+        */
+       private Type returnType = null;
+       
+       /**
+        * Indicated whether the return type has been initialized.
+        * @since 3.1
+        */
+       private boolean returnType2Initialized = false;
+       
+       /**
+        * The type paramters (element type: <code>TypeParameter</code>). 
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * @since 3.1
+        */
+       private ASTNode.NodeList typeParameters = null;
+
+       /**
+        * The number of array dimensions that appear after the parameters, rather
+        * than after the return type itself; defaults to 0.
+        * 
+        * @since 2.1
+        */
+       private int extraArrayDimensions = 0;
+
+       /**
+        * The list of thrown exception names (element type: <code>Name</code>).
+        * Defaults to an empty list.
+        */
+       private ASTNode.NodeList thrownExceptions =
+               new ASTNode.NodeList(THROWN_EXCEPTIONS_PROPERTY);
+
+       /**
+        * The method body, or <code>null</code> if none.
+        * Defaults to none.
+        */
+       private Block optionalBody = null;
+       
+       /**
+        * Creates a new AST node for a method declaration owned 
+        * by the given AST. By default, the declaration is for a method of an
+        * unspecified, but legal, name; no modifiers; no javadoc; no type 
+        * parameters; void return type; no parameters; no array dimensions after 
+        * the parameters; no thrown exceptions; and no body (as opposed to an
+        * empty body).
+        * <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
+        */
+       MethodDeclaration(AST ast) {
+               super(ast);
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY);
+               }
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+               if (property == MODIFIERS_PROPERTY) {
+                       if (get) {
+                               return getModifiers();
+                       } else {
+                               internalSetModifiers(value);
+                               return 0;
+                       }
+               }
+               if (property == EXTRA_DIMENSIONS_PROPERTY) {
+                       if (get) {
+                               return getExtraDimensions();
+                       } else {
+                               setExtraDimensions(value);
+                               return 0;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetIntProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+               if (property == CONSTRUCTOR_PROPERTY) {
+                       if (get) {
+                               return isConstructor();
+                       } else {
+                               setConstructor(value);
+                               return false;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetBooleanProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == JAVADOC_PROPERTY) {
+                       if (get) {
+                               return getJavadoc();
+                       } else {
+                               setJavadoc((Javadoc) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) child);
+                               return null;
+                       }
+               }
+               if (property == RETURN_TYPE_PROPERTY) {
+                       if (get) {
+                               return getReturnType();
+                       } else {
+                               setReturnType((Type) child);
+                               return null;
+                       }
+               }
+               if (property == RETURN_TYPE2_PROPERTY) {
+                       if (get) {
+                               return getReturnType2();
+                       } else {
+                               setReturnType2((Type) child);
+                               return null;
+                       }
+               }
+               if (property == BODY_PROPERTY) {
+                       if (get) {
+                               return getBody();
+                       } else {
+                               setBody((Block) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == MODIFIERS2_PROPERTY) {
+                       return modifiers();
+               }
+               if (property == TYPE_PARAMETERS_PROPERTY) {
+                       return typeParameters();
+               }
+               if (property == PARAMETERS_PROPERTY) {
+                       return parameters();
+               }
+               if (property == THROWN_EXCEPTIONS_PROPERTY) {
+                       return thrownExceptions();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildPropertyDescriptor internalJavadocProperty() {
+               return JAVADOC_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildListPropertyDescriptor internalModifiers2Property() {
+               return MODIFIERS2_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final SimplePropertyDescriptor internalModifiersProperty() {
+               return MODIFIERS_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return METHOD_DECLARATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               MethodDeclaration result = new MethodDeclaration(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setJavadoc(
+                       (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                       result.internalSetModifiers(getModifiers());
+                       result.setReturnType(
+                                       (Type) ASTNode.copySubtree(target, getReturnType()));
+               }
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+                       result.typeParameters().addAll(
+                                       ASTNode.copySubtrees(target, typeParameters()));
+                       result.setReturnType2(
+                                       (Type) ASTNode.copySubtree(target, getReturnType2()));
+               }
+               result.setConstructor(isConstructor());
+               result.setExtraDimensions(getExtraDimensions());
+               result.setName((SimpleName) getName().clone(target));
+               result.parameters().addAll(
+                       ASTNode.copySubtrees(target, parameters()));
+               result.thrownExceptions().addAll(
+                       ASTNode.copySubtrees(target, thrownExceptions()));
+               result.setBody(
+                       (Block) ASTNode.copySubtree(target, getBody()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getJavadoc());
+                       if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                               acceptChild(visitor, getReturnType());
+                       } else {
+                               acceptChildren(visitor, this.modifiers);
+                               acceptChildren(visitor, this.typeParameters);
+                               acceptChild(visitor, getReturnType2());
+                       }
+                       // n.b. visit return type even for constructors
+                       acceptChild(visitor, getName());
+                       acceptChildren(visitor, this.parameters);
+                       acceptChildren(visitor, this.thrownExceptions);
+                       acceptChild(visitor, getBody());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns whether this declaration declares a constructor or a method.
+        * 
+        * @return <code>true</code> if this is a constructor declaration,
+        *    and <code>false</code> if this is a method declaration
+        */ 
+       public boolean isConstructor() {
+               return this.isConstructor;
+       }
+       
+       /**
+        * Sets whether this declaration declares a constructor or a method.
+        * 
+        * @param isConstructor <code>true</code> for a constructor declaration,
+        *    and <code>false</code> for a method declaration
+        */ 
+       public void setConstructor(boolean isConstructor) {
+               preValueChange(CONSTRUCTOR_PROPERTY);
+               this.isConstructor = isConstructor;
+               postValueChange(CONSTRUCTOR_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of type parameters of this method
+        * declaration (added in JLS3 API). This list is non-empty for parameterized methods.
+        * 
+        * @return the live list of type parameters
+        *    (element type: <code>TypeParameter</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public List typeParameters() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.typeParameters == null) {
+                       unsupportedIn2();
+               }
+               return this.typeParameters;
+       }
+       
+       /**
+        * Returns the name of the method declared in this method declaration.
+        * For a constructor declaration, this should be the same as the name 
+        * of the class.
+        * 
+        * @return the method name node
+        */ 
+       public SimpleName getName() {
+               if (this.methodName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.methodName == null) {
+                                       preLazyInit();
+                                       this.methodName = new SimpleName(this.ast);
+                                       postLazyInit(this.methodName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.methodName;
+       }
+       
+       /**
+        * Sets the name of the method declared in this method declaration to the
+        * given name. For a constructor declaration, this should be the same as 
+        * the name of the class.
+        * 
+        * @param methodName the new method name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName methodName) {
+               if (methodName == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.methodName;
+               preReplaceChild(oldChild, methodName, NAME_PROPERTY);
+               this.methodName = methodName;
+               postReplaceChild(oldChild, methodName, NAME_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of method parameter declarations for this
+        * method declaration.
+        * 
+        * @return the live list of method parameter declarations
+        *    (element type: <code>SingleVariableDeclaration</code>)
+        */ 
+       public List parameters() {
+               return this.parameters;
+       }
+       
+       /**
+        * Returns whether this method declaration declares a
+        * variable arity method (added in JLS3 API). The convenience method checks
+        * whether the last parameter is so marked.
+        * 
+        * @return <code>true</code> if this is a variable arity method declaration,
+        *    and <code>false</code> otherwise
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @see SingleVariableDeclaration#isVarargs()
+        * @since 3.1
+        */ 
+       public boolean isVarargs() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.modifiers == null) {
+                       unsupportedIn2();
+               }
+               if (parameters().isEmpty()) {
+                       return false;
+               } else {
+                       SingleVariableDeclaration v = (SingleVariableDeclaration) parameters().get(parameters().size() - 1);
+                       return v.isVarargs();
+               }
+       }
+       
+       /**
+        * Returns the live ordered list of thrown exception names in this method 
+        * declaration.
+        * 
+        * @return the live list of exception names
+        *    (element type: <code>Name</code>)
+        */ 
+       public List thrownExceptions() {
+               return this.thrownExceptions;
+       }
+       
+       /**
+        * Returns the return type of the method declared in this method 
+        * declaration, exclusive of any extra array dimensions (JLS2 API only). 
+        * This is one of the few places where the void type is meaningful.
+        * <p>
+        * Note that this child is not relevant for constructor declarations
+        * (although, it does still figure in subtree equality comparisons
+        * and visits), and is devoid of the binding information ordinarily
+        * available.
+        * </p>
+        * 
+        * @return the return type, possibly the void primitive type
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @deprecated In the JLS3 API, this method is replaced by {@link #getReturnType2()},
+        * which may return <code>null</code>.
+        */ 
+       public Type getReturnType() {
+               return internalGetReturnType();
+       }
+       
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ final Type internalGetReturnType() {
+               supportedOnlyIn2();
+               if (this.returnType == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.returnType == null) {
+                                       preLazyInit();
+                                       this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+                                       postLazyInit(this.returnType, RETURN_TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.returnType;
+       }
+
+       /**
+        * Sets the return type of the method declared in this method declaration
+        * to the given type, exclusive of any extra array dimensions (JLS2 API only). This is one
+        * of the few places where the void type is meaningful.
+        * <p>
+        * Note that this child is not relevant for constructor declarations
+        * (although it does still figure in subtree equality comparisons and visits).
+        * </p>
+        * 
+        * @param type the new return type, possibly the void primitive type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @deprecated In the JLS3 API, this method is replaced by 
+        * {@link #setReturnType2(Type)}, which accepts <code>null</code>.
+        */ 
+       public void setReturnType(Type type) {
+               internalSetReturnType(type);
+       }
+       
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ void internalSetReturnType(Type type) {
+           supportedOnlyIn2();
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.returnType;
+               preReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
+               this.returnType = type;
+               postReplaceChild(oldChild, type, RETURN_TYPE_PROPERTY);
+       }
+
+       /**
+        * Returns the return type of the method declared in this method 
+        * declaration, exclusive of any extra array dimensions (added in JLS3 API). 
+        * This is one of the few places where the void type is meaningful.
+        * <p>
+        * Note that this child is not relevant for constructor declarations
+        * (although, if present, it does still figure in subtree equality comparisons
+        * and visits), and is devoid of the binding information ordinarily
+        * available. In the JLS2 API, the return type is mandatory. 
+        * In the JLS3 API, the return type is optional.
+        * </p>
+        * 
+        * @return the return type, possibly the void primitive type,
+        * or <code>null</code> if none
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public Type getReturnType2() {
+           unsupportedIn2();
+               if (this.returnType == null && !this.returnType2Initialized) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.returnType == null && !this.returnType2Initialized) {
+                                       preLazyInit();
+                                       this.returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
+                                       this.returnType2Initialized = true;
+                                       postLazyInit(this.returnType, RETURN_TYPE2_PROPERTY);
+                               }
+                       }
+               }
+               return this.returnType;
+       }
+
+       /**
+        * Sets the return type of the method declared in this method declaration
+        * to the given type, exclusive of any extra array dimensions (added in JLS3 API).
+        * This is one of the few places where the void type is meaningful.
+        * <p>
+        * Note that this child is not relevant for constructor declarations
+        * (although it does still figure in subtree equality comparisons and visits).
+        * In the JLS2 API, the return type is mandatory. 
+        * In the JLS3 API, the return type is optional.
+        * </p>
+        * 
+        * @param type the new return type, possibly the void primitive type,
+        * or <code>null</code> if none
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        * @since 3.1
+        */ 
+       public void setReturnType2(Type type) {
+           unsupportedIn2();
+               this.returnType2Initialized = true;
+               ASTNode oldChild = this.returnType;
+               preReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
+               this.returnType = type;
+               postReplaceChild(oldChild, type, RETURN_TYPE2_PROPERTY);
+       }
+
+       /**
+        * Returns the number of extra array dimensions over and above the 
+        * explicitly-specified return type.
+        * <p>
+        * For example, <code>int foo()[][]</code> has a return type of 
+        * <code>int</code> and two extra array dimensions; 
+        * <code>int[][] foo()</code> has a return type of <code>int[][]</code>
+        * and zero extra array dimensions. The two constructs have different
+        * ASTs, even though there are really syntactic variants of the same
+        * method declaration.
+        * </p>
+        * 
+        * @return the number of extra array dimensions
+        * @since 2.1
+        */ 
+       public int getExtraDimensions() {
+               return this.extraArrayDimensions;
+       }
+
+       /**
+        * Sets the number of extra array dimensions over and above the 
+        * explicitly-specified return type.
+        * <p>
+        * For example, <code>int foo()[][]</code> is rendered as a return
+        * type of <code>int</code> with two extra array dimensions; 
+        * <code>int[][] foo()</code> is rendered as a return type of 
+        * <code>int[][]</code> with zero extra array dimensions. The two
+        * constructs have different ASTs, even though there are really syntactic
+        * variants of the same method declaration.
+        * </p>
+        * 
+        * @param dimensions the number of array dimensions
+        * @exception IllegalArgumentException if the number of dimensions is
+        *    negative
+        * @since 2.1
+        */ 
+       public void setExtraDimensions(int dimensions) {
+               if (dimensions < 0) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(EXTRA_DIMENSIONS_PROPERTY);
+               this.extraArrayDimensions = dimensions;
+               postValueChange(EXTRA_DIMENSIONS_PROPERTY);
+       }
+
+       /**
+        * Returns the body of this method declaration, or <code>null</code> if 
+        * this method has <b>no</b> body.
+        * <p>
+        * Note that there is a subtle difference between having no body and having
+        * an empty body ("{}").
+        * </p>
+        * 
+        * @return the method body, or <code>null</code> if this method has no
+        *    body
+        */ 
+       public Block getBody() {
+               return this.optionalBody;
+       }
+
+       /**
+        * Sets or clears the body of this method declaration.
+        * <p>
+        * Note that there is a subtle difference between having no body 
+        * (as in <code>"void foo();"</code>) and having an empty body (as in
+        * "void foo() {}"). Abstract methods, and methods declared in interfaces,
+        * have no body. Non-abstract methods, and all constructors, have a body.
+        * </p>
+        * 
+        * @param body the block node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setBody(Block body) {
+               // a MethodDeclaration may occur in a Block - must check cycles
+               ASTNode oldChild = this.optionalBody;
+               preReplaceChild(oldChild, body, BODY_PROPERTY);
+               this.optionalBody = body;
+               postReplaceChild(oldChild, body, BODY_PROPERTY);
+       }
+
+       /**
+        * Resolves and returns the binding for the method or constructor declared
+        * in this method or constructor declaration.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public IMethodBinding resolveBinding() {
+               return this.ast.getBindingResolver().resolveMethod(this);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 9 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+                       + (this.modifiers == null ? 0 : this.modifiers.listSize())
+                       + (this.typeParameters == null ? 0 : this.typeParameters.listSize())
+                       + (this.methodName == null ? 0 : getName().treeSize())
+                       + (this.returnType == null ? 0 : this.returnType.treeSize())
+                       + this.parameters.listSize()
+                       + this.thrownExceptions.listSize()
+                       + (this.optionalBody == null ? 0 : getBody().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodInvocation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodInvocation.java
new file mode 100644 (file)
index 0000000..ed730ca
--- /dev/null
@@ -0,0 +1,399 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Method invocation expression AST node type.
+ * For JLS2:
+ * <pre>
+ * MethodInvocation:
+ *     [ Expression <b>.</b> ] Identifier
+ *         <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ * </pre>
+ * For JLS3, type arguments are added:
+ * <pre>
+ * MethodInvocation:
+ *     [ Expression <b>.</b> ]
+ *         [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ *         Identifier <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MethodInvocation extends Expression {
+
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
+               new ChildPropertyDescriptor(MethodInvocation.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "typeArguments" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+               new ChildListPropertyDescriptor(MethodInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY =
+               new ChildPropertyDescriptor(MethodInvocation.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "arguments" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+               new ChildListPropertyDescriptor(MethodInvocation.class, "arguments", Expression.class, 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_2_0;
+
+       /**
+        * A list of property descriptors (element type:
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+
+       static {
+               List properyList = new ArrayList(4);
+               createPropertyList(MethodInvocation.class, properyList);
+               addProperty(EXPRESSION_PROPERTY, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               addProperty(ARGUMENTS_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+
+               properyList = new ArrayList(5);
+               createPropertyList(MethodInvocation.class, properyList);
+               addProperty(EXPRESSION_PROPERTY, properyList);
+               addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               addProperty(ARGUMENTS_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_3_0 = 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+
+       /**
+        * The expression; <code>null</code> for none; defaults to none.
+        */
+       private Expression optionalExpression = null;
+
+       /**
+        * The type arguments (element type: <code>Type</code>).
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * @since 3.1
+        */
+       private ASTNode.NodeList typeArguments = null;
+
+       /**
+        * The method name; lazily initialized; defaults to a unspecified,
+        * legal Java method name.
+        */
+       private SimpleName methodName = null;
+
+       /**
+        * The list of argument expressions (element type:
+        * <code>Expression</code>). Defaults to an empty list.
+        */
+       private ASTNode.NodeList arguments =
+               new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+       /**
+        * Creates a new AST node for a method invocation expression owned by the
+        * given AST. By default, no expression, no type arguments,
+        * an unspecified, but legal, method name, and an empty list of arguments.
+        *
+        * @param ast the AST that is to own this node
+        */
+       MethodInvocation(AST ast) {
+               super(ast);
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+               }
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) child);
+                               return null;
+                       }
+               }
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == ARGUMENTS_PROPERTY) {
+                       return arguments();
+               }
+               if (property == TYPE_ARGUMENTS_PROPERTY) {
+                       return typeArguments();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return METHOD_INVOCATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               MethodInvocation result = new MethodInvocation(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setName((SimpleName) getName().clone(target));
+               result.setExpression(
+                       (Expression) ASTNode.copySubtree(target, getExpression()));
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+               }
+               result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getExpression());
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChildren(visitor, this.typeArguments);
+                       }
+                       acceptChild(visitor, getName());
+                       acceptChildren(visitor, this.arguments);
+               }
+               visitor.endVisit(this);
+       }
+
+       /**
+        * Returns the expression of this method invocation expression, or
+        * <code>null</code> if there is none.
+        *
+        * @return the expression node, or <code>null</code> if there is none
+        */
+       public Expression getExpression() {
+               return this.optionalExpression;
+       }
+
+       /**
+        * Returns <code>true</code> if the resolved return type has been inferred
+        * from the assignment context (JLS3 15.12.2.8), <code>false</code> otherwise.
+        * <p>
+        * This information is available only when bindings are requested when the AST is being built
+        * </p>.
+        *
+        * @return <code>true</code> if the resolved return type has been inferred
+        *      from the assignment context (JLS3 15.12.2.8), <code>false</code> otherwise
+        * @since 3.3
+        */
+       public boolean isResolvedTypeInferredFromExpectedType() {
+               return this.ast.getBindingResolver().isResolvedTypeInferredFromExpectedType(this);
+       }
+
+       /**
+        * Sets or clears the expression of this method invocation expression.
+        *
+        * @param expression the expression node, or <code>null</code> if
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */
+       public void setExpression(Expression expression) {
+               ASTNode oldChild = this.optionalExpression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.optionalExpression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of type arguments of this method
+        * invocation (added in JLS3 API).
+        *
+        * @return the live list of type arguments
+        *    (element type: <code>Type</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public List typeArguments() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.typeArguments == null) {
+                       unsupportedIn2();
+               }
+               return this.typeArguments;
+       }
+
+       /**
+        * Returns the name of the method invoked in this expression.
+        *
+        * @return the method name node
+        */
+       public SimpleName getName() {
+               if (this.methodName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.methodName == null) {
+                                       preLazyInit();
+                                       this.methodName = new SimpleName(this.ast);
+                                       postLazyInit(this.methodName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.methodName;
+       }
+
+       /**
+        * Sets the name of the method invoked in this expression to the
+        * given name.
+        *
+        * @param name the new method name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */
+       public void setName(SimpleName name) {
+               if (name == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.methodName;
+               preReplaceChild(oldChild, name, NAME_PROPERTY);
+               this.methodName = name;
+               postReplaceChild(oldChild, name, NAME_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of argument expressions in this method
+        * invocation expression.
+        *
+        * @return the live list of argument expressions
+        *    (element type: <code>Expression</code>)
+        */
+       public List arguments() {
+               return this.arguments;
+       }
+
+       /**
+        * Resolves and returns the binding for the method invoked by this
+        * expression.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        *
+        * @return the method binding, or <code>null</code> if the binding cannot
+        * be resolved
+        * @since 2.1
+        */
+       public IMethodBinding resolveMethodBinding() {
+               return this.ast.getBindingResolver().resolveMethod(this);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 4 * 4;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalExpression == null ? 0 : getExpression().treeSize())
+                       + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+                       + (this.methodName == null ? 0 : getName().treeSize())
+                       + (this.arguments == null ? 0 : this.arguments.listSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodRef.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodRef.java
new file mode 100644 (file)
index 0000000..69d3eb4
--- /dev/null
@@ -0,0 +1,317 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a method or constructor reference within a doc comment
+ * ({@link Javadoc}). The principal uses of these are in "@see" and "@link"
+ * tag elements, for references to method and constructor members.
+ * <pre>
+ * MethodRef:
+ *     [ Name ] <b>#</b> Identifier  
+ *         <b>(</b> [ MethodRefParameter | { <b>,</b> MethodRefParameter } ] <b>)</b>
+ * </pre>
+ * 
+ * @see Javadoc
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MethodRef extends ASTNode implements IDocElement {
+       
+       /**
+        * The "qualifier" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor QUALIFIER_PROPERTY = 
+               new ChildPropertyDescriptor(MethodRef.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(MethodRef.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "parameters" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor PARAMETERS_PROPERTY = 
+               new ChildListPropertyDescriptor(MethodRef.class, "parameters", MethodRefParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List properyList = new ArrayList(4);
+               createPropertyList(MethodRef.class, properyList);
+               addProperty(QUALIFIER_PROPERTY, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               addProperty(PARAMETERS_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 AST.JLS* constants
+        * @return a list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor})
+        * @since 3.0
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                       
+       /**
+        * The optional qualifier; <code>null</code> for none; defaults to none.
+        */
+       private Name optionalQualifier = null;
+
+       /**
+        * The method name; lazily initialized; defaults to a unspecified,
+        * legal Java method name.
+        */
+       private SimpleName methodName = null;
+       
+       /**
+        * The parameter declarations 
+        * (element type: <code>MethodRefParameter</code>).
+        * Defaults to an empty list.
+        */
+       private ASTNode.NodeList parameters =
+               new ASTNode.NodeList(PARAMETERS_PROPERTY);
+       
+       
+       /**
+        * Creates a new AST node for a method reference owned by the given 
+        * AST. By default, the method reference is for a method with an
+        * unspecified, but legal, name; no qualifier; and an empty parameter
+        * list.
+        * <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
+        */
+       MethodRef(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == QUALIFIER_PROPERTY) {
+                       if (get) {
+                               return getQualifier();
+                       } else {
+                               setQualifier((Name) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == PARAMETERS_PROPERTY) {
+                       return parameters();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return METHOD_REF;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               MethodRef result = new MethodRef(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+               result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+               result.parameters().addAll(
+                       ASTNode.copySubtrees(target, parameters()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getQualifier());
+                       acceptChild(visitor, getName());
+                       acceptChildren(visitor, this.parameters);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the qualifier of this method reference, or 
+        * <code>null</code> if there is none.
+        * 
+        * @return the qualifier name node, or <code>null</code> if there is none
+        */ 
+       public Name getQualifier() {
+               return this.optionalQualifier;
+       }
+       
+       /**
+        * Sets or clears the qualifier of this method reference.
+        * 
+        * @param name the qualifier name node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setQualifier(Name name) {
+               ASTNode oldChild = this.optionalQualifier;
+               preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+               this.optionalQualifier = name;
+               postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+       }
+
+       /**
+        * Returns the name of the referenced method or constructor.
+        * 
+        * @return the method or constructor name node
+        */ 
+       public SimpleName getName() {
+               if (this.methodName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.methodName == null) {
+                                       preLazyInit();
+                                       this.methodName = new SimpleName(this.ast);
+                                       postLazyInit(this.methodName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.methodName;
+       }
+       
+       /**
+        * Sets the name of the referenced method or constructor to the
+        * given name.
+        * 
+        * @param name the new method or constructor name node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the name is <code>null</code></li>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName name) {
+               if (name == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.methodName;
+               preReplaceChild(oldChild, name, NAME_PROPERTY);
+               this.methodName = name;
+               postReplaceChild(oldChild, name, NAME_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of method parameter references for this
+        * method reference.
+        * 
+        * @return the live list of method parameter references
+        *    (element type: <code>MethodRefParameter</code>)
+        */ 
+       public List parameters() {
+               return this.parameters;
+       }
+       
+       /**
+        * Resolves and returns the binding for the entity referred to by
+        * this method reference.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public final IBinding resolveBinding() {
+               return this.ast.getBindingResolver().resolveReference(this);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+                       + (this.methodName == null ? 0 : getName().treeSize())
+                       + this.parameters.listSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodRefParameter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/MethodRefParameter.java
new file mode 100644 (file)
index 0000000..b044a06
--- /dev/null
@@ -0,0 +1,358 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a parameter within a method reference ({@link MethodRef}).
+ * These nodes only occur within doc comments ({@link Javadoc}).
+ * For JLS2:
+ * <pre>
+ * MethodRefParameter:
+ *             Type [ Identifier ]
+ * </pre>
+ * For JLS3, the variable arity indicator was added:
+ * <pre>
+ * MethodRefParameter:
+ *             Type [ <b>...</b> ] [ Identifier ]
+ * </pre>
+ * <p>
+ * Note: The 1.5 spec for the Javadoc tool does not mention the possibility
+ * of a variable arity indicator in method references. However, the 1.5
+ * Javadoc tool itself does indeed support it. Since it makes sense to have
+ * a way to explicitly refer to variable arity methods, it seems more likely
+ * that the Javadoc spec is wrong in this case.
+ * </p>
+ * 
+ * @see Javadoc
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class MethodRefParameter extends ASTNode {
+       
+       /**
+        * The "type" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(MethodRefParameter.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "varargs" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final SimplePropertyDescriptor VARARGS_PROPERTY = 
+               new SimplePropertyDescriptor(MethodRefParameter.class, "varargs", boolean.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(MethodRefParameter.class, "name", SimpleName.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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+               
+       static {
+               List properyList = new ArrayList(3);
+               createPropertyList(MethodRefParameter.class, properyList);
+               addProperty(TYPE_PROPERTY, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
+               
+               properyList = new ArrayList(3);
+               createPropertyList(MethodRefParameter.class, properyList);
+               addProperty(TYPE_PROPERTY, properyList);
+               addProperty(VARARGS_PROPERTY, properyList);
+               addProperty(NAME_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS_3_0 = 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 AST.JLS* constants
+        * @return a list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor})
+        * @since 3.0
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The type; lazily initialized; defaults to a unspecified,
+        * legal type.
+        */
+       private Type type = null;
+
+       /**
+        * Indicates the last parameter of a variable arity method;
+        * defaults to false.
+        * 
+        * @since 3.1
+        */
+       private boolean variableArity = false;
+
+       /**
+        * The parameter name, or <code>null</code> if none; none by
+        * default.
+        */
+       private SimpleName optionalParameterName = null;
+
+       /**
+        * Creates a new AST node for a method referenece parameter owned by the given 
+        * AST. By default, the node has an unspecified (but legal) type, 
+        * not variable arity, and no parameter name.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       MethodRefParameter(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == TYPE_PROPERTY) {
+                       if (get) {
+                               return getType();
+                       } else {
+                               setType((Type) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) 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.
+        */
+       final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+               if (property == VARARGS_PROPERTY) {
+                       if (get) {
+                               return isVarargs();
+                       } else {
+                               setVarargs(value);
+                               return false;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetBooleanProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return METHOD_REF_PARAMETER;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               MethodRefParameter result = new MethodRefParameter(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setType((Type) ASTNode.copySubtree(target, getType()));
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.setVarargs(isVarargs());
+               }
+               result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getType());
+                       acceptChild(visitor, getName());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the paramter type.
+        * 
+        * @return the parameter type
+        */ 
+       public Type getType() {
+               if (this.type == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.type == null) {
+                                       preLazyInit();
+                                       this.type = this.ast.newPrimitiveType(PrimitiveType.INT);
+                                       postLazyInit(this.type, TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.type;
+       }
+
+       /**
+        * Sets the paramter type to the given type.
+        * 
+        * @param type the new type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the type is <code>null</code></li>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setType(Type type) {
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.type;
+               preReplaceChild(oldChild, type, TYPE_PROPERTY);
+               this.type = type;
+               postReplaceChild(oldChild, type, TYPE_PROPERTY);
+       }
+
+       /**
+        * Returns whether this method reference parameter is for
+        * the last parameter of a variable arity method (added in JLS3 API).
+        * <p>
+        * Note that the binding for the type <code>Foo</code>in the vararg method
+        * reference <code>#fun(Foo...)</code> is always for the type as 
+        * written; i.e., the type binding for <code>Foo</code>. However, if you
+        * navigate from the MethodRef to its method binding to the
+        * type binding for its last parameter, the type binding for the vararg
+        * parameter is always an array type (i.e., <code>Foo[]</code>) reflecting
+        * the way vararg methods get compiled.
+        * </p>
+        * 
+        * @return <code>true</code> if this is a variable arity parameter,
+        *    and <code>false</code> otherwise
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public boolean isVarargs() {
+               unsupportedIn2();
+               return this.variableArity;
+       }
+
+       /**
+        * Sets whether this method reference parameter is for the last parameter of
+        * a variable arity method (added in JLS3 API).
+        * 
+        * @param variableArity <code>true</code> if this is a variable arity
+        *    parameter, and <code>false</code> otherwise
+        * @since 3.1
+        */ 
+       public void setVarargs(boolean variableArity) {
+               unsupportedIn2();
+               preValueChange(VARARGS_PROPERTY);
+               this.variableArity = variableArity;
+               postValueChange(VARARGS_PROPERTY);
+       }
+
+       /**
+        * Returns the parameter name, or <code>null</code> if there is none.
+        * 
+        * @return the parameter name node, or <code>null</code> if there is none
+        */ 
+       public SimpleName getName() {
+               return this.optionalParameterName;
+       }
+       
+       /**
+        * Sets or clears the parameter name.
+        * 
+        * @param name the parameter name node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName name) {
+               ASTNode oldChild = this.optionalParameterName;
+               preReplaceChild(oldChild, name, NAME_PROPERTY);
+               this.optionalParameterName = name;
+               postReplaceChild(oldChild, name, NAME_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 2 * 5;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.type == null ? 0 : getType().treeSize())
+                       + (this.optionalParameterName == null ? 0 : getName().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Modifier.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Modifier.java
new file mode 100644 (file)
index 0000000..c6f9e2b
--- /dev/null
@@ -0,0 +1,707 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Modifier node.
+ * <pre>
+ * Modifier:
+ *    <b>public</b>
+ *    <b>protected</b>
+ *    <b>private</b>
+ *    <b>static</b>
+ *    <b>abstract</b>
+ *    <b>final</b>
+ *    <b>native</b>
+ *    <b>synchronized</b>
+ *    <b>transient</b>
+ *    <b>volatile</b>
+ *    <b>strictfp</b>
+ * </pre>
+ * <p>
+ * The numeric values of these flags match the ones for class
+ * files as described in the Java Virtual Machine Specification.
+ * Note that Java model class {@link org.eclipse.jdt.core.Flags} also
+ * provides the same constants as this class.
+ * </p>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class Modifier extends ASTNode implements IExtendedModifier {
+
+       /**
+        * Modifier keywords (typesafe enumeration).
+        * @since 3.0
+        */
+       public static class ModifierKeyword {
+       
+               /** "abstract" modifier with flag value {@link Modifier#ABSTRACT}. */
+               public static final ModifierKeyword ABSTRACT_KEYWORD = new ModifierKeyword("abstract", ABSTRACT);//$NON-NLS-1$
+               
+               /** "final" modifier with flag value {@link Modifier#FINAL}. */
+               public static final ModifierKeyword FINAL_KEYWORD = new ModifierKeyword("final", FINAL);//$NON-NLS-1$
+               
+               /**
+                * Map from token to operator (key type: <code>String</code>;
+                * value type: <code>Operator</code>).
+                */
+               private static final Map KEYWORDS;
+               
+               /** "native" modifier with flag value {@link Modifier#NATIVE}. */
+               public static final ModifierKeyword NATIVE_KEYWORD = new ModifierKeyword("native", NATIVE);//$NON-NLS-1$
+               
+               /** "private" modifier with flag value {@link Modifier#PRIVATE}. */
+               public static final ModifierKeyword PRIVATE_KEYWORD = new ModifierKeyword("private", PRIVATE);//$NON-NLS-1$
+               
+               /** "protected" modifier with flag value {@link Modifier#PROTECTED}. */
+               public static final ModifierKeyword PROTECTED_KEYWORD = new ModifierKeyword("protected", PROTECTED);//$NON-NLS-1$
+               
+               /** "public" modifier with flag value {@link Modifier#PUBLIC}. */
+               public static final ModifierKeyword PUBLIC_KEYWORD = new ModifierKeyword("public", PUBLIC);//$NON-NLS-1$
+               
+               /** "static" modifier with flag value {@link Modifier#STATIC}. */
+               public static final ModifierKeyword STATIC_KEYWORD = new ModifierKeyword("static", STATIC);//$NON-NLS-1$
+               
+               /** "strictfp" modifier with flag value {@link Modifier#STRICTFP}. */
+               public static final ModifierKeyword STRICTFP_KEYWORD = new ModifierKeyword("strictfp", STRICTFP);//$NON-NLS-1$
+               
+               /** "synchronized" modifier with flag value {@link Modifier#SYNCHRONIZED}. */
+               public static final ModifierKeyword SYNCHRONIZED_KEYWORD = new ModifierKeyword("synchronized", SYNCHRONIZED);//$NON-NLS-1$
+               
+               /** "transient" modifier with flag value {@link Modifier#TRANSIENT}. */
+               public static final ModifierKeyword TRANSIENT_KEYWORD = new ModifierKeyword("transient", TRANSIENT);//$NON-NLS-1$
+               
+               /** "volatile" modifier with flag value {@link Modifier#VOLATILE}. */
+               public static final ModifierKeyword VOLATILE_KEYWORD = new ModifierKeyword("volatile", VOLATILE);//$NON-NLS-1$
+               static {
+                       KEYWORDS = new HashMap(20);
+                       ModifierKeyword[] ops = {
+                                       PUBLIC_KEYWORD,
+                                       PROTECTED_KEYWORD,
+                                       PRIVATE_KEYWORD,
+                                       STATIC_KEYWORD,
+                                       ABSTRACT_KEYWORD,
+                                       FINAL_KEYWORD,
+                                       NATIVE_KEYWORD,
+                                       SYNCHRONIZED_KEYWORD,
+                                       TRANSIENT_KEYWORD,
+                                       VOLATILE_KEYWORD,
+                                       STRICTFP_KEYWORD
+                               };
+                       for (int i = 0; i < ops.length; i++) {
+                               KEYWORDS.put(ops[i].toString(), ops[i]);
+                       }
+               }
+
+               /**
+                * Returns the modifier corresponding to the given single-bit flag value,
+                * or <code>null</code> if none or if more than one bit is set.
+                * <p>
+                * <code>fromFlagValue</code> is the converse of <code>toFlagValue</code>:
+                * that is, <code>ModifierKind.fromFlagValue(k.toFlagValue()) == k</code> for 
+                * all modifier keywords <code>k</code>.
+                * </p>
+                * 
+                * @param flagValue the single-bit flag value for the modifier
+                * @return the modifier keyword, or <code>null</code> if none
+                * @see #toFlagValue()
+                */
+               public static ModifierKeyword fromFlagValue(int flagValue) {
+                       for (Iterator it = KEYWORDS.values().iterator(); it.hasNext(); ) {
+                               ModifierKeyword k = (ModifierKeyword) it.next();
+                               if (k.toFlagValue() == flagValue) {
+                                       return k;
+                               }
+                       }
+                       return null;
+               }
+               
+               /**
+                * Returns the modifier corresponding to the given string,
+                * or <code>null</code> if none.
+                * <p>
+                * <code>toKeyword</code> is the converse of <code>toString</code>:
+                * that is, <code>ModifierKind.toKeyword(k.toString()) == k</code> for 
+                * all modifier keywords <code>k</code>.
+                * </p>
+                * 
+                * @param keyword the lowercase string name for the modifier
+                * @return the modifier keyword, or <code>null</code> if none
+                * @see #toString()
+                */
+               public static ModifierKeyword toKeyword(String keyword) {
+                       return (ModifierKeyword) KEYWORDS.get(keyword);
+               }
+               
+               /**
+                * The flag value for the modifier.
+                */
+               private int flagValue;
+               
+               /**
+                * The keyword modifier string.
+                */
+               private String keyword;
+               
+               /**
+                * Creates a new modifier with the given keyword.
+                * <p>
+                * Note: this constructor is private. The only instances
+                * ever created are the ones for the standard modifiers.
+                * </p>
+                * 
+                * @param keyword the character sequence for the modifier
+                * @param flagValue flag value as described in the Java Virtual Machine Specification
+                */
+               private ModifierKeyword(String keyword, int flagValue) {
+                       this.keyword = keyword;
+                       this.flagValue = flagValue;
+               }
+               
+               /**
+                * Returns the modifier flag value corresponding to this modifier keyword.
+                * These flag values are as described in the Java Virtual Machine Specification.
+                * 
+                * @return one of the <code>Modifier</code> constants
+                * @see #fromFlagValue(int)
+                */ 
+               public int toFlagValue() {
+                       return this.flagValue;
+               }
+
+               /**
+                * Returns the keyword for the modifier.
+                * 
+                * @return the keyword for the modifier
+                * @see #toKeyword(String)
+                */
+               public String toString() {
+                       return this.keyword;
+               }
+       }
+
+       /**
+        * "abstract" modifier constant (bit mask).
+        * Applicable to types and methods.
+        * @since 2.0
+        */
+       public static final int ABSTRACT = 0x0400;
+
+       /**
+        * "final" modifier constant (bit mask).
+        * Applicable to types, methods, fields, and variables.
+        * @since 2.0
+        */
+       public static final int FINAL = 0x0010;
+
+       /**
+        * The "keyword" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor KEYWORD_PROPERTY = 
+               new SimplePropertyDescriptor(Modifier.class, "keyword", Modifier.ModifierKeyword.class, MANDATORY); //$NON-NLS-1$
+
+       /**
+        * "native" modifier constant (bit mask).
+        * Applicable only to methods.
+        * @since 2.0
+        */
+       public static final int NATIVE = 0x0100;
+
+       /**
+        * Modifier constant (bit mask, value 0) indicating no modifiers.
+        * @since 2.0
+        */
+       public static final int NONE = 0x0000;
+
+       /**
+        * "private" modifier constant (bit mask).
+        * Applicable to types, methods, constructors, and fields.
+        * @since 2.0
+        */
+       public static final int PRIVATE = 0x0002;
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+
+       /**
+        * "protected" modifier constant (bit mask).
+        * Applicable to types, methods, constructors, and fields.
+        * @since 2.0
+        */
+       public static final int PROTECTED = 0x0004;
+
+       /**
+        * "public" modifier constant (bit mask).
+        * Applicable to types, methods, constructors, and fields.
+        * @since 2.0
+        */
+       public static final int PUBLIC = 0x0001;
+
+       /**
+        * "static" modifier constant (bit mask).
+        * Applicable to types, methods, fields, and initializers.
+        * @since 2.0
+        */
+       public static final int STATIC = 0x0008;
+
+       /**
+        * "strictfp" modifier constant (bit mask).
+        * Applicable to types and methods.
+        * @since 2.0
+        */
+       public static final int STRICTFP = 0x0800;
+
+       /**
+        * "synchronized" modifier constant (bit mask).
+        * Applicable only to methods.
+        * @since 2.0
+        */
+       public static final int SYNCHRONIZED = 0x0020;
+
+       /**
+        * "transient" modifier constant (bit mask).
+        * Applicable only to fields.
+        * @since 2.0
+        */
+       public static final int TRANSIENT = 0x0080;
+
+       /**
+        * "volatile" modifier constant (bit mask).
+        * Applicable only to fields.
+        * @since 2.0
+        */
+       public static final int VOLATILE = 0x0040;
+
+       static {
+               List properyList = new ArrayList(2);
+               createPropertyList(Modifier.class, properyList);
+               addProperty(KEYWORD_PROPERTY, properyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
+       }
+
+       /**
+        * Returns whether the given flags includes the "abstract" modifier.
+        * Applicable to types and methods.
+        * 
+        * @param flags the modifier flags
+        * @return <code>true</code> if the <code>ABSTRACT</code> bit is
+        *   set, and <code>false</code> otherwise
+        * @since 2.0
+        */
+       public static boolean isAbstract(int flags) {
+               return (flags & ABSTRACT) != 0;
+       }
+
+       /**
+        * Returns whether the given flags includes the "final" modifier.
+        * Applicable to types, methods, fields, and variables.
+        * 
+        * @param flags the modifier flags
+        * @return <code>true</code> if the <code>FINAL</code> bit is
+        *   set, and <code>false</code> otherwise
+        * @since 2.0
+        */
+       public static boolean isFinal(int flags) {
+               return (flags & FINAL) != 0;
+       }
+
+       /**
+        * Returns whether the given flags includes the "native" modifier.
+        * Applicable only to methods.
+        * 
+        * @param flags the modifier flags
+        * @return <code>true</code> if the <code>NATIVE</code> bit is
+        *   set, and <code>false</code> otherwise
+        * @since 2.0
+        */
+       public static boolean isNative(int flags) {
+               return (flags & NATIVE) != 0;
+       }
+
+       /**
+        * Returns whether the given flags includes the "private" modifier.
+        * Applicable to types, methods, constructors, and fields.
+        * 
+        * @param flags the modifier flags
+        * @return <code>true</code> if the <code>PRIVATE</code> bit is
+        *   set, and <code>false</code> otherwise
+        * @since 2.0
+        */
+       public static boolean isPrivate(int flags) {
+               return (flags & PRIVATE) != 0;
+       }
+
+       /**
+        * Returns whether the given flags includes the "protected" modifier.
+        * Applicable to types, methods, constructors, and fields.
+        * 
+        * @param flags the modifier flags
+        * @return <code>true</code> if the <code>PROTECTED</code> bit is
+        *   set, and <code>false</code> otherwise
+        * @since 2.0
+        */
+       public static boolean isProtected(int flags) {
+               return (flags & PROTECTED) != 0;
+       }
+
+       /**
+        * Returns whether the given flags includes the "public" modifier.
+        * Applicable to types, methods, constructors, and fields.
+        * 
+        * @param flags the modifier flags
+        * @return <code>true</code> if the <code>PUBLIC</code> bit is
+        *   set, and <code>false</code> otherwise
+        * @since 2.0
+        */
+       public static boolean isPublic(int flags) {
+               return (flags & PUBLIC) != 0;
+       }
+
+       /**
+        * Returns whether the given flags includes the "static" modifier.
+        * Applicable to types, methods, fields, and initializers.
+        * 
+        * @param flags the modifier flags
+        * @return <code>true</code> if the <code>STATIC</code> bit is
+        *   set, and <code>false</code> otherwise
+        * @since 2.0
+        */
+       public static boolean isStatic(int flags) {
+               return (flags & STATIC) != 0;
+       }
+       
+       /**
+        * Returns whether the given flags includes the "strictfp" modifier.
+        * Applicable to types and methods.
+        * 
+        * @param flags the modifier flags
+        * @return <code>true</code> if the <code>STRICTFP</code> bit is
+        *   set, and <code>false</code> otherwise
+        * @since 2.0
+        */
+       public static boolean isStrictfp(int flags) {
+               return (flags & STRICTFP) != 0;
+       }
+       
+       /**
+        * Returns whether the given flags includes the "synchronized" modifier.
+        * Applicable only to methods.
+        * 
+        * @param flags the modifier flags
+        * @return <code>true</code> if the <code>SYNCHRONIZED</code> bit is
+        *   set, and <code>false</code> otherwise
+        * @since 2.0
+        */
+       public static boolean isSynchronized(int flags) {
+               return (flags & SYNCHRONIZED) != 0;
+       }
+       
+       /**
+        * Returns whether the given flags includes the "transient" modifier.
+        * Applicable only to fields.
+        * 
+        * @param flags the modifier flags
+        * @return <code>true</code> if the <code>TRANSIENT</code> bit is
+        *   set, and <code>false</code> otherwise
+        * @since 2.0
+        */
+       public static boolean isTransient(int flags) {
+               return (flags & TRANSIENT) != 0;
+       }
+       
+       /**
+        * Returns whether the given flags includes the "volatile" modifier.
+        * Applicable only to fields.
+        * 
+        * @param flags the modifier flags
+        * @return <code>true</code> if the <code>VOLATILE</code> bit is
+        *   set, and <code>false</code> otherwise
+        * @since 2.0
+        */
+       public static boolean isVolatile(int flags) {
+               return (flags & VOLATILE) != 0;
+       }
+
+       /**
+        * 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 modifier keyword; defaults to an unspecified modifier.
+        * @since 3.0
+        */
+       private ModifierKeyword modifierKeyword = ModifierKeyword.PUBLIC_KEYWORD;
+
+       /**
+        * Creates a new unparented modifier node owned by the given AST.
+        * By default, the node has unspecified (but legal) modifier.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        * @since 3.0
+        */
+       Modifier(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       ASTNode clone0(AST target) {
+               Modifier result = new Modifier(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setKeyword(getKeyword());
+               return result;
+       }
+
+       /**
+        * Returns the modifier keyword of this modifier node.
+        * 
+        * @return the modifier keyword
+        * @since 3.0
+        */ 
+       public ModifierKeyword getKeyword() {
+               return this.modifierKeyword;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       final int getNodeType0() {
+               return MODIFIER;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == KEYWORD_PROPERTY) {
+                       if (get) {
+                               return getKeyword();
+                       } else {
+                               setKeyword((ModifierKeyword) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+
+       /**
+        * Answer true if the receiver is the abstract modifier, false otherwise.
+        * 
+        * @return true if the receiver is the abstract modifier, false otherwise
+        * @since 3.2
+        */
+       public boolean isAbstract() {
+               return this.modifierKeyword == ModifierKeyword.ABSTRACT_KEYWORD;
+       }
+
+       /**
+        * @see IExtendedModifier#isAnnotation()
+        */ 
+       public boolean isAnnotation() {
+               return false;
+       }
+       
+       /**
+        * Answer true if the receiver is the final modifier, false otherwise.
+        * 
+        * @return true if the receiver is the final modifier, false otherwise
+        * @since 3.2
+        */
+       public boolean isFinal() {
+               return this.modifierKeyword == ModifierKeyword.FINAL_KEYWORD;
+       }
+
+       /**
+        * @see IExtendedModifier#isModifier()
+        */ 
+       public boolean isModifier() {
+               return true;
+       }
+
+       /**
+        * Answer true if the receiver is the native modifier, false otherwise.
+        * 
+        * @return true if the receiver is the native modifier, false otherwise
+        * @since 3.2
+        */
+       public boolean isNative() {
+               return this.modifierKeyword == ModifierKeyword.NATIVE_KEYWORD;
+       }
+       
+       /**
+        * Answer true if the receiver is the private modifier, false otherwise.
+        * 
+        * @return true if the receiver is the private modifier, false otherwise
+        * @since 3.2
+        */
+       public boolean isPrivate() {
+               return this.modifierKeyword == ModifierKeyword.PRIVATE_KEYWORD;
+       }
+       
+       /**
+        * Answer true if the receiver is the protected modifier, false otherwise.
+        * 
+        * @return true if the receiver is the protected modifier, false otherwise
+        * @since 3.2
+        */
+       public boolean isProtected() {
+               return this.modifierKeyword == ModifierKeyword.PROTECTED_KEYWORD;
+       }
+       
+       /**
+        * Answer true if the receiver is the public modifier, false otherwise.
+        * 
+        * @return true if the receiver is the public modifier, false otherwise
+        * @since 3.2
+        */
+       public boolean isPublic() {
+               return this.modifierKeyword == ModifierKeyword.PUBLIC_KEYWORD;
+       }
+       
+       /**
+        * Answer true if the receiver is the static modifier, false otherwise.
+        * 
+        * @return true if the receiver is the static modifier, false otherwise
+        * @since 3.2
+        */
+       public boolean isStatic() {
+               return this.modifierKeyword == ModifierKeyword.STATIC_KEYWORD;
+       }
+       
+       /**
+        * Answer true if the receiver is the strictfp modifier, false otherwise.
+        * 
+        * @return true if the receiver is the strictfp modifier, false otherwise
+        * @since 3.2
+        */
+       public boolean isStrictfp() {
+               return this.modifierKeyword == ModifierKeyword.STRICTFP_KEYWORD;
+       }
+       
+       /**
+        * Answer true if the receiver is the synchronized modifier, false otherwise.
+        * 
+        * @return true if the receiver is the synchronized modifier, false otherwise
+        * @since 3.2
+        */
+       public boolean isSynchronized() {
+               return this.modifierKeyword == ModifierKeyword.SYNCHRONIZED_KEYWORD;
+       }
+       
+       /**
+        * Answer true if the receiver is the transient modifier, false otherwise.
+        * 
+        * @return true if the receiver is the transient modifier, false otherwise
+        * @since 3.2
+        */
+       public boolean isTransient() {
+               return this.modifierKeyword == ModifierKeyword.TRANSIENT_KEYWORD;
+       }
+       
+       /**
+        * Answer true if the receiver is the volatile modifier, false otherwise.
+        * 
+        * @return true if the receiver is the volatile modifier, false otherwise
+        * @since 3.2
+        */
+       public boolean isVolatile() {
+               return this.modifierKeyword == ModifierKeyword.VOLATILE_KEYWORD;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       int memSize() {
+               // treat ModifierKeyword as free
+               return BASE_NODE_SIZE + 1 * 4;
+       }
+       
+       /**
+        * Sets the modifier keyword of this modifier node.
+        * 
+        * @param modifierKeyord the modifier keyword 
+        * @exception IllegalArgumentException if the argument is <code>null</code>
+        * @since 3.0
+        */ 
+       public void setKeyword(ModifierKeyword modifierKeyord) {
+               if (modifierKeyord == null) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(KEYWORD_PROPERTY);
+               this.modifierKeyword = modifierKeyord;
+               postValueChange(KEYWORD_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       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.
+        * @since 3.0
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Name.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Name.java
new file mode 100644 (file)
index 0000000..e619cb6
--- /dev/null
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Abstract base class for all AST nodes that represent names.
+ * There are exactly two kinds of name: simple ones 
+ * (<code>SimpleName</code>) and qualified ones (<code>QualifiedName</code>).
+ * <p>
+ * <pre>
+ * Name:
+ *     SimpleName
+ *     QualifiedName
+ * </pre>
+ * </p>
+ * 
+ * @since 2.0
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public abstract class Name extends Expression implements IDocElement {
+       
+       /**
+        * Approximate base size of an expression node instance in bytes, 
+        * including object header and instance fields.
+        */
+       static final int BASE_NAME_NODE_SIZE = BASE_NODE_SIZE + 1 * 4;
+       
+       /**
+        * This index represents the position inside a qualified name.
+        */
+       int index;
+       
+       /**
+        * Creates a new AST node for a name owned by the given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       Name(AST ast) {
+               super(ast);
+       }
+       
+       /**
+        * Returns whether this name is a simple name
+        * (<code>SimpleName</code>).
+        * 
+        * @return <code>true</code> if this is a simple name, and 
+        *    <code>false</code> otherwise
+        */
+       public final boolean isSimpleName() {
+               return (this instanceof SimpleName);
+       }
+               
+       /**
+        * Returns whether this name is a qualified name
+        * (<code>QualifiedName</code>).
+        * 
+        * @return <code>true</code> if this is a qualified name, and 
+        *    <code>false</code> otherwise
+        */
+       public final boolean isQualifiedName() {
+               return (this instanceof QualifiedName);
+       }
+
+       /**
+        * Resolves and returns the binding for the entity referred to by this name.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public final IBinding resolveBinding() {
+               return this.ast.getBindingResolver().resolveName(this);
+       }
+       
+       /**
+        * Returns the standard dot-separated representation of this name.
+        * If the name is a simple name, the result is the name's identifier.
+        * If the name is a qualified name, the result is the name of the qualifier
+        * (as computed by this method) followed by "." followed by the name's
+        * identifier.
+        * 
+        * @return the fully qualified name
+        * @since 3.0
+        */
+       public final String getFullyQualifiedName() {
+               if (isSimpleName()) {
+                       // avoid creating garbage for common case
+                       return ((SimpleName) this).getIdentifier();
+               } else {
+                       StringBuffer buffer = new StringBuffer(50);
+                       appendName(buffer);
+                       return new String(buffer);
+               }
+       }
+
+       /**
+        * Appends the standard representation of this name to the given string
+        * buffer.
+        * 
+        * @param buffer the buffer
+        * @since 3.0
+        */
+       abstract void appendName(StringBuffer buffer);  
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NodeEventHandler.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NodeEventHandler.java
new file mode 100644 (file)
index 0000000..90a763b
--- /dev/null
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * A node event handler is an internal mechanism for receiving
+ * notification of changes to nodes in an AST.
+ * <p>
+ * The default implementation serves as the default event handler
+ * that does nothing. Internal subclasses do all the real work.
+ * </p>
+ * 
+ * @see AST#getEventHandler()
+ */
+class NodeEventHandler {
+
+       /**
+        * Creates a node event handler.
+        */
+       NodeEventHandler() {
+               // default implementation: do nothing
+       }
+       
+       /**
+        * Reports that the given node is about to lose a child.
+        * The first half of an event pair. The default implementation does nothing.
+        * 
+        * @param node the node about to be modified
+        * @param child the node about to be removed
+        * @param property the child or child list property descriptor
+        * @see #postRemoveChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+        * @since 3.0
+        */
+       void preRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+               // do nothing
+               // System.out.println("DEL1 " + property);
+       }
+       
+       /**
+        * Reports that the given node has just lose a child.
+        * The second half of an event pair. The default implementation does nothing.
+        * 
+        * @param node the node that was modified
+        * @param child the child that was removed; note that this node is unparented
+        * @param property the child or child list property descriptor
+        * @see #preRemoveChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+        * @since 3.0
+        */
+       void postRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+               // do nothing
+               // System.out.println("DEL2 " + property);
+       }
+       
+       /**
+        * Reports that the given node is about to have a child replaced.
+        * The first half of an event pair.
+        * The default implementation does nothing.
+        * 
+        * @param node the node about to be modified
+        * @param child the node about to be replaced
+        * @param newChild the replacement child; note that this node is unparented
+        * @param property the child or child list property descriptor
+        * @see #preReplaceChildEvent(ASTNode, ASTNode, ASTNode, StructuralPropertyDescriptor)
+        * @since 3.0
+        */
+       void preReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+               // do nothing
+               // System.out.println("REP1 " + property);
+       }
+       
+       /**
+        * Reports that the given node has had its child replaced. The second half
+        * of an event pair. The default implementation does nothing.
+        * 
+        * @param node the node that was modified
+        * @param child the node that was replaced; note that this node is unparented
+        * @param newChild the replacement child
+        * @param property the child or child list property descriptor
+        * @see #postReplaceChildEvent(ASTNode, ASTNode, ASTNode, StructuralPropertyDescriptor)
+        * @since 3.0
+        */
+       void postReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
+               // do nothing
+               // System.out.println("REP2 " + property);
+       }
+       
+       /**
+        * Reports that the given node is about to gain a child.
+        * The first half of an event pair. The default implementation does nothing.
+        * 
+        * @param node the node that to be modified
+        * @param child the node that is to be added as a child; note that this
+        * node is unparented; in the case of a child list property, the exact
+        * location of insertion is not supplied (but is known on the
+        * corresponding <code>postAddChildEvent</code> to
+        * follow)
+        * @param property the child or child list property descriptor
+        * @see #postAddChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+        * @since 3.0
+        */
+       void preAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+               // do nothing
+               // System.out.println("ADD1 " + property);
+       }
+       
+       /**
+        * Reports that the given node has just gained a child.
+        * The second half of an event pair. The default implementation does nothing.
+        * 
+        * @param node the node that was modified
+        * @param child the node that was added as a child
+        * @param property the child or child list property descriptor
+        * @see #preAddChildEvent(ASTNode, ASTNode, StructuralPropertyDescriptor)
+        * @since 3.0
+        */
+       void postAddChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
+               // do nothing
+               // System.out.println("ADD2 " + property);
+       }
+       
+       /**
+        * Reports that the given node is about to change the value of a
+        * non-child property. The first half of an event pair.
+        * The default implementation does nothing.
+        * 
+        * @param node the node to be modified
+        * @param property the property descriptor
+        * @see #postValueChangeEvent(ASTNode, SimplePropertyDescriptor)
+        * @since 3.0
+        */
+       void preValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+               // do nothing
+               // System.out.println("MOD1 " + property);
+       }
+
+       /**
+        * Reports that the given node has just changed the value of a
+        * non-child property. The second half of an event pair.
+        * The default implementation does nothing.
+        * 
+        * @param node the node that was modified
+        * @param property the property descriptor
+        * @see #preValueChangeEvent(ASTNode, SimplePropertyDescriptor)
+        * @since 3.0
+        */
+       void postValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
+               // do nothing
+               // System.out.println("MOD2 " + property);
+       }
+       
+       /**
+        * Reports that the given node is about to be cloned. 
+        * The first half of an event pair.
+        * The default implementation does nothing.
+        * 
+        * @param node the node to be modified
+        * @see #postCloneNodeEvent(ASTNode, ASTNode)
+        * @since 3.0
+        */
+       void preCloneNodeEvent(ASTNode node) {
+               // do nothing
+               // System.out.println("CLONE1");
+       }
+
+       /**
+        * Reports that the given node has just been cloned.
+        * The second half of an event pair.
+        * The default implementation does nothing.
+        * 
+        * @param node the node that was modified
+        * @param clone the clone of <code>node</code>
+        * @see #preCloneNodeEvent(ASTNode)
+        * @since 3.0
+        */
+       void postCloneNodeEvent(ASTNode node, ASTNode clone) {
+               // do nothing
+               // System.out.println("CLONE2");
+       }
+       
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NodeSearcher.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NodeSearcher.java
new file mode 100644 (file)
index 0000000..95b69fd
--- /dev/null
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
+import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.CompilationUnitScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
+
+class NodeSearcher extends ASTVisitor {
+       public net.sourceforge.phpdt.internal.compiler.ast.ASTNode found;
+       public TypeDeclaration enclosingType;
+       public int position;
+       
+       NodeSearcher(int position) {
+               this.position = position;
+       }
+
+       public boolean visit(
+               ConstructorDeclaration constructorDeclaration,
+               ClassScope scope) {
+
+               if (constructorDeclaration.declarationSourceStart <= position
+                       && position <= constructorDeclaration.declarationSourceEnd) {
+                               found = constructorDeclaration;
+                               return false;
+               }
+               return true;
+       }
+
+       public boolean visit(
+               FieldDeclaration fieldDeclaration,
+               MethodScope scope) {
+                       if (fieldDeclaration.declarationSourceStart <= position
+                               && position <= fieldDeclaration.declarationSourceEnd) {
+                                       found = fieldDeclaration;
+                                       return false;
+                       }
+                       return true;
+       }
+
+       public boolean visit(Initializer initializer, MethodScope scope) {
+               if (initializer.declarationSourceStart <= position
+                       && position <= initializer.declarationSourceEnd) {
+                               found = initializer;
+                               return false;
+               }
+               return true;
+       }
+
+       public boolean visit(
+               TypeDeclaration memberTypeDeclaration,
+               ClassScope scope) {
+                       if (memberTypeDeclaration.declarationSourceStart <= position
+                               && position <= memberTypeDeclaration.declarationSourceEnd) {
+                                       enclosingType = memberTypeDeclaration;
+                                       return true;
+
+                       }
+                       return false;           
+       }
+
+       public boolean visit(
+               MethodDeclaration methodDeclaration,
+               ClassScope scope) {
+
+               if (methodDeclaration.declarationSourceStart <= position
+                       && position <= methodDeclaration.declarationSourceEnd) {
+                               found = methodDeclaration;
+                               return false;
+               }
+               return true;
+       }
+
+       public boolean visit(
+               TypeDeclaration typeDeclaration,
+               CompilationUnitScope scope) {
+                       if (typeDeclaration.declarationSourceStart <= position
+                               && position <= typeDeclaration.declarationSourceEnd) {
+                                       enclosingType = typeDeclaration;
+                                       return true;
+                       }
+                       return false;           
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NormalAnnotation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NormalAnnotation.java
new file mode 100644 (file)
index 0000000..2a1fd75
--- /dev/null
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Normal annotation node (added in JLS3 API).
+ * <p>
+ * <pre>
+ * NormalAnnotation:
+ *   <b>@</b> TypeName <b>(</b> [ MemberValuePair { <b>,</b> MemberValuePair } ] <b>)</b>
+ * </pre>
+ * </p>
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class NormalAnnotation extends Annotation {
+       
+       /**
+        * The "typeName" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor TYPE_NAME_PROPERTY = 
+               internalTypeNamePropertyFactory(NormalAnnotation.class);
+
+       /**
+        * The "values" structural property of this node type.
+        */
+       public static final ChildListPropertyDescriptor VALUES_PROPERTY = 
+               new ChildListPropertyDescriptor(NormalAnnotation.class, "values", MemberValuePair.class, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(NormalAnnotation.class, propertyList);
+               addProperty(TYPE_NAME_PROPERTY, propertyList);
+               addProperty(VALUES_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+       
+       /**
+        * 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 AST.JLS* constants
+        * @return a list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+       
+       /**
+        * The list of member value pairs (element type: 
+        * <code MemberValuePair</code>). Defaults to an empty list.
+        */
+       private ASTNode.NodeList values = 
+               new ASTNode.NodeList(VALUES_PROPERTY);
+
+       /**
+        * Creates a new unparented normal annotation node owned 
+        * by the given AST.  By default, the annotation has an
+        * unspecified type name and an empty list of member value
+        * pairs.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       NormalAnnotation(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == TYPE_NAME_PROPERTY) {
+                       if (get) {
+                               return getTypeName();
+                       } else {
+                               setTypeName((Name) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == VALUES_PROPERTY) {
+                       return values();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildPropertyDescriptor internalTypeNameProperty() {
+               return TYPE_NAME_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return NORMAL_ANNOTATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               NormalAnnotation result = new NormalAnnotation(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setTypeName((Name) ASTNode.copySubtree(target, getTypeName()));
+               result.values().addAll(ASTNode.copySubtrees(target, values()));
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getTypeName());
+                       acceptChildren(visitor, this.values);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the live list of member value pairs in this annotation.
+        * Adding and removing nodes from this list affects this node
+        * dynamically. All nodes in this list must be 
+        * {@link MemberValuePair}s; attempts to add any other 
+        * type of node will trigger an exception.
+        * 
+        * @return the live list of member value pairs in this 
+        *    annotation (element type: <code>MemberValuePair</code>)
+        */ 
+       public List values() {
+               return this.values;
+       }
+               
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.typeName == null ? 0 : getTypeName().treeSize())
+                       + this.values.listSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NullLiteral.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NullLiteral.java
new file mode 100644 (file)
index 0000000..849f247
--- /dev/null
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Null literal node.
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class NullLiteral extends Expression {
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(1);
+               createPropertyList(NullLiteral.class, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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;
+       }
+                       
+       /**
+        * Creates a new unparented null literal node owned by the given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       NullLiteral(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return NULL_LITERAL;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               NullLiteral result = new NullLiteral(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NumberLiteral.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/NumberLiteral.java
new file mode 100644 (file)
index 0000000..5cf4282
--- /dev/null
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Number literal nodes.
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class NumberLiteral extends Expression {
+
+       /**
+        * The "token" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor TOKEN_PROPERTY = 
+               new SimplePropertyDescriptor(NumberLiteral.class, "token", String.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(NumberLiteral.class, propertyList);
+               addProperty(TOKEN_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 token string; defaults to the integer literal "0".
+        */
+       private String tokenValue = "0";//$NON-NLS-1$
+
+       /**
+        * Creates a new unparented number literal node owned by the given AST.
+        * By default, the number literal is the token "<code>0</code>".
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       NumberLiteral(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == TOKEN_PROPERTY) {
+                       if (get) {
+                               return getToken();
+                       } else {
+                               setToken((String) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return NUMBER_LITERAL;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               NumberLiteral result = new NumberLiteral(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setToken(getToken());
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the token of this number literal node. The value is the sequence
+        * of characters that would appear in the source program.
+        * 
+        * @return the numeric literal token
+        */ 
+       public String getToken() {
+               return this.tokenValue;
+       }
+               
+       /**
+        * Sets the token of this number literal node. The value is the sequence
+        * of characters that would appear in the source program.
+        * 
+        * @param token the numeric literal token
+        * @exception IllegalArgumentException if the argument is incorrect
+        */ 
+       public void setToken(String token) {
+               // update internalSetToken(String) if this is changed
+               if (token == null || token.length() == 0) {
+                       throw new IllegalArgumentException();
+               }
+               Scanner scanner = this.ast.scanner;
+               char[] source = token.toCharArray();
+               scanner.setSource(source);
+               scanner.resetTo(0, source.length);
+               scanner.tokenizeComments = false;
+               scanner.tokenizeWhiteSpace = false;
+               try {
+                       int tokenType = scanner.getNextToken();
+                       switch(tokenType) {
+                               case TerminalTokens.TokenNameDoubleLiteral:
+                               case TerminalTokens.TokenNameIntegerLiteral:
+                               case TerminalTokens.TokenNameFloatingPointLiteral:
+                               case TerminalTokens.TokenNameLongLiteral:
+                                       break;
+                               case TerminalTokens.TokenNameMINUS :
+                                       tokenType = scanner.getNextToken();
+                                       switch(tokenType) {
+                                               case TerminalTokens.TokenNameDoubleLiteral:
+                                               case TerminalTokens.TokenNameIntegerLiteral:
+                                               case TerminalTokens.TokenNameFloatingPointLiteral:
+                                               case TerminalTokens.TokenNameLongLiteral:
+                                                       break;
+                                               default:
+                                                       throw new IllegalArgumentException("Invalid number literal : >" + token + "<"); //$NON-NLS-1$//$NON-NLS-2$
+                                       }
+                                       break;          
+                               default:
+                                       throw new IllegalArgumentException("Invalid number literal : >" + token + "<");//$NON-NLS-1$//$NON-NLS-2$
+                       }
+               } catch(InvalidInputException e) {
+                       throw new IllegalArgumentException();
+               } finally {
+                       scanner.tokenizeComments = true;
+                       scanner.tokenizeWhiteSpace = true;
+               }
+               preValueChange(TOKEN_PROPERTY);
+               this.tokenValue = token;
+               postValueChange(TOKEN_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * This method is a copy of setToken(String) that doesn't do any validation.
+        */
+       void internalSetToken(String token) {
+               preValueChange(TOKEN_PROPERTY);
+               this.tokenValue = token;
+               postValueChange(TOKEN_PROPERTY);
+       }
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               int size = BASE_NODE_SIZE + 1 * 4 + stringSize(tokenValue);
+               return size;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PackageBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PackageBinding.java
new file mode 100644 (file)
index 0000000..6f9edac
--- /dev/null
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IPackageFragment;
+import net.sourceforge.phpdt.core.IPackageFragmentRoot;
+import net.sourceforge.phpdt.core.JavaModelException;
+
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.env.IBinaryAnnotation;
+import net.sourceforge.phpdt.internal.compiler.env.IBinaryType;
+import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
+import net.sourceforge.phpdt.internal.compiler.env.NameEnvironmentAnswer;
+import net.sourceforge.phpdt.internal.compiler.lookup.BinaryTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+import net.sourceforge.phpdt.internal.core.NameLookup;
+import net.sourceforge.phpdt.internal.core.SearchableEnvironment;
+
+/**
+ * Internal implementation of package bindings.
+ */
+class PackageBinding implements IPackageBinding {
+
+       private static final String[] NO_NAME_COMPONENTS = CharOperation.NO_STRINGS;
+       private static final String UNNAMED = Util.EMPTY_STRING;
+       private static final char PACKAGE_NAME_SEPARATOR = '.';
+
+       private net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding binding;
+       private String name;
+       private BindingResolver resolver;
+       private String[] components;
+
+       PackageBinding(net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding binding, BindingResolver resolver) {
+               this.binding = binding;
+               this.resolver = resolver;
+       }
+
+       public IAnnotationBinding[] getAnnotations() {
+               try {
+                       INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment;
+                       if (!(nameEnvironment instanceof SearchableEnvironment))
+                               return AnnotationBinding.NoAnnotations;
+                       NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup;
+                       if (nameLookup == null)
+                               return AnnotationBinding.NoAnnotations;
+                       final String pkgName = getName();
+                       IPackageFragment[] pkgs = nameLookup.findPackageFragments(pkgName, false/*exact match*/);
+                       if (pkgs == null)
+                               return AnnotationBinding.NoAnnotations;
+
+                       for (int i = 0, len = pkgs.length; i < len; i++) {
+                               int fragType = pkgs[i].getKind();
+                               switch(fragType) {
+                                       case IPackageFragmentRoot.K_SOURCE:
+                                               String unitName = "package-info.java"; //$NON-NLS-1$
+                                               ICompilationUnit unit = pkgs[i].getCompilationUnit(unitName);
+                                               if (unit != null && unit.exists()) {
+                                                       ASTParser p = ASTParser.newParser(AST.JLS3);
+                                                       p.setSource(unit);
+                                                       p.setResolveBindings(true);
+                                                       p.setUnitName(unitName);
+                                                       p.setFocalPosition(0);
+                                                       p.setKind(ASTParser.K_COMPILATION_UNIT);
+                                                       CompilationUnit domUnit = (CompilationUnit) p.createAST(null);
+                                                       PackageDeclaration pkgDecl = domUnit.getPackage();
+                                                       if (pkgDecl != null) {
+                                                               List annos = pkgDecl.annotations();
+                                                               if (annos == null || annos.isEmpty())
+                                                                       return AnnotationBinding.NoAnnotations;
+                                                               IAnnotationBinding[] result = new IAnnotationBinding[annos.size()];
+                                                               int index=0;
+                                                               for (Iterator it = annos.iterator(); it.hasNext(); index++) {
+                                                                       result[index] = ((Annotation) it.next()).resolveAnnotationBinding();
+                                                                       // not resolving bindings
+                                                                       if (result[index] == null)
+                                                                               return AnnotationBinding.NoAnnotations;
+                                                               }
+                                                               return result;
+                                                       }
+                                               }
+                                               break;
+                                       case IPackageFragmentRoot.K_BINARY:
+                                               NameEnvironmentAnswer answer =
+                                                       nameEnvironment.findType(TypeConstants.PACKAGE_INFO_NAME, this.binding.compoundName);
+                                               if (answer != null && answer.isBinaryType()) {
+                                                       IBinaryType type = answer.getBinaryType();
+                                                       char[][][] missingTypeNames = type.getMissingTypeNames();
+                                                       IBinaryAnnotation[] binaryAnnotations = type.getAnnotations();
+                                                       net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[] binaryInstances =
+                                                               BinaryTypeBinding.createAnnotations(binaryAnnotations, this.binding.environment, missingTypeNames);
+                                                       net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[] allInstances =
+                                                               net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding.addStandardAnnotations(binaryInstances, type.getTagBits(), this.binding.environment);
+                                                       int total = allInstances.length;
+                                                       IAnnotationBinding[] domInstances = new AnnotationBinding[total];
+                                                       for (int a = 0; a < total; a++) {
+                                                               final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(allInstances[a]);
+                                                               if (annotationInstance == null) {// not resolving binding
+                                                                       return AnnotationBinding.NoAnnotations;
+                                                               }
+                                                               domInstances[a] = annotationInstance;
+                                                       }
+                                                       return domInstances;
+                                               }
+                               }
+                       }
+               } catch(JavaModelException e) {
+                       return AnnotationBinding.NoAnnotations;
+               }
+               return AnnotationBinding.NoAnnotations;
+       }
+
+       /*
+        * @see IBinding#getName()
+        */
+       public String getName() {
+               if (name == null) {
+                       computeNameAndComponents();
+               }
+               return name;
+       }
+
+       /*
+        * @see IPackageBinding#isUnnamed()
+        */
+       public boolean isUnnamed() {
+               return getName().equals(UNNAMED);
+       }
+
+       /*
+        * @see IPackageBinding#getNameComponents()
+        */
+       public String[] getNameComponents() {
+               if (components == null) {
+                       computeNameAndComponents();
+               }
+               return components;
+       }
+
+       /*
+        * @see IBinding#getKind()
+        */
+       public int getKind() {
+               return IBinding.PACKAGE;
+       }
+
+       /*
+        * @see IBinding#getModifiers()
+        */
+       public int getModifiers() {
+               return Modifier.NONE;
+       }
+
+       /*
+        * @see IBinding#isDeprecated()
+        */
+       public boolean isDeprecated() {
+               return false;
+       }
+
+       /**
+        * @see IBinding#isRecovered()
+        */
+       public boolean isRecovered() {
+               return false;
+       }
+
+       /**
+        * @see IBinding#isSynthetic()
+        */
+       public boolean isSynthetic() {
+               return false;
+       }
+
+       /*
+        * @see IBinding#getJavaElement()
+        */
+       public IJavaElement getJavaElement() {
+               INameEnvironment nameEnvironment = this.binding.environment.nameEnvironment; // a package binding always has a LooupEnvironment set
+               if (!(nameEnvironment instanceof SearchableEnvironment)) return null;
+               NameLookup nameLookup = ((SearchableEnvironment) nameEnvironment).nameLookup;
+               if (nameLookup == null) return null;
+               IJavaElement[] pkgs = nameLookup.findPackageFragments(getName(), false/*exact match*/);
+               if (pkgs == null) return null;
+               return pkgs[0];
+       }
+
+       /*
+        * @see IBinding#getKey()
+        */
+       public String getKey() {
+               return new String(this.binding.computeUniqueKey());
+       }
+
+       /*
+        * @see IBinding#isEqualTo(Binding)
+        * @since 3.1
+        */
+       public boolean isEqualTo(IBinding other) {
+               if (other == this) {
+                       // identical binding - equal (key or no key)
+                       return true;
+               }
+               if (other == null) {
+                       // other binding missing
+                       return false;
+               }
+               if (!(other instanceof PackageBinding)) {
+                       return false;
+               }
+               net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding packageBinding2 = ((PackageBinding) other).binding;
+               return CharOperation.equals(this.binding.compoundName, packageBinding2.compoundName);
+       }
+
+       private void computeNameAndComponents() {
+               char[][] compoundName = this.binding.compoundName;
+               if (compoundName == CharOperation.NO_CHAR_CHAR || compoundName == null) {
+                       name = UNNAMED;
+                       components = NO_NAME_COMPONENTS;
+               } else {
+                       int length = compoundName.length;
+                       components = new String[length];
+                       StringBuffer buffer = new StringBuffer();
+                       for (int i = 0; i < length - 1; i++) {
+                               components[i] = new String(compoundName[i]);
+                               buffer.append(compoundName[i]).append(PACKAGE_NAME_SEPARATOR);
+                       }
+                       components[length - 1] = new String(compoundName[length - 1]);
+                       buffer.append(compoundName[length - 1]);
+                       name = buffer.toString();
+               }
+       }
+
+       /*
+        * For debugging purpose only.
+        * @see java.lang.Object#toString()
+        */
+       public String toString() {
+               return this.binding.toString();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PackageDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PackageDeclaration.java
new file mode 100644 (file)
index 0000000..0043ee3
--- /dev/null
@@ -0,0 +1,362 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Package declaration AST node type.
+ * For JLS2:
+ * <pre>
+ * PackageDeclaration:
+ *    <b>package</b> Name <b>;</b>
+ * </pre>
+ * For JLS3, annotations and doc comment
+ * were added:
+ * <pre>
+ * PackageDeclaration:
+ *    [ Javadoc ] { Annotation } <b>package</b> Name <b>;</b>
+ * </pre>
+ * Note that the standard AST parser only recognizes a Javadoc comment
+ * immediately preceding the package declaration when it occurs in the
+ * special <code>package-info.java</code> compilation unit (JLS3 7.4.1.1).
+ * The Javadoc comment in that file contains the package description.
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class PackageDeclaration extends ASTNode {
+       
+       /**
+        * The "javadoc" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
+               new ChildPropertyDescriptor(PackageDeclaration.class, "javadoc", Javadoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "annotations" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor ANNOTATIONS_PROPERTY = 
+               new ChildListPropertyDescriptor(PackageDeclaration.class, "annotations", Annotation.class, CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(PackageDeclaration.class, "name", Name.class, MANDATORY, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(PackageDeclaration.class, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+               
+               propertyList = new ArrayList(4);
+               createPropertyList(PackageDeclaration.class, propertyList);
+               addProperty(JAVADOC_PROPERTY, propertyList);
+               addProperty(ANNOTATIONS_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The doc comment, or <code>null</code> if none.
+        * Defaults to none.
+        * @since 3.0
+        */
+       Javadoc optionalDocComment = null;
+
+       /**
+        * The annotations (element type: <code>Annotation</code>). 
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * @since 3.1
+        */
+       private ASTNode.NodeList annotations = null;
+       
+       /**
+        * The package name; lazily initialized; defaults to a unspecified,
+        * legal Java package identifier.
+        */
+       private Name packageName = null;
+
+       /**
+        * Creates a new AST node for a package declaration owned by the
+        * given AST. The package declaration initially has an unspecified,
+        * but legal, Java identifier; and an empty list of annotations.
+        * <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
+        */
+       PackageDeclaration(AST ast) {
+               super(ast);
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.annotations = new ASTNode.NodeList(ANNOTATIONS_PROPERTY);
+               }
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == JAVADOC_PROPERTY) {
+                       if (get) {
+                               return getJavadoc();
+                       } else {
+                               setJavadoc((Javadoc) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((Name) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == ANNOTATIONS_PROPERTY) {
+                       return annotations();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return PACKAGE_DECLARATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               PackageDeclaration result = new PackageDeclaration(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.setJavadoc((Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+                       result.annotations().addAll(ASTNode.copySubtrees(target, annotations()));
+               }
+               result.setName((Name) getName().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChild(visitor, getJavadoc());
+                               acceptChildren(visitor, this.annotations);
+                       }
+                       acceptChild(visitor, getName());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the live ordered list of annotations of this 
+        * package declaration (added in JLS3 API).
+        * 
+        * @return the live list of annotations
+        *    (element type: <code>Annotation</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public List annotations() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.annotations == null) {
+                       unsupportedIn2();
+               }
+               return this.annotations;
+       }
+       
+       /**
+        * Returns the doc comment node.
+        * 
+        * @return the doc comment node, or <code>null</code> if none
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.0
+        */
+       public Javadoc getJavadoc() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.annotations == null) {
+                       unsupportedIn2();
+               }
+               return this.optionalDocComment;
+       }
+
+       /**
+        * Sets or clears the doc comment node.
+        * 
+        * @param docComment the doc comment node, or <code>null</code> if none
+        * @exception IllegalArgumentException if the doc comment string is invalid
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.0
+        */
+       public void setJavadoc(Javadoc docComment) {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.annotations == null) {
+                       unsupportedIn2();
+               }
+               ASTNode oldChild = this.optionalDocComment;
+               preReplaceChild(oldChild, docComment, JAVADOC_PROPERTY);
+               this.optionalDocComment = docComment;
+               postReplaceChild(oldChild, docComment, JAVADOC_PROPERTY);
+       }
+
+       /**
+        * Returns the package name of this package declaration.
+        * 
+        * @return the package name node
+        */ 
+       public Name getName() {
+               if (this.packageName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.packageName == null) {
+                                       preLazyInit();
+                                       this.packageName = new SimpleName(this.ast);
+                                       postLazyInit(this.packageName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.packageName;
+       }
+       
+       /**
+        * Sets the package name of this package declaration to the given name.
+        * 
+        * @param name the new package name
+        * @exception IllegalArgumentException if`:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(Name name) {
+               if (name == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.packageName;
+               preReplaceChild(oldChild, name, NAME_PROPERTY);
+               this.packageName = name;
+               postReplaceChild(oldChild, name, NAME_PROPERTY);
+       }
+       
+       /**
+        * Resolves and returns the binding for the package declared in this package
+        * declaration.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public IPackageBinding resolveBinding() {
+               return this.ast.getBindingResolver().resolvePackage(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+                       + (this.annotations == null ? 0 : this.annotations.listSize())
+                       + (this.packageName == null ? 0 : getName().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ParameterizedType.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ParameterizedType.java
new file mode 100644 (file)
index 0000000..11343bb
--- /dev/null
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for a parameterized type (added in JLS3 API).
+ * These nodes are used for type references (as opposed to
+ * declarations of parameterized types.)
+ * <pre>
+ * ParameterizedType:
+ *    Type <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b>
+ * </pre>
+ * The first type may be a simple type or a qualified type;
+ * other kinds of types are meaningless.
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ParameterizedType extends Type {
+    /**
+     * This index represents the position inside a parameterized qualified type.
+     */
+    int index;
+       
+       /**
+        * The "type" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(ParameterizedType.class, "type", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "typeArguments" structural property of this node type.
+        */
+       public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(ParameterizedType.class, "typeArguments", Type.class, CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(ParameterizedType.class, propertyList);
+               addProperty(TYPE_PROPERTY, propertyList);
+               addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                       
+       /** 
+        * The type node; lazily initialized; defaults to an unspecfied, but legal,
+        * type.
+        */
+       private Type type = null;
+       
+       /**
+        * The type arguments (element type: <code>Type</code>). 
+        * Defaults to an empty list.
+        */
+       private ASTNode.NodeList typeArguments =
+               new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+       
+       /**
+        * Creates a new unparented node for a parameterized type owned by the
+        * given AST. By default, an unspecified, but legal, type, and no type
+        * arguments.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ParameterizedType(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == TYPE_PROPERTY) {
+                       if (get) {
+                               return getType();
+                       } else {
+                               setType((Type) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == TYPE_ARGUMENTS_PROPERTY) {
+                       return typeArguments();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return PARAMETERIZED_TYPE;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ParameterizedType result = new ParameterizedType(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setType((Type) ((ASTNode) getType()).clone(target));
+               result.typeArguments().addAll(
+                       ASTNode.copySubtrees(target, typeArguments()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getType());
+                       acceptChildren(visitor, this.typeArguments);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the type of this parameterized type.
+        * 
+        * @return the type of this parameterized type
+        */ 
+       public Type getType() {
+               if (this.type == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.type == null) {
+                                       preLazyInit();
+                                       this.type = new SimpleType(this.ast);
+                                       postLazyInit(this.type, TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.type;
+       }
+       
+       /**
+        * Sets the type of this parameterized type.
+        * 
+        * @param type the new type of this parameterized type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setType(Type type) {
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.type;
+               preReplaceChild(oldChild, type, TYPE_PROPERTY);
+               this.type = type;
+               postReplaceChild(oldChild, type, TYPE_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of type arguments of this parameterized 
+        * type. For the parameterized type to be plausible, the list should contain
+        * at least one element and not contain primitive types.
+        * 
+        * @return the live list of type arguments
+        *    (element type: <code>Type</code>)
+        */ 
+       public List typeArguments() {
+               return this.typeArguments;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.type == null ? 0 : getType().treeSize())
+                       + this.typeArguments.listSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ParenthesizedExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ParenthesizedExpression.java
new file mode 100644 (file)
index 0000000..e001403
--- /dev/null
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Parenthesized expression AST node type.
+ *
+ * <pre>
+ * ParenthesizedExpression:
+ *     <b>(</b> Expression <b>)</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ParenthesizedExpression extends Expression {
+       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(ParenthesizedExpression.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(ParenthesizedExpression.class, propertyList);
+               addProperty(EXPRESSION_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 expression; lazily initialized; defaults to a unspecified, but legal,
+        * expression.
+        */
+       private Expression expression = null;
+
+       /**
+        * Creates a new unparented parenthesized expression node owned by the given 
+        * AST. By default, the parenthesized expression has an unspecified, but
+        * legal, expression.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ParenthesizedExpression(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) 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.
+        */
+       final int getNodeType0() {
+               return PARENTHESIZED_EXPRESSION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ParenthesizedExpression result = new ParenthesizedExpression(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setExpression((Expression) getExpression().clone(target));
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getExpression());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this parenthesized expression.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new SimpleName(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.expression;
+       }
+               
+       /**
+        * Sets the expression of this parenthesized expression.
+        * 
+        * @param expression the new expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.expression == null ? 0 : getExpression().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PostfixExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PostfixExpression.java
new file mode 100644 (file)
index 0000000..de39325
--- /dev/null
@@ -0,0 +1,330 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Postfix expression AST node type.
+ *
+ * <pre>
+ * PostfixExpression:
+ *    Expression PostfixOperator
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class PostfixExpression extends Expression {
+
+       /**
+        * Postfix operators (typesafe enumeration).
+        * <pre>
+        * PostfixOperator:
+        *    <b><code>++</code></b>  <code>INCREMENT</code>
+        *    <b><code>--</code></b>  <code>DECREMENT</code>
+        * </pre>
+        */
+       public static class Operator {
+       
+               /**
+                * The token for the operator.
+                */
+               private String token;
+               
+               /**
+                * Creates a new postfix operator with the given token.
+                * <p>
+                * Note: this constructor is private. The only instances
+                * ever created are the ones for the standard operators.
+                * </p>
+                * 
+                * @param token the character sequence for the operator
+                */
+               private Operator(String token) {
+                       this.token = token;
+               }
+               
+               /**
+                * Returns the character sequence for the operator.
+                * 
+                * @return the character sequence for the operator
+                */
+               public String toString() {
+                       return token;
+               }
+               
+               /** Postfix increment "++" operator. */
+               public static final Operator INCREMENT = new Operator("++");//$NON-NLS-1$
+               /** Postfix decrement "--" operator. */
+               public static final Operator DECREMENT = new Operator("--");//$NON-NLS-1$
+               
+               /**
+                * Map from token to operator (key type: <code>String</code>;
+                * value type: <code>Operator</code>).
+                */
+               private static final Map CODES;
+               static {
+                       CODES = new HashMap(20);
+                       Operator[] ops = {
+                                       INCREMENT,
+                                       DECREMENT,
+                               };
+                       for (int i = 0; i < ops.length; i++) {
+                               CODES.put(ops[i].toString(), ops[i]);
+                       }
+               }
+
+               /**
+                * Returns the postfix operator corresponding to the given string,
+                * or <code>null</code> if none.
+                * <p>
+                * <code>toOperator</code> is the converse of <code>toString</code>:
+                * that is, <code>Operator.toOperator(op.toString()) == op</code> for 
+                * all operators <code>op</code>.
+                * </p>
+                * 
+                * @param token the character sequence for the operator
+                * @return the postfix operator, or <code>null</code> if none
+                */
+               public static Operator toOperator(String token) {
+                       return (Operator) CODES.get(token);
+               }
+       }
+       
+       /**
+        * The "operator" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor OPERATOR_PROPERTY = 
+               new SimplePropertyDescriptor(PostfixExpression.class, "operator", PostfixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "operand" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor OPERAND_PROPERTY = 
+               new ChildPropertyDescriptor(PostfixExpression.class, "operand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(PostfixExpression.class, propertyList);
+               addProperty(OPERAND_PROPERTY, propertyList);
+               addProperty(OPERATOR_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 operator; defaults to an unspecified postfix operator.
+        */
+       private PostfixExpression.Operator operator = 
+               PostfixExpression.Operator.INCREMENT;
+
+       /**
+        * The operand; lazily initialized; defaults to an unspecified,
+        * but legal, simple name.
+        */
+       private Expression operand = null;
+
+       /**
+        * Creates a new AST node for an postfix expression owned by the given 
+        * AST. By default, the node has unspecified (but legal) operator and 
+        * operand.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       PostfixExpression(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == OPERATOR_PROPERTY) {
+                       if (get) {
+                               return getOperator();
+                       } else {
+                               setOperator((Operator) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == OPERAND_PROPERTY) {
+                       if (get) {
+                               return getOperand();
+                       } else {
+                               setOperand((Expression) 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.
+        */
+       final int getNodeType0() {
+               return POSTFIX_EXPRESSION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               PostfixExpression result = new PostfixExpression(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setOperator(getOperator());
+               result.setOperand((Expression) getOperand().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getOperand());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the operator of this postfix expression.
+        * 
+        * @return the operator
+        */ 
+       public PostfixExpression.Operator getOperator() {
+               return this.operator;
+       }
+
+       /**
+        * Sets the operator of this postfix expression.
+        * 
+        * @param operator the operator
+        * @exception IllegalArgumentException if the argument is incorrect
+        */ 
+       public void setOperator(PostfixExpression.Operator operator) {
+               if (operator == null) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(OPERATOR_PROPERTY);
+               this.operator = operator;
+               postValueChange(OPERATOR_PROPERTY);
+       }
+
+       /**
+        * Returns the operand of this postfix expression.
+        * 
+        * @return the operand expression node
+        */ 
+       public Expression getOperand() {
+               if (this.operand  == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.operand == null) {
+                                       preLazyInit();
+                                       this.operand= new SimpleName(this.ast);
+                                       postLazyInit(this.operand, OPERAND_PROPERTY);
+                               }
+                       }
+               }
+               return this.operand;
+       }
+               
+       /**
+        * Sets the operand of this postfix expression.
+        * 
+        * @param expression the operand expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setOperand(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.operand;
+               preReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+               this.operand = expression;
+               postReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Operator as free
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.operand == null ? 0 : getOperand().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PrefixExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PrefixExpression.java
new file mode 100644 (file)
index 0000000..74bf961
--- /dev/null
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Prefix expression AST node type.
+ *
+ * <pre>
+ * PrefixExpression:
+ *    PrefixOperator Expression 
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class PrefixExpression extends Expression {
+
+       /**
+        * Prefix operators (typesafe enumeration).
+        * <pre>
+        * PrefixOperator:
+        *    <b><code>++</code></b>  <code>INCREMENT</code>
+        *    <b><code>--</code></b>  <code>DECREMENT</code>
+        *    <b><code>+</code></b>  <code>PLUS</code>
+        *    <b><code>-</code></b>  <code>MINUS</code>
+        *    <b><code>~</code></b>  <code>COMPLEMENT</code>
+        *    <b><code>!</code></b>  <code>NOT</code>
+        * </pre>
+        */
+       public static class Operator {
+       
+               /**
+                * The token for the operator.
+                */
+               private String token;
+               
+               /**
+                * Creates a new prefix operator with the given token.
+                * <p>
+                * Note: this constructor is private. The only instances
+                * ever created are the ones for the standard operators.
+                * </p>
+                * 
+                * @param token the character sequence for the operator
+                */
+               private Operator(String token) {
+                       this.token = token;
+               }
+               
+               /**
+                * Returns the character sequence for the operator.
+                * 
+                * @return the character sequence for the operator
+                */
+               public String toString() {
+                       return token;
+               }
+               
+               /** Prefix increment "++" operator. */
+               public static final Operator INCREMENT = new Operator("++");//$NON-NLS-1$
+               /** Prefix decrement "--" operator. */
+               public static final Operator DECREMENT = new Operator("--");//$NON-NLS-1$
+               /** Unary plus "+" operator. */
+               public static final Operator PLUS = new Operator("+");//$NON-NLS-1$
+               /** Unary minus "-" operator. */
+               public static final Operator MINUS = new Operator("-");//$NON-NLS-1$
+               /** Bitwise complement "~" operator. */
+               public static final Operator COMPLEMENT = new Operator("~");//$NON-NLS-1$
+               /** Logical complement "!" operator. */
+               public static final Operator NOT = new Operator("!");//$NON-NLS-1$
+               
+               /**
+                * Map from token to operator (key type: <code>String</code>;
+                * value type: <code>Operator</code>).
+                */
+               private static final Map CODES;
+               static {
+                       CODES = new HashMap(20);
+                       Operator[] ops = {
+                                       INCREMENT,
+                                       DECREMENT,
+                                       PLUS,
+                                       MINUS,
+                                       COMPLEMENT,
+                                       NOT,
+                               };
+                       for (int i = 0; i < ops.length; i++) {
+                               CODES.put(ops[i].toString(), ops[i]);
+                       }
+               }
+
+               /**
+                * Returns the prefix operator corresponding to the given string,
+                * or <code>null</code> if none.
+                * <p>
+                * <code>toOperator</code> is the converse of <code>toString</code>:
+                * that is, <code>Operator.toOperator(op.toString()) == op</code> for 
+                * all operators <code>op</code>.
+                * </p>
+                * 
+                * @param token the character sequence for the operator
+                * @return the prefix operator, or <code>null</code> if none
+                */
+               public static Operator toOperator(String token) {
+                       return (Operator) CODES.get(token);
+               }
+       }
+       
+       /**
+        * The "operator" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor OPERATOR_PROPERTY = 
+               new SimplePropertyDescriptor(PrefixExpression.class, "operator", PrefixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "operand" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor OPERAND_PROPERTY = 
+               new ChildPropertyDescriptor(PrefixExpression.class, "operand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(PrefixExpression.class, propertyList);
+               addProperty(OPERATOR_PROPERTY, propertyList);
+               addProperty(OPERAND_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 operator; defaults to an unspecified prefix operator.
+        */
+       private PrefixExpression.Operator operator = 
+               PrefixExpression.Operator.PLUS;
+
+       /**
+        * The operand; lazily initialized; defaults to an unspecified,
+        * but legal, simple name.
+        */
+       private Expression operand = null;
+
+       /**
+        * Creates a new AST node for an prefix expression owned by the given 
+        * AST. By default, the node has unspecified (but legal) operator and 
+        * operand.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       PrefixExpression(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == OPERATOR_PROPERTY) {
+                       if (get) {
+                               return getOperator();
+                       } else {
+                               setOperator((Operator) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == OPERAND_PROPERTY) {
+                       if (get) {
+                               return getOperand();
+                       } else {
+                               setOperand((Expression) 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.
+        */
+       final int getNodeType0() {
+               return PREFIX_EXPRESSION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               PrefixExpression result = new PrefixExpression(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setOperator(getOperator());
+               result.setOperand((Expression) getOperand().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getOperand());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the operator of this prefix expression.
+        * 
+        * @return the operator
+        */ 
+       public PrefixExpression.Operator getOperator() {
+               return this.operator;
+       }
+
+       /**
+        * Sets the operator of this prefix expression.
+        * 
+        * @param operator the operator
+        * @exception IllegalArgumentException if the argument is incorrect
+        */ 
+       public void setOperator(PrefixExpression.Operator operator) {
+               if (operator == null) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(OPERATOR_PROPERTY);
+               this.operator = operator;
+               postValueChange(OPERATOR_PROPERTY);
+       }
+
+       /**
+        * Returns the operand of this prefix expression.
+        * 
+        * @return the operand expression node
+        */ 
+       public Expression getOperand() {
+               if (this.operand  == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.operand == null) {
+                                       preLazyInit();
+                                       this.operand= new SimpleName(this.ast);
+                                       postLazyInit(this.operand, OPERAND_PROPERTY);
+                               }
+                       }
+               }
+               return this.operand;
+       }
+               
+       /**
+        * Sets the operand of this prefix expression.
+        * 
+        * @param expression the operand expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setOperand(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.operand;
+               preReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+               this.operand = expression;
+               postReplaceChild(oldChild, expression, OPERAND_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Operator as free
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.operand == null ? 0 : getOperand().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PrimitiveType.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/PrimitiveType.java
new file mode 100644 (file)
index 0000000..00b80e8
--- /dev/null
@@ -0,0 +1,302 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Primitive type nodes.
+ * <pre>
+ * PrimitiveType:
+ *    <b>byte</b>
+ *    <b>short</b>
+ *    <b>char</b>
+ *    <b>int</b>
+ *    <b>long</b>
+ *    <b>float</b>
+ *    <b>double</b>
+ *    <b>boolean</b>
+ *    <b>void</b>
+ * </pre>
+ * <p>
+ * Note that due to the fact that AST nodes belong to a specific AST and
+ * have a specific parent, there needs to multiple instances of these
+ * nodes.
+ * </p>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class PrimitiveType extends Type {
+       
+       /**
+        * Primitive type codes (typesafe enumeration).
+        * <pre>
+        *    <b>byte</b>       BYTE
+        *    <b>short</b>      SHORT
+        *    <b>char</b>       CHAR
+        *    <b>int</b>        INT
+        *    <b>long</b>       LONG
+        *    <b>float</b>      FLOAT
+        *    <b>double</b>     DOUBLE
+        *    <b>boolean</b>    BOOLEAN
+        *    <b>void</b>       VOID
+        * </pre>
+        */
+       public static class Code {
+       
+               /**
+                * The name of the type.
+                */
+               private String name;
+               
+               /**
+                * Creates a new primitive type code with the given name.
+                * <p>
+                * Note: this constructor is package-private. The only instances
+                * ever created are the ones for the standard primitive types.
+                * </p>
+                * 
+                * @param name the standard name of the primitive type
+                */
+               Code(String name) {
+                       this.name = name;
+               }
+               
+               /**
+                * Returns the standard name of the primitive type.
+                * 
+                * @return the standard name of the primitive type
+                */
+               public String toString() {
+                       return name;
+               }
+       }               
+       
+       /** Type code for the primitive type "int". */
+       public static final Code INT = new Code("int");//$NON-NLS-1$
+       /** Type code for the primitive type "char". */
+       public static final Code CHAR = new Code("char");//$NON-NLS-1$
+       /** Type code for the primitive type "boolean". */
+       public static final Code BOOLEAN = new Code("boolean");//$NON-NLS-1$
+       /** Type code for the primitive type "short". */
+       public static final Code SHORT = new Code("short");//$NON-NLS-1$
+       /** Type code for the primitive type "long". */
+       public static final Code LONG = new Code("long");//$NON-NLS-1$
+       /** Type code for the primitive type "float". */
+       public static final Code FLOAT = new Code("float");//$NON-NLS-1$
+       /** Type code for the primitive type "double". */
+       public static final Code DOUBLE = new Code("double");//$NON-NLS-1$
+       /** Type code for the primitive type "byte". */
+       public static final Code BYTE = new Code("byte");//$NON-NLS-1$
+
+       /** Type code for the primitive type "void". Note that "void" is
+        * special in that its only legitimate uses are as a method return
+        * type and as a type literal.
+        */
+       public static final Code VOID = new Code("void");//$NON-NLS-1$
+               
+       /** 
+        * The primitive type code; one of the PrimitiveType constants; default
+        * is int.
+        */
+       private PrimitiveType.Code typeCode = INT;
+       
+       /**
+        * Map from token to primitive type code (key type: <code>String</code>;
+        * value type: <code>PrimitiveType.Code</code>).
+        */
+       private static final Map CODES;
+       static {
+               CODES = new HashMap(20);
+               Code[] ops = {
+                               INT,
+                               BYTE,
+                               CHAR,
+                               BOOLEAN,
+                               SHORT,
+                               LONG,
+                               FLOAT,
+                               DOUBLE,
+                               VOID,
+                       };
+               for (int i = 0; i < ops.length; i++) {
+                       CODES.put(ops[i].toString(), ops[i]);
+               }
+       }
+       
+       /**
+        * Returns the primitive type code corresponding to the given string,
+        * or <code>null</code> if none.
+        * <p>
+        * <code>toCode</code> is the converse of <code>toString</code>:
+        * that is, 
+        * <code>PrimitiveType.Code.toCode(code.toString()) == code</code>
+        * for all type code <code>code</code>.
+        * </p>
+        * 
+        * @param token the standard name of the primitive type
+        * @return the primitive type code, or <code>null</code> if none
+        */
+       public static PrimitiveType.Code toCode(String token) {
+               return (PrimitiveType.Code) CODES.get(token);
+       }
+       
+       /**
+        * The "primitiveTypeCode" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor PRIMITIVE_TYPE_CODE_PROPERTY = 
+               new SimplePropertyDescriptor(PrimitiveType.class, "primitiveTypeCode", PrimitiveType.Code.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(PrimitiveType.class, propertyList);
+               addProperty(PRIMITIVE_TYPE_CODE_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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;
+       }
+                       
+       /**
+        * Creates a new unparented node for a primitive type owned by the given
+        * AST. By default, the node has type "int".
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       PrimitiveType(AST ast) {
+               super(ast);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == PRIMITIVE_TYPE_CODE_PROPERTY) {
+                       if (get) {
+                               return getPrimitiveTypeCode();
+                       } else {
+                               setPrimitiveTypeCode((Code) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return PRIMITIVE_TYPE;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               PrimitiveType result = new PrimitiveType(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setPrimitiveTypeCode(getPrimitiveTypeCode());
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the primitive type code.
+        * 
+        * @return one of the primitive type code constants declared in this
+        *    class
+        */
+       public PrimitiveType.Code getPrimitiveTypeCode() {
+               return this.typeCode;
+       }
+       
+       /**
+        * Sets the primitive type code.
+        * 
+        * @param typeCode one of the primitive type code constants declared in 
+        *    this class
+        * @exception IllegalArgumentException if the argument is incorrect
+        */
+       public void setPrimitiveTypeCode(PrimitiveType.Code typeCode) {
+               if (typeCode == null) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(PRIMITIVE_TYPE_CODE_PROPERTY);
+               this.typeCode = typeCode;
+               postValueChange(PRIMITIVE_TYPE_CODE_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/QualifiedName.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/QualifiedName.java
new file mode 100644 (file)
index 0000000..e5b29b0
--- /dev/null
@@ -0,0 +1,281 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * AST node for a qualified name. A qualified name is defined recursively
+ * as a simple name preceded by a name, which qualifies it. Expressing it this
+ * way means that the qualifier and the simple name get their own AST nodes.
+ * <pre>
+ * QualifiedName:
+ *    Name <b>.</b> SimpleName
+ * </pre>
+ * <p>
+ * See <code>FieldAccess</code> for guidelines on handling other expressions
+ * that resemble qualified names.
+ * </p>
+ * 
+ * @see FieldAccess
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class QualifiedName extends Name {
+       
+       /**
+        * The "qualifier" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor QUALIFIER_PROPERTY = 
+               new ChildPropertyDescriptor(QualifiedName.class, "qualifier", Name.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(QualifiedName.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(QualifiedName.class, propertyList);
+               addProperty(QUALIFIER_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 identifier; lazily initialized; defaults to a unspecified, legal 
+        * Java identifier.
+        */
+       private Name qualifier = null;
+       
+       /**
+        * The name being qualified; lazily initialized; defaults to a unspecified,
+        * legal Java identifier.
+        */
+       private SimpleName name = null;
+       
+       /**
+        * Creates a new AST node for a qualified name owned by the given AST.
+        * <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
+        */
+       QualifiedName(AST ast) {
+               super(ast);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == QUALIFIER_PROPERTY) {
+                       if (get) {
+                               return getQualifier();
+                       } else {
+                               setQualifier((Name) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) 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.
+        */
+       final int getNodeType0() {
+               return QUALIFIED_NAME;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               QualifiedName result = new QualifiedName(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setQualifier((Name) getQualifier().clone(target));
+               result.setName((SimpleName) getName().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getQualifier());
+                       acceptChild(visitor, getName());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the qualifier part of this qualified name.
+        * 
+        * @return the qualifier part of this qualified name
+        */ 
+       public Name getQualifier() {
+               if (this.qualifier == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.qualifier == null) {
+                                       preLazyInit();
+                                       this.qualifier = new SimpleName(this.ast);
+                                       postLazyInit(this.qualifier, QUALIFIER_PROPERTY);
+                               }
+                       }
+               }
+               return this.qualifier;
+       }
+       
+       /**
+        * Sets the qualifier of this qualified name to the given name.
+        * 
+        * @param qualifier the qualifier of this qualified name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setQualifier(Name qualifier) {
+               if (qualifier == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.qualifier;
+               preReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY);
+               this.qualifier = qualifier;
+               postReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY);
+       }
+       
+       /**
+        * Returns the name part of this qualified name.
+        * 
+        * @return the name being qualified 
+        */ 
+       public SimpleName getName() {
+               if (this.name == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.name == null) {
+                                       preLazyInit();
+                                       this.name = new SimpleName(this.ast);
+                                       postLazyInit(this.name, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.name;
+       }
+       
+       /**
+        * Sets the name part of this qualified name to the given simple name.
+        * 
+        * @param name the identifier of this qualified name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName name) {
+               if (name == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.name;
+               preReplaceChild(oldChild, name, NAME_PROPERTY);
+               this.name = name;
+               postReplaceChild(oldChild, name, NAME_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on Name.
+        */
+       void appendName(StringBuffer buffer) {
+               getQualifier().appendName(buffer);
+               buffer.append('.');
+               getName().appendName(buffer);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NAME_NODE_SIZE + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.name == null ? 0 : getName().treeSize())
+                       + (this.qualifier == null ? 0 : getQualifier().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/QualifiedType.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/QualifiedType.java
new file mode 100644 (file)
index 0000000..1c5857b
--- /dev/null
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for a qualified type (added in JLS3 API).
+ * <pre>
+ * QualifiedType:
+ *    Type <b>.</b> SimpleName
+ * </pre>
+ * <p>
+ * Not all node arragements will represent legal Java constructs. In particular,
+ * it is nonsense if the type is an array type or primitive type. The normal use
+ * is when the type is a simple or parameterized type.
+ * </p>
+ * <p>
+ * A type like "A.B" can be represented either of two ways:
+ * <ol>
+ * <li>
+ * <code>QualifiedType(SimpleType(SimpleName("A")),SimpleName("B"))</code>
+ * </li>
+ * <li>
+ * <code>SimpleType(QualifiedName(SimpleName("A"),SimpleName("B")))</code>
+ * </li>
+ * </ol>
+ * The first form is preferred when "A" is known to be a type. However, a 
+ * parser cannot always determine this. Clients should be prepared to handle
+ * either rather than make assumptions. (Note also that the first form
+ * became possible as of JLS3; only the second form existed in JLS2 API.)
+ * </p>
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class QualifiedType extends Type {
+    /**
+     * This index represents the position inside a parameterized qualified type.
+     */
+    int index;
+       
+       /**
+        * The "qualifier" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor QUALIFIER_PROPERTY = 
+               new ChildPropertyDescriptor(QualifiedType.class, "qualifier", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "name" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(QualifiedType.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(QualifiedType.class, propertyList);
+               addProperty(QUALIFIER_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                       
+       /** 
+        * The type node; lazily initialized; defaults to a type with
+        * an unspecfied, but legal, simple name.
+        */
+       private Type qualifier = null;
+       
+       /**
+        * The name being qualified; lazily initialized; defaults to a unspecified,
+        * legal Java identifier.
+        */
+       private SimpleName name = null;
+
+       /**
+        * Creates a new unparented node for a qualified type owned by the
+        * given AST. By default, an unspecified, but legal, qualifier and name.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       QualifiedType(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == QUALIFIER_PROPERTY) {
+                       if (get) {
+                               return getQualifier();
+                       } else {
+                               setQualifier((Type) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) 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.
+        */
+       final int getNodeType0() {
+               return QUALIFIED_TYPE;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               QualifiedType result = new QualifiedType(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setQualifier((Type) ((ASTNode) getQualifier()).clone(target));
+               result.setName((SimpleName) ((ASTNode) getName()).clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getQualifier());
+                       acceptChild(visitor, getName());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the qualifier of this qualified type.
+        * 
+        * @return the qualifier of this qualified type
+        */ 
+       public Type getQualifier() {
+               if (this.qualifier == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.qualifier == null) {
+                                       preLazyInit();
+                                       this.qualifier = new SimpleType(this.ast);
+                                       postLazyInit(this.qualifier, QUALIFIER_PROPERTY);
+                               }
+                       }
+               }
+               return this.qualifier;
+       }
+       
+       /**
+        * Sets the qualifier of this qualified type to the given type.
+        * 
+        * @param type the new qualifier of this qualified type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setQualifier(Type type) {
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.qualifier;
+               preReplaceChild(oldChild, type, QUALIFIER_PROPERTY);
+               this.qualifier = type;
+               postReplaceChild(oldChild, type, QUALIFIER_PROPERTY);
+       }
+
+       /**
+        * Returns the name part of this qualified type.
+        * 
+        * @return the name being qualified 
+        */ 
+       public SimpleName getName() {
+               if (this.name == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.name == null) {
+                                       preLazyInit();
+                                       this.name = new SimpleName(this.ast);
+                                       postLazyInit(this.name, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.name;
+       }
+       
+       /**
+        * Sets the name part of this qualified type to the given simple name.
+        * 
+        * @param name the identifier of this qualified name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName name) {
+               if (name == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.name;
+               preReplaceChild(oldChild, name, NAME_PROPERTY);
+               this.name = name;
+               postReplaceChild(oldChild, name, NAME_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.qualifier == null ? 0 : getQualifier().treeSize())
+                       + (this.name == null ? 0 : getName().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/RecoveredTypeBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/RecoveredTypeBinding.java
new file mode 100644 (file)
index 0000000..1cccc7f
--- /dev/null
@@ -0,0 +1,690 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.List;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
+import net.sourceforge.phpdt.internal.compiler.lookup.CompilationUnitScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.util.SuffixConstants;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+import net.sourceforge.phpdt.internal.core.PackageFragment;
+
+/**
+ * This class represents the recovered binding for a type
+ */
+class RecoveredTypeBinding implements ITypeBinding {
+
+       private VariableDeclaration variableDeclaration;
+       private Type currentType;
+       private BindingResolver resolver;
+       private int dimensions;
+       private RecoveredTypeBinding innerTypeBinding;
+       private ITypeBinding[] typeArguments;
+       private net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding;
+
+       RecoveredTypeBinding(BindingResolver resolver, VariableDeclaration variableDeclaration) {
+               this.variableDeclaration = variableDeclaration;
+               this.resolver = resolver;
+               this.currentType = getType();
+               this.dimensions = variableDeclaration.getExtraDimensions();
+               if (this.currentType.isArrayType()) {
+                       this.dimensions += ((ArrayType) this.currentType).getDimensions();
+               }
+       }
+
+       RecoveredTypeBinding(BindingResolver resolver, net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding) {
+               this.resolver = resolver;
+               this.dimensions = typeBinding.dimensions();
+               this.binding = typeBinding;
+       }
+
+       RecoveredTypeBinding(BindingResolver resolver, Type type) {
+               this.currentType = type;
+               this.resolver = resolver;
+               this.dimensions = 0;
+               if (type.isArrayType()) {
+                       this.dimensions += ((ArrayType) type).getDimensions();
+               }
+       }
+
+       RecoveredTypeBinding(BindingResolver resolver, RecoveredTypeBinding typeBinding, int dimensions) {
+               this.innerTypeBinding = typeBinding;
+               this.dimensions = typeBinding.getDimensions() + dimensions;
+               this.resolver = resolver;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#createArrayType(int)
+        */
+       public ITypeBinding createArrayType(int dims) {
+               return this.resolver.getTypeBinding(this, dims);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getBinaryName()
+        */
+       public String getBinaryName() {
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getBound()
+        */
+       public ITypeBinding getBound() {
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getComponentType()
+        */
+       public ITypeBinding getComponentType() {
+               if (this.dimensions == 0) return null;
+               return this.resolver.getTypeBinding(this, -1);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaredFields()
+        */
+       public IVariableBinding[] getDeclaredFields() {
+               return TypeBinding.NO_VARIABLE_BINDINGS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaredMethods()
+        */
+       public IMethodBinding[] getDeclaredMethods() {
+               return TypeBinding.NO_METHOD_BINDINGS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaredModifiers()
+        */
+       public int getDeclaredModifiers() {
+               return 0;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaredTypes()
+        */
+       public ITypeBinding[] getDeclaredTypes() {
+               return TypeBinding.NO_TYPE_BINDINGS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaringClass()
+        */
+       public ITypeBinding getDeclaringClass() {
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getDeclaringMethod()
+        */
+       public IMethodBinding getDeclaringMethod() {
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getDimensions()
+        */
+       public int getDimensions() {
+               return this.dimensions;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getElementType()
+        */
+       public ITypeBinding getElementType() {
+               if (this.binding != null) {
+                       if (this.binding.isArrayType()) {
+                               ArrayBinding arrayBinding = (ArrayBinding) this.binding;
+                               return new RecoveredTypeBinding(this.resolver, arrayBinding.leafComponentType);
+                       } else {
+                               return new RecoveredTypeBinding(this.resolver, this.binding);
+                       }
+               }
+               if (this.innerTypeBinding != null) {
+                       return this.innerTypeBinding.getElementType();
+               }
+               if (this.currentType!= null && this.currentType.isArrayType()) {
+                       return this.resolver.getTypeBinding(((ArrayType) this.currentType).getElementType());
+               }
+               if (this.variableDeclaration != null && this.variableDeclaration.getExtraDimensions() != 0) {
+                       return this.resolver.getTypeBinding(getType());
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getErasure()
+        */
+       public ITypeBinding getErasure() {
+               return this;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getInterfaces()
+        */
+       public ITypeBinding[] getInterfaces() {
+               return TypeBinding.NO_TYPE_BINDINGS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getModifiers()
+        */
+       public int getModifiers() {
+               return Modifier.NONE;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getName()
+        */
+       public String getName() {
+               char[] brackets = new char[this.dimensions * 2];
+               for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) {
+                       brackets[i] = ']';
+                       brackets[i - 1] = '[';
+               }
+               StringBuffer buffer = new StringBuffer(this.getInternalName());
+               buffer.append(brackets);
+               return String.valueOf(buffer);
+       }
+
+       private String getInternalName() {
+               if (this.innerTypeBinding != null) {
+                       return this.innerTypeBinding.getInternalName();
+               }
+               ReferenceBinding referenceBinding = getReferenceBinding();
+               if (referenceBinding != null) {
+                       return new String(referenceBinding.compoundName[referenceBinding.compoundName.length - 1]);
+               }
+               return this.getTypeNameFrom(getType());
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getPackage()
+        */
+       public IPackageBinding getPackage() {
+               if (this.binding != null) {
+                       switch (this.binding.kind()) {
+                               case Binding.BASE_TYPE :
+                               case Binding.ARRAY_TYPE :
+                               case Binding.TYPE_PARAMETER : // includes capture scenario
+                               case Binding.WILDCARD_TYPE :
+                               case Binding.INTERSECTION_TYPE:
+                                       return null;
+                       }
+                       IPackageBinding packageBinding = this.resolver.getPackageBinding(this.binding.getPackage());
+                       if (packageBinding != null) return packageBinding;
+               }
+               if (this.innerTypeBinding != null && this.dimensions > 0) {
+                       return null;
+               }
+               CompilationUnitScope scope = this.resolver.scope();
+               if (scope != null) {
+                       return this.resolver.getPackageBinding(scope.getCurrentPackage());
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getQualifiedName()
+        */
+       public String getQualifiedName() {
+               ReferenceBinding referenceBinding = getReferenceBinding();
+               if (referenceBinding != null) {
+                       StringBuffer buffer = new StringBuffer();
+                       char[] brackets = new char[this.dimensions * 2];
+                       for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) {
+                               brackets[i] = ']';
+                               brackets[i - 1] = '[';
+                       }
+                       buffer.append(CharOperation.toString(referenceBinding.compoundName));
+                       buffer.append(brackets);
+                       return String.valueOf(buffer);
+               } else { 
+                       return getName();
+               }
+       }
+
+       private ReferenceBinding getReferenceBinding() {
+               if (this.binding != null) {
+                       if (this.binding.isArrayType()) {
+                               ArrayBinding arrayBinding = (ArrayBinding) this.binding;
+                               if (arrayBinding.leafComponentType instanceof ReferenceBinding) {
+                                       return (ReferenceBinding) arrayBinding.leafComponentType;
+                               }
+                       } else if (this.binding instanceof ReferenceBinding) {
+                               return (ReferenceBinding) this.binding;
+                       }
+               } else if (this.innerTypeBinding != null) {
+                       return this.innerTypeBinding.getReferenceBinding();
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getSuperclass()
+        */
+       public ITypeBinding getSuperclass() {
+               if (getQualifiedName().equals("java.lang.Object")) {    //$NON-NLS-1$
+                       return null;
+               }
+               return this.resolver.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeArguments()
+        */
+       public ITypeBinding[] getTypeArguments() {
+               if (this.binding != null) {
+                       return this.typeArguments = TypeBinding.NO_TYPE_BINDINGS;
+               }
+               if (this.typeArguments != null) {
+                       return typeArguments;
+               }
+
+               if (this.innerTypeBinding != null) {
+                       return this.innerTypeBinding.getTypeArguments();
+               }
+
+               if (this.currentType.isParameterizedType()) {
+                       ParameterizedType parameterizedType = (ParameterizedType) this.currentType;
+                       List typeArgumentsList = parameterizedType.typeArguments();
+                       int size = typeArgumentsList.size();
+                       ITypeBinding[] temp = new ITypeBinding[size];
+                       for (int i = 0; i < size; i++) {
+                               ITypeBinding currentTypeBinding = ((Type) typeArgumentsList.get(i)).resolveBinding();
+                               if (currentTypeBinding == null) {
+                                       return this.typeArguments = TypeBinding.NO_TYPE_BINDINGS;
+                               }
+                               temp[i] = currentTypeBinding;
+                       }
+                       return this.typeArguments = temp;
+               }
+               return this.typeArguments = TypeBinding.NO_TYPE_BINDINGS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeBounds()
+        */
+       public ITypeBinding[] getTypeBounds() {
+               return TypeBinding.NO_TYPE_BINDINGS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeDeclaration()
+        */
+       public ITypeBinding getTypeDeclaration() {
+               return this;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeParameters()
+        */
+       public ITypeBinding[] getTypeParameters() {
+               return TypeBinding.NO_TYPE_BINDINGS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getWildcard()
+        */
+       public ITypeBinding getWildcard() {
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isAnnotation()
+        */
+       public boolean isAnnotation() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isAnonymous()
+        */
+       public boolean isAnonymous() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isArray()
+        */
+       public boolean isArray() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isAssignmentCompatible(org.eclipse.jdt.core.dom.ITypeBinding)
+        */
+       public boolean isAssignmentCompatible(ITypeBinding typeBinding) {
+               if ("java.lang.Object".equals(typeBinding.getQualifiedName())) { //$NON-NLS-1$
+                       return true;
+               }
+               // since recovered binding are not unique isEqualTo is required
+               return this.isEqualTo(typeBinding);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isCapture()
+        */
+       public boolean isCapture() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isCastCompatible(org.eclipse.jdt.core.dom.ITypeBinding)
+        */
+       public boolean isCastCompatible(ITypeBinding typeBinding) {
+               if ("java.lang.Object".equals(typeBinding.getQualifiedName())) { //$NON-NLS-1$
+                       return true;
+               }
+               // since recovered binding are not unique isEqualTo is required
+               return this.isEqualTo(typeBinding);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isClass()
+        */
+       public boolean isClass() {
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isEnum()
+        */
+       public boolean isEnum() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isFromSource()
+        */
+       public boolean isFromSource() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isGenericType()
+        */
+       public boolean isGenericType() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isInterface()
+        */
+       public boolean isInterface() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isLocal()
+        */
+       public boolean isLocal() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isMember()
+        */
+       public boolean isMember() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isNested()
+        */
+       public boolean isNested() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isNullType()
+        */
+       public boolean isNullType() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isParameterizedType()
+        */
+       public boolean isParameterizedType() {
+               if (this.innerTypeBinding != null) {
+                       return this.innerTypeBinding.isParameterizedType();
+               }
+               if (this.currentType != null) {
+                       return this.currentType.isParameterizedType();
+               }
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isPrimitive()
+        */
+       public boolean isPrimitive() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isRawType()
+        */
+       public boolean isRawType() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isSubTypeCompatible(org.eclipse.jdt.core.dom.ITypeBinding)
+        */
+       public boolean isSubTypeCompatible(ITypeBinding typeBinding) {
+               if ("java.lang.Object".equals(typeBinding.getQualifiedName())) { //$NON-NLS-1$
+                       return true;
+               }
+               // since recovered binding are not unique isEqualTo is required
+               return this.isEqualTo(typeBinding);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isTopLevel()
+        */
+       public boolean isTopLevel() {
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isTypeVariable()
+        */
+       public boolean isTypeVariable() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isUpperbound()
+        */
+       public boolean isUpperbound() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isWildcardType()
+        */
+       public boolean isWildcardType() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.IBinding#getAnnotations()
+        */
+       public IAnnotationBinding[] getAnnotations() {
+               return AnnotationBinding.NoAnnotations;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.IBinding#getJavaElement()
+        */
+       public IJavaElement getJavaElement() {
+               IPackageBinding packageBinding = getPackage();
+               if (packageBinding != null) {
+                       final IJavaElement javaElement = packageBinding.getJavaElement();
+                       if (javaElement != null && javaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
+                               // best effort: we don't know if the recovered binding is a binary or source binding, so go with a compilation unit
+                               return ((PackageFragment) javaElement).getCompilationUnit(getInternalName() + SuffixConstants.SUFFIX_STRING_java);
+                       }
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.IBinding#getKey()
+        */
+       public String getKey() {
+               StringBuffer buffer = new StringBuffer();
+               buffer.append("Recovered#"); //$NON-NLS-1$
+               if (this.innerTypeBinding != null) {
+                       buffer.append("innerTypeBinding") //$NON-NLS-1$
+                             .append(this.innerTypeBinding.getKey());
+               } else if (this.currentType != null) {
+                       buffer.append("currentType") //$NON-NLS-1$
+                             .append(this.currentType.toString());
+               } else if (this.binding != null) {
+                       buffer.append("typeBinding") //$NON-NLS-1$
+                                 .append(this.binding.computeUniqueKey());
+               } else if (variableDeclaration != null) {
+                       buffer
+                               .append("variableDeclaration") //$NON-NLS-1$
+                               .append(this.variableDeclaration.getClass())
+                               .append(this.variableDeclaration.getName().getIdentifier())
+                               .append(this.variableDeclaration.getExtraDimensions());
+               }
+               buffer.append(this.getDimensions());
+               if (this.typeArguments != null) {
+                       buffer.append('<');
+                       for (int i = 0, max = this.typeArguments.length; i < max; i++) {
+                               if (i != 0) {
+                                       buffer.append(',');
+                               }
+                               buffer.append(this.typeArguments[i].getKey());
+                       }
+                       buffer.append('>');
+               }
+               return String.valueOf(buffer);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.IBinding#getKind()
+        */
+       public int getKind() {
+               return IBinding.TYPE;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.IBinding#isDeprecated()
+        */
+       public boolean isDeprecated() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.IBinding#isEqualTo(org.eclipse.jdt.core.dom.IBinding)
+        */
+       public boolean isEqualTo(IBinding other) {
+               if (!other.isRecovered() || other.getKind() != IBinding.TYPE) return false;
+               return this.getKey().equals(other.getKey());
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.IBinding#isRecovered()
+        */
+       public boolean isRecovered() {
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.IBinding#isSynthetic()
+        */
+       public boolean isSynthetic() {
+               return false;
+       }
+
+       private String getTypeNameFrom(Type type) {
+               if (type == null) return Util.EMPTY_STRING;
+               switch(type.getNodeType0()) {
+                       case ASTNode.ARRAY_TYPE :
+                               ArrayType arrayType = (ArrayType) type;
+                               type = arrayType.getElementType();
+                               return getTypeNameFrom(type);
+                       case ASTNode.PARAMETERIZED_TYPE :
+                               ParameterizedType parameterizedType = (ParameterizedType) type;
+                               StringBuffer buffer = new StringBuffer(getTypeNameFrom(parameterizedType.getType()));
+                               ITypeBinding[] tArguments = getTypeArguments();
+                               final int typeArgumentsLength = tArguments.length;
+                               if (typeArgumentsLength != 0) {
+                                       buffer.append('<');
+                                       for (int i = 0; i < typeArgumentsLength; i++) {
+                                               if (i > 0) {
+                                                       buffer.append(',');
+                                               }
+                                               buffer.append(tArguments[i].getName());
+                                       }
+                                       buffer.append('>');
+                               }
+                               return String.valueOf(buffer);
+                       case ASTNode.PRIMITIVE_TYPE :
+                               PrimitiveType primitiveType = (PrimitiveType) type;
+                               return primitiveType.getPrimitiveTypeCode().toString();
+                       case ASTNode.QUALIFIED_TYPE :
+                               QualifiedType qualifiedType = (QualifiedType) type;
+                               return qualifiedType.getName().getIdentifier();
+                       case ASTNode.SIMPLE_TYPE :
+                               SimpleType simpleType = (SimpleType) type;
+                               Name name = simpleType.getName();
+                               if (name.isQualifiedName()) {
+                                       QualifiedName qualifiedName = (QualifiedName) name;
+                                       return qualifiedName.getName().getIdentifier();
+                               }
+                               return ((SimpleName) name).getIdentifier();
+               }
+               return Util.EMPTY_STRING;
+       }
+
+       private Type getType() {
+               if (this.currentType != null) {
+                       return this.currentType;
+               }
+               if (this.variableDeclaration == null) return null;
+               switch(this.variableDeclaration.getNodeType()) {
+                       case ASTNode.SINGLE_VARIABLE_DECLARATION :
+                               SingleVariableDeclaration singleVariableDeclaration = (SingleVariableDeclaration) this.variableDeclaration;
+                               return singleVariableDeclaration.getType();
+                       default :
+                               // this is a variable declaration fragment
+                               ASTNode parent = this.variableDeclaration.getParent();
+                               switch(parent.getNodeType()) {
+                                       case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
+                                               VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) parent;
+                                               return variableDeclarationExpression.getType();
+                                       case ASTNode.VARIABLE_DECLARATION_STATEMENT :
+                                               VariableDeclarationStatement statement = (VariableDeclarationStatement) parent;
+                                               return statement.getType();
+                                       case ASTNode.FIELD_DECLARATION :
+                                               FieldDeclaration fieldDeclaration  = (FieldDeclaration) parent;
+                                               return fieldDeclaration.getType();
+                               }
+               }
+               return null; // should not happen
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/RecoveredVariableBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/RecoveredVariableBinding.java
new file mode 100644 (file)
index 0000000..242bd11
--- /dev/null
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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 net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+
+/**
+ * This class represents the recovered binding for a variable
+ */
+class RecoveredVariableBinding implements IVariableBinding {
+
+       private VariableDeclaration variableDeclaration;
+       private BindingResolver resolver;
+
+       RecoveredVariableBinding(BindingResolver resolver, VariableDeclaration variableDeclaration) {
+               this.resolver = resolver;
+               this.variableDeclaration = variableDeclaration;
+       }
+       public Object getConstantValue() {
+               return null;
+       }
+
+       public ITypeBinding getDeclaringClass() {
+               ASTNode parent = this.variableDeclaration.getParent();
+               while (parent != null && parent.getNodeType() != ASTNode.TYPE_DECLARATION) {
+                       parent = parent.getParent();
+               }
+               if (parent != null) {
+                       return ((TypeDeclaration) parent).resolveBinding();
+               }
+               return null;
+       }
+
+       public IMethodBinding getDeclaringMethod() {
+               ASTNode parent = this.variableDeclaration.getParent();
+               while (parent != null && parent.getNodeType() != ASTNode.METHOD_DECLARATION) {
+                       parent = parent.getParent();
+               }
+               if (parent != null) {
+                       return ((MethodDeclaration) parent).resolveBinding();
+               }
+               return null;
+       }
+
+       public String getName() {
+               return this.variableDeclaration.getName().getIdentifier();
+       }
+
+       public ITypeBinding getType() {
+               return this.resolver.getTypeBinding(this.variableDeclaration);
+       }
+
+       public IVariableBinding getVariableDeclaration() {
+               return this;
+       }
+
+       public int getVariableId() {
+               return 0;
+       }
+
+       public boolean isEnumConstant() {
+               return false;
+       }
+
+       public boolean isField() {
+               return this.variableDeclaration.getParent() instanceof FieldDeclaration;
+       }
+
+       public boolean isParameter() {
+               return this.variableDeclaration instanceof SingleVariableDeclaration;
+       }
+
+       public IAnnotationBinding[] getAnnotations() {
+               return AnnotationBinding.NoAnnotations;
+       }
+
+       public IJavaElement getJavaElement() {
+               return null;
+       }
+
+       public String getKey() {
+               StringBuffer buffer = new StringBuffer();
+               buffer.append("Recovered#"); //$NON-NLS-1$
+               if (variableDeclaration != null) {
+                       buffer
+                               .append("variableDeclaration") //$NON-NLS-1$
+                               .append(this.variableDeclaration.getClass())
+                               .append(this.variableDeclaration.getName().getIdentifier())
+                               .append(this.variableDeclaration.getExtraDimensions());
+               }
+               return String.valueOf(buffer);
+       }
+
+       public int getKind() {
+               return IBinding.VARIABLE;
+       }
+
+       public int getModifiers() {
+               return 0;
+       }
+
+       public boolean isDeprecated() {
+               return false;
+       }
+
+       public boolean isEqualTo(IBinding binding) {
+               if (binding.isRecovered() && binding.getKind() == IBinding.VARIABLE) {
+                       return this.getKey().equals(binding.getKey());
+               }
+               return false;
+       }
+
+       public boolean isRecovered() {
+               return true;
+       }
+
+       public boolean isSynthetic() {
+               return false;
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ReturnStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ReturnStatement.java
new file mode 100644 (file)
index 0000000..ebaa825
--- /dev/null
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Return statement AST node type.
+ *
+ * <pre>
+ * ReturnStatement:
+ *    <b>return</b> [ Expression ] <b>;</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ReturnStatement extends Statement {
+                       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(ReturnStatement.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(ReturnStatement.class, propertyList);
+               addProperty(EXPRESSION_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 expression; <code>null</code> for none; defaults to none.
+        */
+       private Expression optionalExpression = null;
+       
+       /**
+        * Creates a new AST node for a return statement owned by the 
+        * given AST. By default, the statement has no expression.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ReturnStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) 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.
+        */
+       final int getNodeType0() {
+               return RETURN_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ReturnStatement result = new ReturnStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setExpression(
+                       (Expression) ASTNode.copySubtree(target, getExpression()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getExpression());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this return statement, or 
+        * <code>null</code> if there is none.
+        * 
+        * @return the expression node, or <code>null</code> if there is none
+        */ 
+       public Expression getExpression() {
+               return this.optionalExpression;
+       }
+       
+       /**
+        * Sets or clears the expression of this return statement.
+        * 
+        * @param expression the expression node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               ASTNode oldChild = this.optionalExpression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.optionalExpression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalExpression == null ? 0 : getExpression().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SimpleName.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SimpleName.java
new file mode 100644 (file)
index 0000000..0181e4d
--- /dev/null
@@ -0,0 +1,304 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * AST node for a simple name. A simple name is an identifier other than
+ * a keyword, boolean literal ("true", "false") or null literal ("null").
+ * <pre>
+ * SimpleName:
+ *     Identifier
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SimpleName extends Name {
+
+       /**
+        * The "identifier" structural property of this node type.
+        * 
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor IDENTIFIER_PROPERTY = 
+               new SimplePropertyDescriptor(SimpleName.class, "identifier", String.class, MANDATORY); //$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;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(SimpleName.class, propertyList);
+               addProperty(IDENTIFIER_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+       
+       /**
+        * 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 AST.JLS* constants
+        * @return a list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor})
+        * @since 3.0
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+       
+       /**
+        * An unspecified (but externally observable) legal Java identifier.
+        */
+       private static final String MISSING_IDENTIFIER = "MISSING";//$NON-NLS-1$
+       
+       /**
+        * The identifier; defaults to a unspecified, legal Java identifier.
+        */
+       private String identifier = MISSING_IDENTIFIER;
+       
+       /**
+        * Creates a new AST node for a simple name owned by the given AST.
+        * The new node has an unspecified, legal Java identifier.
+        * <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
+        */
+       SimpleName(AST ast) {
+               super(ast);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == IDENTIFIER_PROPERTY) {
+                       if (get) {
+                               return getIdentifier();
+                       } else {
+                               setIdentifier((String) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return SIMPLE_NAME;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               SimpleName result = new SimpleName(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setIdentifier(getIdentifier());
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+
+       /**
+        * Returns this node's identifier.
+        * 
+        * @return the identifier of this node
+        */ 
+       public String getIdentifier() {
+               return this.identifier;
+       }
+       
+       /**
+        * Sets the identifier of this node to the given value.
+        * The identifier should be legal according to the rules
+        * of the Java language. Note that keywords are not legal
+        * identifiers.
+        * <p>
+        * Note that the list of keywords may depend on the version of the
+        * language (determined when the AST object was created).
+        * </p>
+        * 
+        * @param identifier the identifier of this node
+        * @exception IllegalArgumentException if the identifier is invalid
+        */ 
+       public void setIdentifier(String identifier) {
+               // update internalSetIdentifier if this is changed
+               if (identifier == null) {
+                       throw new IllegalArgumentException();
+               }
+               Scanner scanner = this.ast.scanner;
+               char[] source = identifier.toCharArray();
+               scanner.setSource(source);
+               final int length = source.length;
+               scanner.resetTo(0, length - 1);
+               try {
+                       int tokenType = scanner.scanIdentifier();
+                       if (tokenType != TerminalTokens.TokenNameIdentifier) {
+                               throw new IllegalArgumentException();
+                       }
+                       if (scanner.currentPosition != length) {
+                               // this is the case when there is only one identifier see 87849
+                               throw new IllegalArgumentException();
+                       }
+               } catch(InvalidInputException e) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(IDENTIFIER_PROPERTY);
+               this.identifier = identifier;
+               postValueChange(IDENTIFIER_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * This method is a copy of setIdentifier(String) that doesn't do any validation.
+        */
+       void internalSetIdentifier(String ident) {
+               preValueChange(IDENTIFIER_PROPERTY);
+               this.identifier = ident;
+               postValueChange(IDENTIFIER_PROPERTY);
+       }
+       
+       /**
+        * Returns whether this simple name represents a name that is being defined,
+        * as opposed to one being referenced. The following positions are considered
+        * ones where a name is defined:
+        * <ul>
+        * <li>The type name in a <code>TypeDeclaration</code> node.</li>
+        * <li>The method name in a <code>MethodDeclaration</code> node
+        * providing <code>isConstructor</code> is <code>false</code>.</li>
+        * <li>The variable name in any type of <code>VariableDeclaration</code>
+        * node.</li>
+        * <li>The enum type name in a <code>EnumDeclaration</code> node.</li>
+        * <li>The enum constant name in an <code>EnumConstantDeclaration</code>
+        * node.</li>
+        * <li>The variable name in an <code>EnhancedForStatement</code>
+        * node.</li>
+        * <li>The type variable name in a <code>TypeParameter</code>
+        * node.</li>
+        * <li>The type name in an <code>AnnotationTypeDeclaration</code> node.</li>
+        * <li>The member name in an <code>AnnotationTypeMemberDeclaration</code> node.</li>
+        * </ul>
+        * <p>
+        * Note that this is a convenience method that simply checks whether
+        * this node appears in the declaration position relative to its parent.
+        * It always returns <code>false</code> if this node is unparented.
+        * </p>
+        * 
+        * @return <code>true</code> if this node declares a name, and 
+        *    <code>false</code> otherwise
+        */ 
+       public boolean isDeclaration() {
+               StructuralPropertyDescriptor d = getLocationInParent();
+               if (d == null) {
+                       // unparented node
+                       return false;
+               }
+               ASTNode parent = getParent();
+               if (parent instanceof TypeDeclaration) {
+                       return (d == TypeDeclaration.NAME_PROPERTY);
+               }
+               if (parent instanceof MethodDeclaration) {
+                       MethodDeclaration p = (MethodDeclaration) parent;
+                       // could be the name of the method or constructor
+                       return !p.isConstructor() && (d == MethodDeclaration.NAME_PROPERTY);
+               }
+               if (parent instanceof SingleVariableDeclaration) {
+                       return (d == SingleVariableDeclaration.NAME_PROPERTY);
+               }
+               if (parent instanceof VariableDeclarationFragment) {
+                       return (d == VariableDeclarationFragment.NAME_PROPERTY);
+               }
+               if (parent instanceof EnumDeclaration) {
+                       return (d == EnumDeclaration.NAME_PROPERTY);
+               }
+               if (parent instanceof EnumConstantDeclaration) {
+                       return (d == EnumConstantDeclaration.NAME_PROPERTY);
+               }
+               if (parent instanceof TypeParameter) {
+                       return (d == TypeParameter.NAME_PROPERTY);
+               }
+               if (parent instanceof AnnotationTypeDeclaration) {
+                       return (d == AnnotationTypeDeclaration.NAME_PROPERTY);
+               }
+               if (parent instanceof AnnotationTypeMemberDeclaration) {
+                       return (d == AnnotationTypeMemberDeclaration.NAME_PROPERTY);
+               }
+               return false;
+       }
+               
+       /* (omit javadoc for this method)
+        * Method declared on Name.
+        */
+       void appendName(StringBuffer buffer) {
+               buffer.append(getIdentifier());
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               int size = BASE_NAME_NODE_SIZE + 2 * 4;
+               if (identifier != MISSING_IDENTIFIER) {
+                       // everything but our missing id costs
+                       size += stringSize(identifier);
+               }
+               return size;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SimplePropertyDescriptor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SimplePropertyDescriptor.java
new file mode 100644 (file)
index 0000000..182163e
--- /dev/null
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Descriptor for a simple property of an AST node.
+ * A simple property is one whose value is a
+ * primitive type (such as <code>int</code> or <code>boolean</code>)
+ * or some simple value type (such as <code>String</code> or
+ * <code>InfixExpression.Operator</code>).
+ * 
+ * @see org.eclipse.jdt.core.dom.ASTNode#getStructuralProperty(StructuralPropertyDescriptor)
+ * @see org.eclipse.jdt.core.dom.ASTNode#setStructuralProperty(StructuralPropertyDescriptor, Object)
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class SimplePropertyDescriptor extends StructuralPropertyDescriptor {
+       
+       /**
+        * Value type. For example, for a node type like
+        * SingleVariableDeclaration, the modifiers property is int.class
+        */
+       private final Class valueType;
+       
+       /**
+        * Indicates whether a value is mandatory. A property value is allowed
+        * to be <code>null</code> only if it is not mandatory.
+        */
+       private final boolean mandatory;        
+       
+       /**
+        * Creates a new simple property descriptor with the given property id.
+        * Note that this constructor is declared package-private so that
+        * property descriptors can only be created by the AST
+        * implementation.
+        * 
+        * @param nodeClass concrete AST node type that owns this property
+        * @param propertyId the property id
+        * @param valueType the value type of this property
+        * @param mandatory <code>true</code> if the property is mandatory,
+        * and <code>false</code> if it is may be <code>null</code>
+        */
+       SimplePropertyDescriptor(Class nodeClass, String propertyId, Class valueType, boolean mandatory) {
+               super(nodeClass, propertyId);
+               if (valueType == null || ASTNode.class.isAssignableFrom(valueType)) {
+                       throw new IllegalArgumentException();
+               }
+               this.valueType = valueType;
+               this.mandatory = mandatory;
+       }
+       
+       /**
+        * Returns the value type of this property.
+        * <p>
+        * For example, for a node type like SingleVariableDeclaration,
+        * the "modifiers" property returns <code>int.class</code>.
+        * </p>
+        * 
+        * @return the value type of the property
+        */
+       public Class getValueType() {
+               return this.valueType;
+       }
+       
+       /**
+        * Returns whether this property is mandatory. A property value
+        * is not allowed to be <code>null</code> if it is mandatory.
+        * 
+        * @return <code>true</code> if the property is mandatory,
+        * and <code>false</code> if it is may be <code>null</code>
+        */
+       public boolean isMandatory() {
+               return this.mandatory;
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SimpleType.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SimpleType.java
new file mode 100644 (file)
index 0000000..3c83bf3
--- /dev/null
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for a named class type, a named interface type, or a type variable.
+ * <p>
+ * This kind of node is used to convert a name (<code>Name</code>) into a type
+ * (<code>Type</code>) by wrapping it.
+ * </p>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SimpleType extends Type {
+       
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(SimpleType.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(SimpleType.class, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 type name node; lazily initialized; defaults to a type with
+        * an unspecfied, but legal, name.
+        */
+       private Name typeName = null;
+       
+       /**
+        * Creates a new unparented node for a simple type owned by the given AST.
+        * By default, an unspecified, but legal, name.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       SimpleType(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((Name) 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.
+        */
+       final int getNodeType0() {
+               return SIMPLE_TYPE;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               SimpleType result = new SimpleType(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setName((Name) (getName()).clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getName());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the name of this simple type.
+        * 
+        * @return the name of this simple type
+        */ 
+       public Name getName() {
+               if (this.typeName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.typeName == null) {
+                                       preLazyInit();
+                                       this.typeName = new SimpleName(this.ast);
+                                       postLazyInit(this.typeName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.typeName;
+       }
+       
+       /**
+        * Sets the name of this simple type to the given name.
+        * 
+        * @param typeName the new name of this simple type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(Name typeName) {
+               if (typeName == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.typeName;
+               preReplaceChild(oldChild, typeName, NAME_PROPERTY);
+               this.typeName = typeName;
+               postReplaceChild(oldChild, typeName, NAME_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.typeName == null ? 0 : getName().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SingleMemberAnnotation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SingleMemberAnnotation.java
new file mode 100644 (file)
index 0000000..2d6c996
--- /dev/null
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Single member annotation node (added in JLS3 API). The single member annotation 
+ * "@foo(bar)" is equivalent to the normal annotation "@foo(value=bar)". 
+ * <p>
+ * <pre>
+ * SingleMemberAnnotation:
+ *   <b>@</b> TypeName <b>(</b> Expression  <b>)</b>
+ * </pre>
+ * Within annotations, only certain kinds of expressions are meaningful,
+ * including other annotations.
+ * </p>
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class SingleMemberAnnotation extends Annotation {
+       
+       /**
+        * The "typeName" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor TYPE_NAME_PROPERTY = 
+               internalTypeNamePropertyFactory(SingleMemberAnnotation.class);
+
+       /**
+        * The "value" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor VALUE_PROPERTY = 
+               new ChildPropertyDescriptor(SingleMemberAnnotation.class, "value", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(SingleMemberAnnotation.class, propertyList);
+               addProperty(TYPE_NAME_PROPERTY, propertyList);
+               addProperty(VALUE_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+       
+       /**
+        * 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 AST.JLS* constants
+        * @return a list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+       
+       /**
+        * The value; lazily initialized; defaults to a unspecified, but legal,
+        * expression.
+        */
+       private Expression value = null;
+
+       /**
+        * Creates a new unparented normal annotation node owned 
+        * by the given AST.  By default, the annotation has an
+        * unspecified type name and an unspecified value.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       SingleMemberAnnotation(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == TYPE_NAME_PROPERTY) {
+                       if (get) {
+                               return getTypeName();
+                       } else {
+                               setTypeName((Name) child);
+                               return null;
+                       }
+               }
+               if (property == VALUE_PROPERTY) {
+                       if (get) {
+                               return getValue();
+                       } else {
+                               setValue((Expression) child);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetChildProperty(property, get, child);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildPropertyDescriptor internalTypeNameProperty() {
+               return TYPE_NAME_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return SINGLE_MEMBER_ANNOTATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               SingleMemberAnnotation result = new SingleMemberAnnotation(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setTypeName((Name) ASTNode.copySubtree(target, getTypeName()));
+               result.setValue((Expression) ASTNode.copySubtree(target, getValue()));
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getTypeName());
+                       acceptChild(visitor, getValue());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the value of this annotation.
+        * 
+        * @return the value node
+        */ 
+       public Expression getValue() {
+               if (this.value == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.value == null) {
+                                       preLazyInit();
+                                       this.value = new SimpleName(this.ast);
+                                       postLazyInit(this.value, VALUE_PROPERTY);
+                               }
+                       }
+               }
+               return this.value;
+       }
+               
+       /**
+        * Sets the value of this annotation.
+        * 
+        * @param value the new value
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setValue(Expression value) {
+               if (value == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.value;
+               preReplaceChild(oldChild, value, VALUE_PROPERTY);
+               this.value = value;
+               postReplaceChild(oldChild, value, VALUE_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.typeName == null ? 0 : getTypeName().treeSize())
+                       + (this.value == null ? 0 : getValue().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SingleVariableDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SingleVariableDeclaration.java
new file mode 100644 (file)
index 0000000..3620347
--- /dev/null
@@ -0,0 +1,636 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Single variable declaration AST node type. Single variable
+ * declaration nodes are used in a limited number of places, including formal
+ * parameter lists and catch clauses. They are not used for field declarations
+ * and regular variable declaration statements.
+ * For JLS2:
+ * <pre>
+ * SingleVariableDeclaration:
+ *    { Modifier } Type Identifier { <b>[</b><b>]</b> } [ <b>=</b> Expression ]
+ * </pre>
+ * For JLS3, the modifier flags were replaced by
+ * a list of modifier nodes (intermixed with annotations), and the variable arity
+ * indicator was added:
+ * <pre>
+ * SingleVariableDeclaration:
+ *    { ExtendedModifier } Type [ <b>...</b> ] Identifier { <b>[</b><b>]</b> } [ <b>=</b> Expression ]
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SingleVariableDeclaration extends VariableDeclaration {
+       
+       /**
+        * The "modifiers" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor MODIFIERS_PROPERTY = 
+               new SimplePropertyDescriptor(SingleVariableDeclaration.class, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "modifiers" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
+               new ChildListPropertyDescriptor(SingleVariableDeclaration.class, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(SingleVariableDeclaration.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "type" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(SingleVariableDeclaration.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "varargs" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final SimplePropertyDescriptor VARARGS_PROPERTY = 
+               new SimplePropertyDescriptor(SingleVariableDeclaration.class, "varargs", boolean.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "extraDimensions" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor EXTRA_DIMENSIONS_PROPERTY = 
+               new SimplePropertyDescriptor(SingleVariableDeclaration.class, "extraDimensions", int.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "initializer" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor INITIALIZER_PROPERTY = 
+               new ChildPropertyDescriptor(SingleVariableDeclaration.class, "initializer", Expression.class, OPTIONAL, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List propertyList = new ArrayList(6);
+               createPropertyList(SingleVariableDeclaration.class, propertyList);
+               addProperty(MODIFIERS_PROPERTY, propertyList);
+               addProperty(TYPE_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+               addProperty(INITIALIZER_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+               
+               propertyList = new ArrayList(7);
+               createPropertyList(SingleVariableDeclaration.class, propertyList);
+               addProperty(MODIFIERS2_PROPERTY, propertyList);
+               addProperty(TYPE_PROPERTY, propertyList);
+               addProperty(VARARGS_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+               addProperty(INITIALIZER_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The extended modifiers (element type: <code>IExtendedModifier</code>). 
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * 
+        * @since 3.1
+        */
+       private ASTNode.NodeList modifiers = null;
+       
+       /**
+        * The modifiers; bit-wise or of Modifier flags.
+        * Defaults to none. Not used in 3.0.
+        */
+       private int modifierFlags = Modifier.NONE;
+       
+       /**
+        * The variable name; lazily initialized; defaults to a unspecified,
+        * legal Java identifier.
+        */
+       private SimpleName variableName = null;
+
+       /**
+        * The type; lazily initialized; defaults to a unspecified,
+        * legal type.
+        */
+       private Type type = null;
+
+       /**
+        * Indicates the last parameter of a variable arity method;
+        * defaults to false.
+        * 
+        * @since 3.1
+        */
+       private boolean variableArity = false;
+
+       /**
+        * The number of extra array dimensions that appear after the variable;
+        * defaults to 0.
+        * 
+        * @since 2.1
+        */
+       private int extraArrayDimensions = 0;
+
+       /**
+        * The initializer expression, or <code>null</code> if none;
+        * defaults to none.
+        */
+       private Expression optionalInitializer = null;
+
+       /**
+        * Creates a new AST node for a variable declaration owned by the given 
+        * AST. By default, the variable declaration has: no modifiers, an 
+        * unspecified (but legal) type, an unspecified (but legal) variable name, 
+        * 0 dimensions after the variable; no initializer; not variable arity.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       SingleVariableDeclaration(AST ast) {
+               super(ast);
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY);
+               }
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        * @since 3.1
+        */
+       final SimplePropertyDescriptor internalExtraDimensionsProperty() {
+               return EXTRA_DIMENSIONS_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        * @since 3.1
+        */
+       final ChildPropertyDescriptor internalInitializerProperty() {
+               return INITIALIZER_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        * @since 3.1
+        */
+       final ChildPropertyDescriptor internalNameProperty() {
+               return NAME_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+               if (property == MODIFIERS_PROPERTY) {
+                       if (get) {
+                               return getModifiers();
+                       } else {
+                               setModifiers(value);
+                               return 0;
+                       }
+               }
+               if (property == EXTRA_DIMENSIONS_PROPERTY) {
+                       if (get) {
+                               return getExtraDimensions();
+                       } else {
+                               setExtraDimensions(value);
+                               return 0;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetIntProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+               if (property == VARARGS_PROPERTY) {
+                       if (get) {
+                               return isVarargs();
+                       } else {
+                               setVarargs(value);
+                               return false;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetBooleanProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) child);
+                               return null;
+                       }
+               }
+               if (property == TYPE_PROPERTY) {
+                       if (get) {
+                               return getType();
+                       } else {
+                               setType((Type) child);
+                               return null;
+                       }
+               }
+               if (property == INITIALIZER_PROPERTY) {
+                       if (get) {
+                               return getInitializer();
+                       } else {
+                               setInitializer((Expression) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == MODIFIERS2_PROPERTY) {
+                       return modifiers();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return SINGLE_VARIABLE_DECLARATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               SingleVariableDeclaration result = new SingleVariableDeclaration(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                       result.setModifiers(getModifiers());
+               } else {
+                       result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+                       result.setVarargs(isVarargs());
+               }
+               result.setType((Type) getType().clone(target));
+               result.setExtraDimensions(getExtraDimensions());
+               result.setName((SimpleName) getName().clone(target));
+               result.setInitializer(
+                       (Expression) ASTNode.copySubtree(target, getInitializer()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChildren(visitor, this.modifiers);
+                       }
+                       acceptChild(visitor, getType());
+                       acceptChild(visitor, getName());
+                       acceptChild(visitor, getInitializer());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the live ordered list of modifiers and annotations
+        * of this declaration (added in JLS3 API).
+        * <p>
+        * Note that the final modifier is the only meaningful modifier for local
+        * variable and formal parameter declarations.
+        * </p>
+        * 
+        * @return the live list of modifiers and annotations
+        *    (element type: <code>IExtendedModifier</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public List modifiers() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.modifiers == null) {
+                       unsupportedIn2();
+               }
+               return this.modifiers;
+       }
+       
+       /**
+        * Returns the modifiers explicitly specified on this declaration.
+        * <p>
+        * In the JLS3 API, this method is a convenience method that
+        * computes these flags from <code>modifiers()</code>.
+        * </p>
+        * 
+        * @return the bit-wise or of <code>Modifier</code> constants
+        * @see Modifier
+        */ 
+       public int getModifiers() {
+               // more efficient than checking getAST().API_LEVEL
+               if (this.modifiers == null) {
+                       // JLS2 behavior - bona fide property
+                       return this.modifierFlags;
+               } else {
+                       // JLS3 behavior - convenient method
+                       // performance could be improved by caching computed flags
+                       // but this would require tracking changes to this.modifiers
+                       int computedModifierFlags = Modifier.NONE;
+                       for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+                               Object x = it.next();
+                               if (x instanceof Modifier) {
+                                       computedModifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+                               }
+                       }
+                       return computedModifierFlags;
+               }
+       }
+
+       /**
+        * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+        * <p>
+        * The following modifiers are meaningful for fields: public, private, protected,
+        * static, final, volatile, and transient. For local variable and formal
+        * parameter declarations, the only meaningful modifier is final.
+        * </p>
+        * 
+        * @param modifiers the given modifiers (bit-wise or of <code>Modifier</code> constants)
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @see Modifier
+        * @deprecated In the JLS3 API, this method is replaced by 
+        * {@link  #modifiers()} which contains a list of a <code>Modifier</code> nodes.
+        */ 
+       public void setModifiers(int modifiers) {
+               internalSetModifiers(modifiers);
+       }
+
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ final void internalSetModifiers(int pmodifiers) {
+           supportedOnlyIn2();
+               preValueChange(MODIFIERS_PROPERTY);
+               this.modifierFlags = pmodifiers;
+               postValueChange(MODIFIERS_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        */ 
+       public SimpleName getName() {
+               if (this.variableName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.variableName == null) {
+                                       preLazyInit();
+                                       this.variableName = new SimpleName(this.ast);
+                                       postLazyInit(this.variableName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.variableName;
+       }
+               
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        */ 
+       public void setName(SimpleName variableName) {
+               if (variableName == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.variableName;
+               preReplaceChild(oldChild, variableName, NAME_PROPERTY);
+               this.variableName = variableName;
+               postReplaceChild(oldChild, variableName, NAME_PROPERTY);
+       }
+
+       /**
+        * Returns the type of the variable declared in this variable declaration,
+        * exclusive of any extra array dimensions.
+        * 
+        * @return the type
+        */ 
+       public Type getType() {
+               if (this.type == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.type == null) {
+                                       preLazyInit();
+                                       this.type = this.ast.newPrimitiveType(PrimitiveType.INT);
+                                       postLazyInit(this.type, TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.type;
+       }
+
+       /**
+        * Sets the type of the variable declared in this variable declaration to 
+        * the given type, exclusive of any extra array dimensions.
+        * 
+        * @param type the new type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setType(Type type) {
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.type;
+               preReplaceChild(oldChild, type, TYPE_PROPERTY);
+               this.type = type;
+               postReplaceChild(oldChild, type, TYPE_PROPERTY);
+       }
+
+       /**
+        * Returns whether this declaration declares the last parameter of
+        * a variable arity method (added in JLS3 API).
+        * <p>
+        * Note that the binding for the type <code>Foo</code>in the vararg method
+        * declaration <code>void fun(Foo... args)</code> is always for the type as 
+        * written; i.e., the type binding for <code>Foo</code>. However, if you
+        * navigate from the method declaration to its method binding to the
+        * type binding for its last parameter, the type binding for the vararg
+        * parameter is always an array type (i.e., <code>Foo[]</code>) reflecting
+        * the way vararg methods get compiled.
+        * </p>
+        * 
+        * @return <code>true</code> if this is a variable arity parameter declaration,
+        *    and <code>false</code> otherwise
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public boolean isVarargs() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.modifiers == null) {
+                       unsupportedIn2();
+               }
+               return this.variableArity;
+       }
+       
+       /**
+        * Sets whether this declaration declares the last parameter of
+        * a variable arity method (added in JLS3 API).
+        * 
+        * @param variableArity <code>true</code> if this is a variable arity
+        *    parameter declaration, and <code>false</code> otherwise
+        * @since 3.1
+        */ 
+       public void setVarargs(boolean variableArity) {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.modifiers == null) {
+                       unsupportedIn2();
+               }
+               preValueChange(VARARGS_PROPERTY);
+               this.variableArity = variableArity;
+               postValueChange(VARARGS_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        * @since 2.1
+        */ 
+       public int getExtraDimensions() {
+               return this.extraArrayDimensions;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        * @since 2.1
+        */ 
+       public void setExtraDimensions(int dimensions) {
+               if (dimensions < 0) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(EXTRA_DIMENSIONS_PROPERTY);
+               this.extraArrayDimensions = dimensions;
+               postValueChange(EXTRA_DIMENSIONS_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        */ 
+       public Expression getInitializer() {
+               return this.optionalInitializer;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        */ 
+       public void setInitializer(Expression initializer) {
+               // a SingleVariableDeclaration may occur inside an Expression 
+               // must check cycles
+               ASTNode oldChild = this.optionalInitializer;
+               preReplaceChild(oldChild, initializer,INITIALIZER_PROPERTY);
+               this.optionalInitializer = initializer;
+               postReplaceChild(oldChild, initializer,INITIALIZER_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Operator as free
+               return BASE_NODE_SIZE + 7 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.modifiers == null ? 0 : this.modifiers.listSize())
+                       + (this.type == null ? 0 : getType().treeSize())
+                       + (this.variableName == null ? 0 : getName().treeSize())
+                       + (this.optionalInitializer == null ? 0 : getInitializer().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Statement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Statement.java
new file mode 100644 (file)
index 0000000..7416e3a
--- /dev/null
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * Abstract base class of AST nodes that represent statements.
+ * There are many kinds of statements.
+ * <p>
+ * The grammar combines both Statement and BlockStatement.
+ * For JLS2:
+ * <pre>
+ * Statement:
+ *    Block
+ *    IfStatement
+ *    ForStatement
+ *    WhileStatement
+ *    DoStatement
+ *    TryStatement
+ *    SwitchStatement
+ *    SynchronizedStatement
+ *    ReturnStatement
+ *    ThrowStatement
+ *    BreakStatement
+ *    ContinueStatement
+ *    EmptyStatement
+ *    ExpressionStatement
+ *    LabeledStatement
+ *    AssertStatement
+ *    VariableDeclarationStatement
+ *    TypeDeclarationStatement
+ *    ConstructorInvocation
+ *    SuperConstructorInvocation
+ * </pre>
+ * For JLS3, an enhanced for node type was added:
+ * <pre>
+ * Statement:
+ *    Block
+ *    IfStatement
+ *    ForStatement
+ *    EnhancedForStatement
+ *    WhileStatement
+ *    DoStatement
+ *    TryStatement
+ *    SwitchStatement
+ *    SynchronizedStatement
+ *    ReturnStatement
+ *    ThrowStatement
+ *    BreakStatement
+ *    ContinueStatement
+ *    EmptyStatement
+ *    ExpressionStatement
+ *    LabeledStatement
+ *    AssertStatement
+ *    VariableDeclarationStatement
+ *    TypeDeclarationStatement
+ *    ConstructorInvocation
+ *    SuperConstructorInvocation
+ * </pre>
+ * </p>
+ * 
+ * @since 2.0
+ */
+public abstract class Statement extends ASTNode {
+       
+       /**
+        * The leading comment, or <code>null</code> if none.
+        * Defaults to none.
+        * 
+        * @deprecated The leading comment feature was removed in 2.1.
+        */
+       private String optionalLeadingComment = null;
+       
+       /**
+        * Creates a new AST node for a statement owned by the given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       Statement(AST ast) {
+               super(ast);
+       }
+       
+       /**
+        * Returns the leading comment string, including the starting
+        * and ending comment delimiters, and any embedded line breaks.
+        * <p>
+        * A leading comment is a comment that appears before the statement.
+        * It may be either a traditional comment or an end-of-line comment.
+        * Traditional comments must begin with "/&#42;, may contain line breaks,
+        * and must end with "&#42;/. End-of-line comments must begin with "//",
+        * must end with a line delimiter (as per JLS 3.7), and must not contain
+        * line breaks.
+        * </p>
+        * 
+        * @return the comment string, or <code>null</code> if none
+        * @deprecated This feature was removed in the 2.1 release because it was
+        * only a partial, and inadequate, solution to the issue of associating
+        * comments with statements. Furthermore, AST.parseCompilationUnit did not
+        * associate leading comments, making this moot. Clients that need to access
+        * comments preceding a statement should either consult the compilation
+        * unit's {@linkplain CompilationUnit#getCommentList() comment table}
+        * or use a scanner to reanalyze the source text immediately preceding
+        * the statement's source range.
+        */
+       public String getLeadingComment() {
+               return optionalLeadingComment;
+       }
+
+       /**
+        * Sets or clears the leading comment string. The comment
+        * string must include the starting and ending comment delimiters,
+        * and any embedded linebreaks.
+        * <p>
+        * A leading comment is a comment that appears before the statement.
+        * It may be either a traditional comment or an end-of-line comment.
+        * Traditional comments must begin with "/&#42;, may contain line breaks,
+        * and must end with "&#42;/. End-of-line comments must begin with "//"
+        * (as per JLS 3.7), and must not contain line breaks.
+        * </p>
+        * <p>
+        * Examples:
+        * <code>
+        * <pre>
+        * setLeadingComment("/&#42; traditional comment &#42;/");  // correct
+        * setLeadingComment("missing comment delimiters");  // wrong
+        * setLeadingComment("/&#42; unterminated traditional comment ");  // wrong
+        * setLeadingComment("/&#42; broken\n traditional comment &#42;/");  // correct
+        * setLeadingComment("// end-of-line comment\n");  // correct
+        * setLeadingComment("// end-of-line comment without line terminator");  // correct
+        * setLeadingComment("// broken\n end-of-line comment\n");  // wrong
+        * </pre>
+        * </code>
+        * </p>
+        * 
+        * @param comment the comment string, or <code>null</code> if none
+        * @exception IllegalArgumentException if the comment string is invalid
+        * @deprecated This feature was removed in the 2.1 release because it was
+        * only a partial, and inadequate, solution to the issue of associating
+        * comments with statements.
+        */
+       public void setLeadingComment(String comment) {
+               if (comment != null) {
+                       char[] source = comment.toCharArray();
+                       Scanner scanner = this.ast.scanner;
+                       scanner.resetTo(0, source.length);
+                       scanner.setSource(source);
+                       try {
+                               int token;
+                               boolean onlyOneComment = false;
+                               while ((token = scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+                                       switch(token) {
+                                               case TerminalTokens.TokenNameCOMMENT_BLOCK :
+                                               case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+                                               case TerminalTokens.TokenNameCOMMENT_LINE :
+                                                       if (onlyOneComment) {
+                                                               throw new IllegalArgumentException();
+                                                       }
+                                                       onlyOneComment = true;
+                                                       break;
+                                               default:
+                                                       onlyOneComment = false;
+                                       }
+                               }
+                               if (!onlyOneComment) {
+                                       throw new IllegalArgumentException();
+                               }
+                       } catch (InvalidInputException e) {
+                               throw new IllegalArgumentException();
+                       }
+               }
+               // we do not consider the obsolete comment as a structureal property
+               // but we protect them nevertheless
+               checkModifiable();
+               this.optionalLeadingComment = comment;
+       }
+
+       /**
+        * Copies the leading comment from the given statement.
+        * 
+        * @param source the statement that supplies the leading comment
+        * @since 2.1
+        */
+       void copyLeadingComment(Statement source) {
+               setLeadingComment(source.getLeadingComment());
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               int size = BASE_NODE_SIZE + 1 * 4 + stringSize(getLeadingComment());
+               return size;
+       }
+}      
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/StringLiteral.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/StringLiteral.java
new file mode 100644 (file)
index 0000000..b393337
--- /dev/null
@@ -0,0 +1,345 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.TerminalTokens;
+
+/**
+ * String literal nodes.
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class StringLiteral extends Expression {
+
+       /**
+        * The "escapedValue" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor ESCAPED_VALUE_PROPERTY = 
+               new SimplePropertyDescriptor(StringLiteral.class, "escapedValue", String.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(StringLiteral.class, propertyList);
+               addProperty(ESCAPED_VALUE_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 literal string, including quotes and escapes; defaults to the 
+        * literal for the empty string.
+        */
+       private String escapedValue = "\"\"";//$NON-NLS-1$
+
+       /**
+        * Creates a new unparented string literal node owned by the given AST.
+        * By default, the string literal denotes the empty string.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       StringLiteral(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == ESCAPED_VALUE_PROPERTY) {
+                       if (get) {
+                               return getEscapedValue();
+                       } else {
+                               setEscapedValue((String) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return STRING_LITERAL;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               StringLiteral result = new StringLiteral(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setEscapedValue(getEscapedValue());
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the string value of this literal node to the given string
+        * literal token. The token is the sequence of characters that would appear
+        * in the source program, including enclosing double quotes and embedded
+        * escapes.
+        * 
+        * @return the string literal token, including enclosing double
+        *    quotes and embedded escapes
+        */ 
+       public String getEscapedValue() {
+               return this.escapedValue;
+       }
+               
+       /**
+        * Sets the string value of this literal node to the given string literal
+        * token. The token is the sequence of characters that would appear in the
+        * source program, including enclosing double quotes and embedded escapes.
+        * For example,
+        * <ul>
+        * <li><code>""</code> <code>setLiteral("\"\"")</code></li>
+        * <li><code>"hello world"</code> <code>setLiteral("\"hello world\"")</code></li>
+        * <li><code>"boo\nhoo"</code> <code>setLiteral("\"boo\\nhoo\"")</code></li>
+        * </ul>
+        * 
+        * @param token the string literal token, including enclosing double
+        *    quotes and embedded escapes
+        * @exception IllegalArgumentException if the argument is incorrect
+        */ 
+       public void setEscapedValue(String token) {
+               // update internalSetEscapedValue(String) if this is changed
+               if (token == null) {
+                       throw new IllegalArgumentException("Token cannot be null"); //$NON-NLS-1$
+               }
+               Scanner scanner = this.ast.scanner;
+               char[] source = token.toCharArray();
+               scanner.setSource(source);
+               scanner.resetTo(0, source.length);
+               try {
+                       int tokenType = scanner.getNextToken();
+                       switch(tokenType) {
+                               case TerminalTokens.TokenNameStringLiteral:
+                                       break;
+                               default:
+                                       throw new IllegalArgumentException("Invalid string literal : >" + token + "<"); //$NON-NLS-1$//$NON-NLS-2$
+                       }
+               } catch(InvalidInputException e) {
+                       throw new IllegalArgumentException("Invalid string literal : >" + token + "<");//$NON-NLS-1$//$NON-NLS-2$
+               }
+               preValueChange(ESCAPED_VALUE_PROPERTY);
+               this.escapedValue = token;
+               postValueChange(ESCAPED_VALUE_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * This method is a copy of setEscapedValue(String) that doesn't do any validation.
+        */
+       void internalSetEscapedValue(String token) {
+               preValueChange(ESCAPED_VALUE_PROPERTY);
+               this.escapedValue = token;
+               postValueChange(ESCAPED_VALUE_PROPERTY);
+       }
+
+       /**
+        * Returns the value of this literal node. 
+        * <p>
+        * For example,
+        * <pre>
+        * StringLiteral s;
+        * s.setEscapedValue("\"hello\\nworld\"");
+        * assert s.getLiteralValue().equals("hello\nworld");
+        * </pre>
+        * </p>
+        * <p>
+        * Note that this is a convenience method that converts from the stored 
+        * string literal token returned by <code>getEscapedLiteral</code>.
+        * </p>
+        * 
+        * @return the string value without enclosing double quotes and embedded
+        *    escapes
+        * @exception IllegalArgumentException if the literal value cannot be converted
+        */ 
+       public String getLiteralValue() {
+               String s = getEscapedValue();
+               int len = s.length();
+               if (len < 2 || s.charAt(0) != '\"' || s.charAt(len-1) != '\"' ) {
+                       throw new IllegalArgumentException();
+               }
+               
+               Scanner scanner = this.ast.scanner;
+               char[] source = s.toCharArray();
+               scanner.setSource(source);
+               scanner.resetTo(0, source.length);
+               try {
+                       int tokenType = scanner.getNextToken();
+                       switch(tokenType) {
+                               case TerminalTokens.TokenNameStringLiteral:
+                                       return scanner.getCurrentStringLiteral();
+                               default:
+                                       throw new IllegalArgumentException();
+                       }
+               } catch(InvalidInputException e) {
+                       throw new IllegalArgumentException();
+               }
+       }
+
+       /**
+        * Sets the value of this literal node. 
+        * <p>
+        * For example,
+        * <pre>
+        * StringLiteral s;
+        * s.setLiteralValue("hello\nworld");
+        * assert s.getEscapedValue("\"hello\\nworld\"");
+        * assert s.getLiteralValue().equals("hello\nworld");
+        * </pre>
+        * </p>
+        * <p>
+        * Note that this is a convenience method that converts to the stored 
+        * string literal token acceptable to <code>setEscapedLiteral</code>.
+        * </p>
+        * 
+        * @param value the string value without enclosing double quotes and 
+        *    embedded escapes
+        * @exception IllegalArgumentException if the argument is incorrect
+        */
+       public void setLiteralValue(String value) {
+               if (value == null) {
+                       throw new IllegalArgumentException();
+               }
+               int len = value.length();
+               StringBuffer b = new StringBuffer(len + 2);
+               
+               b.append("\""); // opening delimiter //$NON-NLS-1$
+               for (int i = 0; i < len; i++) {
+                       char c = value.charAt(i);
+                       switch(c) {
+                               case '\b' :
+                                       b.append("\\b"); //$NON-NLS-1$
+                                       break;
+                               case '\t' :
+                                       b.append("\\t"); //$NON-NLS-1$
+                                       break;
+                               case '\n' :
+                                       b.append("\\n"); //$NON-NLS-1$
+                                       break;
+                               case '\f' :
+                                       b.append("\\f"); //$NON-NLS-1$
+                                       break;
+                               case '\r' :
+                                       b.append("\\r"); //$NON-NLS-1$
+                                       break;
+                               case '\"':
+                                       b.append("\\\""); //$NON-NLS-1$
+                                       break;
+                               case '\'':
+                                       b.append("\\\'"); //$NON-NLS-1$
+                                       break;
+                               case '\\':
+                                       b.append("\\\\"); //$NON-NLS-1$
+                                       break;
+                               case '\0' :
+                                       b.append("\\0"); //$NON-NLS-1$
+                                       break;
+                               case '\1' :
+                                       b.append("\\1"); //$NON-NLS-1$
+                                       break;
+                               case '\2' :
+                                       b.append("\\2"); //$NON-NLS-1$
+                                       break;
+                               case '\3' :
+                                       b.append("\\3"); //$NON-NLS-1$
+                                       break;
+                               case '\4' :
+                                       b.append("\\4"); //$NON-NLS-1$
+                                       break;
+                               case '\5' :
+                                       b.append("\\5"); //$NON-NLS-1$
+                                       break;
+                               case '\6' :
+                                       b.append("\\6"); //$NON-NLS-1$
+                                       break;
+                               case '\7' :
+                                       b.append("\\7"); //$NON-NLS-1$
+                                       break;                  
+                               default:
+                                       b.append(c);
+                       }
+               }
+               b.append("\""); // closing delimiter //$NON-NLS-1$
+               setEscapedValue(b.toString());
+       }
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               int size = BASE_NODE_SIZE + 1 * 4 + stringSize(escapedValue);
+               return size;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/StructuralPropertyDescriptor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/StructuralPropertyDescriptor.java
new file mode 100644 (file)
index 0000000..a90cf39
--- /dev/null
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Abstract base class for property descriptors of AST nodes.
+ * There are three kinds of properties:
+ * <ul>
+ * <li>simple properties ({@link SimplePropertyDescriptor})
+ * - properties where the value is a primitive (int, boolean)
+ * or simple (String, InfixExprsssion.Operator) type other than an
+ * AST node; for example, the identifier of a {@link SimpleName}</li>
+ * <li>child properties ({@link ChildPropertyDescriptor})
+ * - properties whose value is another AST node;
+ * for example, the name of a {@link MethodDeclaration}</li>
+ * <li>child list properties ({@link ChildListPropertyDescriptor})
+ * - properties where the value is a list of AST nodes;
+ * for example, the statements of a {@link Block}</li>
+ * </ul>
+ * 
+ * @since 3.0
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public abstract class StructuralPropertyDescriptor {
+       
+       /**
+        * Property id.
+        */
+       private final String propertyId;
+       
+       /**
+        * The concrete AST node type that owns this property.
+        */
+       private final Class nodeClass;
+       
+       /**
+        * Creates a new property descriptor for the given node type
+        * with the given property id.
+        * Note that this constructor is declared package-private so that
+        * property descriptors can only be created by the AST
+        * implementation.
+        * 
+        * @param nodeClass concrete AST node type that owns this property
+        * @param propertyId the property id
+        */
+       StructuralPropertyDescriptor(Class nodeClass, String propertyId) {
+               if (nodeClass == null || propertyId == null) {
+                       throw new IllegalArgumentException();
+               }
+               this.propertyId = propertyId;
+               this.nodeClass = nodeClass;
+       }
+       
+       /**
+        * Returns the id of this property.
+        * 
+        * @return the property id
+        */
+       public final String getId() {
+               return this.propertyId;
+       }
+       
+       /**
+        * Returns the AST node type that owns this property.
+        * <p>
+        * For example, for all properties of the node type
+        * TypeDeclaration, this method returns <code>TypeDeclaration.class</code>.
+        * </p>
+        * 
+        * @return the node type that owns this property
+        */
+       public final Class getNodeClass() {
+               return this.nodeClass;
+       }
+       
+       /**
+        * Returns whether this property is a simple property
+        * (instance of {@link SimplePropertyDescriptor}.
+        * 
+        * @return <code>true</code> if this is a simple property, and 
+        * <code>false</code> otherwise
+        */
+       public final boolean isSimpleProperty(){
+               return (this instanceof SimplePropertyDescriptor);
+       }
+       
+       /**
+        * Returns whether this property is a child property
+        * (instance of {@link ChildPropertyDescriptor}.
+        * 
+        * @return <code>true</code> if this is a child property, and 
+        * <code>false</code> otherwise
+        */
+       public final boolean isChildProperty() {
+               return (this instanceof ChildPropertyDescriptor);
+       }
+       
+       /**
+        * Returns whether this property is a child list property
+        * (instance of {@link ChildListPropertyDescriptor}.
+        * 
+        * @return <code>true</code> if this is a child list property, and 
+        * <code>false</code> otherwise
+        */
+       public final boolean isChildListProperty() { 
+               return (this instanceof ChildListPropertyDescriptor);
+       }
+
+       /**
+        * Returns a string suitable for debug purposes.
+        * @return {@inheritDoc}
+        */
+       public String toString() {
+               StringBuffer b = new StringBuffer();
+               if (isChildListProperty()) {
+                       b.append("ChildList"); //$NON-NLS-1$
+               }
+               if (isChildProperty()) {
+                       b.append("Child"); //$NON-NLS-1$
+               }
+               if (isSimpleProperty()) {
+                       b.append("Simple"); //$NON-NLS-1$
+               }
+               b.append("Property["); //$NON-NLS-1$
+               if (this.nodeClass != null) {
+                       b.append(this.nodeClass.getName());
+               }
+               b.append(","); //$NON-NLS-1$
+               if (this.propertyId != null) {
+                       b.append(this.propertyId);
+               }
+               b.append("]"); //$NON-NLS-1$
+               return b.toString();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SuperConstructorInvocation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SuperConstructorInvocation.java
new file mode 100644 (file)
index 0000000..d53134f
--- /dev/null
@@ -0,0 +1,317 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Super constructor invocation statement AST node type.
+ * For JLS2: * <pre>
+ * SuperConstructorInvocation:
+ *     [ Expression <b>.</b> ] <b>super</b>
+ *         <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b> <b>;</b>
+ * </pre>
+ * For JLS3, type arguments are added:
+ * <pre>
+ * SuperConstructorInvocation:
+ *     [ Expression <b>.</b> ]
+ *         [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ *         <b>super</b> <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b> <b>;</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SuperConstructorInvocation extends Statement {
+       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(SuperConstructorInvocation.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "typeArguments" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(SuperConstructorInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "arguments" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(SuperConstructorInvocation.class, "arguments", Expression.class, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(SuperConstructorInvocation.class, propertyList);
+               addProperty(EXPRESSION_PROPERTY, propertyList);
+               addProperty(ARGUMENTS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+               
+               propertyList = new ArrayList(4);
+               createPropertyList(SuperConstructorInvocation.class, propertyList);
+               addProperty(EXPRESSION_PROPERTY, propertyList);
+               addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList);
+               addProperty(ARGUMENTS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The expression; <code>null</code> for none; defaults to none.
+        */
+       private Expression optionalExpression = null;
+       
+       /**
+        * The type arguments (element type: <code>Type</code>). 
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * @since 3.1
+        */
+       private ASTNode.NodeList typeArguments = null;
+
+       /**
+        * The list of argument expressions (element type: 
+        * <code>Expression</code>). Defaults to an empty list.
+        */
+       private ASTNode.NodeList arguments =
+               new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+       /**
+        * Creates a new AST node for an super constructor invocation statement
+        * owned by the given AST. By default, no type arguments, and an empty list
+        * of arguments.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       SuperConstructorInvocation(AST ast) {
+               super(ast);     
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+               }
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == ARGUMENTS_PROPERTY) {
+                       return arguments();
+               }
+               if (property == TYPE_ARGUMENTS_PROPERTY) {
+                       return typeArguments();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return SUPER_CONSTRUCTOR_INVOCATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               SuperConstructorInvocation result = new SuperConstructorInvocation(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setExpression(
+                       (Expression) ASTNode.copySubtree(target, getExpression()));
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+               }
+               result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getExpression());
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChildren(visitor, this.typeArguments);
+                       }
+                       acceptChildren(visitor, this.arguments);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this super constructor invocation statement,
+        * or <code>null</code> if there is none.
+        * 
+        * @return the expression node, or <code>null</code> if there is none
+        */ 
+       public Expression getExpression() {
+               return this.optionalExpression;
+       }
+       
+       /**
+        * Sets or clears the expression of this super constructor invocation
+        * statement.
+        * 
+        * @param expression the expression node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               ASTNode oldChild = this.optionalExpression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.optionalExpression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of type arguments of this constructor
+        * invocation (added in JLS3 API).
+        * 
+        * @return the live list of type arguments
+        *    (element type: <code>Type</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public List typeArguments() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.typeArguments == null) {
+                       unsupportedIn2();
+               }
+               return this.typeArguments;
+       }
+       
+       /**
+        * Returns the live ordered list of argument expressions in this super
+        * constructor invocation statement.
+        * 
+        * @return the live list of argument expressions 
+        *    (element type: <code>Expression</code>)
+        */ 
+       public List arguments() {
+               return this.arguments;
+       }
+
+       /**
+        * Resolves and returns the binding for the constructor invoked by this
+        * expression.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the constructor binding, or <code>null</code> if the binding
+        *    cannot be resolved
+        */     
+       public IMethodBinding resolveConstructorBinding() {
+               return this.ast.getBindingResolver().resolveConstructor(this);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize()
+               + (this.optionalExpression == null ? 0 : getExpression().treeSize())
+               + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+               + (this.arguments == null ? 0 : this.arguments.listSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SuperFieldAccess.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SuperFieldAccess.java
new file mode 100644 (file)
index 0000000..31e67a7
--- /dev/null
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple or qualified "super" field access expression AST node type.
+ *
+ * <pre>
+ * SuperFieldAccess:
+ *     [ ClassName <b>.</b> ] <b>super</b> <b>.</b> Identifier
+ * </pre>
+ * 
+ * <p>
+ * See <code>FieldAccess</code> for guidelines on handling other expressions
+ * that resemble qualified names.
+ * </p>
+ * 
+ * @see FieldAccess
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SuperFieldAccess extends Expression {
+
+       /**
+        * The "qualifier" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor QUALIFIER_PROPERTY = 
+               new ChildPropertyDescriptor(SuperFieldAccess.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(SuperFieldAccess.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(SuperFieldAccess.class, propertyList);
+               addProperty(QUALIFIER_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 optional qualifier; <code>null</code> for none; defaults to none.
+        */
+       private Name optionalQualifier = null;
+
+       /**
+        * The field; lazily initialized; defaults to an unspecified,
+        * but legal, simple field name.
+        */
+       private SimpleName fieldName = null;
+
+       /**
+        * Creates a new unparented node for a super field access expression owned
+        * by the given AST. By default, field name is an unspecified, but legal, 
+        * name, and there is no qualifier.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       SuperFieldAccess(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == QUALIFIER_PROPERTY) {
+                       if (get) {
+                               return getQualifier();
+                       } else {
+                               setQualifier((Name) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) 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.
+        */
+       final int getNodeType0() {
+               return SUPER_FIELD_ACCESS;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               SuperFieldAccess result = new SuperFieldAccess(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setName((SimpleName) ASTNode.copySubtree(target, getName()));
+               result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getQualifier());
+                       acceptChild(visitor, getName());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the qualifier of this "super" field access expression, or 
+        * <code>null</code> if there is none.
+        * 
+        * @return the qualifier name node, or <code>null</code> if there is none
+        */ 
+       public Name getQualifier() {
+               return this.optionalQualifier;
+       }
+       
+       /**
+        * Sets or clears the qualifier of this "super" field access expression.
+        * 
+        * @param name the qualifier name node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setQualifier(Name name) {
+               ASTNode oldChild = this.optionalQualifier;
+               preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+               this.optionalQualifier = name;
+               postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+       }
+
+       /**
+        * Returns the name of the field accessed in this "super" field access 
+        * expression.
+        * 
+        * @return the field name
+        */ 
+       public SimpleName getName() {
+               if (this.fieldName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.fieldName == null) {
+                                       preLazyInit();
+                                       this.fieldName = new SimpleName(this.ast);
+                                       postLazyInit(this.fieldName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.fieldName;
+       }
+
+       /**
+        * Resolves and returns the binding for the field accessed by this
+        * expression.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        *
+        * @return the variable binding, or <code>null</code> if the binding cannot
+        * be resolved
+        * @since 3.0
+        */
+       public IVariableBinding resolveFieldBinding() {
+               return this.ast.getBindingResolver().resolveField(this);
+       }
+               
+       /**
+        * Sets the name of the field accessed in this "super" field access 
+        * expression.
+        * 
+        * @param fieldName the field name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName fieldName) {
+               if (fieldName == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.fieldName;
+               preReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+               this.fieldName = fieldName;
+               postReplaceChild(oldChild, fieldName, NAME_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+                       + (this.fieldName == null ? 0 : getName().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SuperMethodInvocation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SuperMethodInvocation.java
new file mode 100644 (file)
index 0000000..a3c2aec
--- /dev/null
@@ -0,0 +1,397 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple or qualified "super" method invocation expression AST node type.
+ * For JLS2:
+ * <pre>
+ * SuperMethodInvocation:
+ *     [ ClassName <b>.</b> ] <b>super</b> <b>.</b> Identifier
+ *         <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ * </pre>
+ * For JLS3, type arguments are added:
+ * <pre>
+ * SuperMethodInvocation:
+ *     [ ClassName <b>.</b> ] <b>super</b> <b>.</b>
+ *         [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
+ *         Identifier <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
+ * </pre>
+ *
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SuperMethodInvocation extends Expression {
+
+       /**
+        * The "qualifier" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+               new ChildPropertyDescriptor(SuperMethodInvocation.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "typeArguments" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
+               new ChildListPropertyDescriptor(SuperMethodInvocation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY =
+               new ChildPropertyDescriptor(SuperMethodInvocation.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "arguments" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY =
+               new ChildListPropertyDescriptor(SuperMethodInvocation.class, "arguments", Expression.class, 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_2_0;
+
+       /**
+        * A list of property descriptors (element type:
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+
+       static {
+               List propertyList = new ArrayList(4);
+               createPropertyList(SuperMethodInvocation.class, propertyList);
+               addProperty(QUALIFIER_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               addProperty(ARGUMENTS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+
+               propertyList = new ArrayList(5);
+               createPropertyList(SuperMethodInvocation.class, propertyList);
+               addProperty(QUALIFIER_PROPERTY, propertyList);
+               addProperty(TYPE_ARGUMENTS_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               addProperty(ARGUMENTS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+
+       /**
+        * The optional qualifier; <code>null</code> for none; defaults to none.
+        */
+       private Name optionalQualifier = null;
+
+       /**
+        * The type arguments (element type: <code>Type</code>).
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * @since 3.1
+        */
+       private ASTNode.NodeList typeArguments = null;
+
+       /**
+        * The method name; lazily initialized; defaults to a unspecified,
+        * legal Java method name.
+        */
+       private SimpleName methodName = null;
+
+       /**
+        * The list of argument expressions (element type:
+        * <code>Expression</code>). Defaults to an empty list.
+        */
+       private ASTNode.NodeList arguments =
+               new ASTNode.NodeList(ARGUMENTS_PROPERTY);
+
+       /**
+        * Creates a new AST node for a "super" method invocation expression owned
+        * by the given AST. By default, no qualifier, no type arguments,
+        * an unspecified, but legal, method name, and an empty list of arguments.
+        *
+        * @param ast the AST that is to own this node
+        */
+       SuperMethodInvocation(AST ast) {
+               super(ast);
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
+               }
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == QUALIFIER_PROPERTY) {
+                       if (get) {
+                               return getQualifier();
+                       } else {
+                               setQualifier((Name) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == ARGUMENTS_PROPERTY) {
+                       return arguments();
+               }
+               if (property == TYPE_ARGUMENTS_PROPERTY) {
+                       return typeArguments();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return SUPER_METHOD_INVOCATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               SuperMethodInvocation result = new SuperMethodInvocation(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setName((SimpleName) getName().clone(target));
+               result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
+               }
+               result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getQualifier());
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChildren(visitor, this.typeArguments);
+                       }
+                       acceptChild(visitor, getName());
+                       acceptChildren(visitor, this.arguments);
+               }
+               visitor.endVisit(this);
+       }
+
+       /**
+        * Returns the qualifier of this "super" method invocation expression, or
+        * <code>null</code> if there is none.
+        *
+        * @return the qualifier name node, or <code>null</code> if there is none
+        */
+       public Name getQualifier() {
+               return this.optionalQualifier;
+       }
+
+       /**
+        * Returns true if the resolved return type has been inferred from the assignment context (JLS3 15.12.2.8), false otherwise.
+        * <p>
+        * This information is available only when bindings are requested when the AST is being built
+        * </p>.
+        *
+        * @return true if the resolved return type has been inferred from the assignment context (JLS3 15.12.2.8), false otherwise
+        * @since 3.3
+        */
+       public boolean isResolvedTypeInferredFromExpectedType() {
+               return this.ast.getBindingResolver().isResolvedTypeInferredFromExpectedType(this);
+       }
+
+
+       /**
+        * Sets or clears the qualifier of this "super" method invocation expression.
+        *
+        * @param name the qualifier name node, or <code>null</code> if
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */
+       public void setQualifier(Name name) {
+               ASTNode oldChild = this.optionalQualifier;
+               preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+               this.optionalQualifier = name;
+               postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of type arguments of this method
+        * invocation (added in JLS3 API).
+        *
+        * @return the live list of type arguments
+        *    (element type: <code>Type</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */
+       public List typeArguments() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.typeArguments == null) {
+                       unsupportedIn2();
+               }
+               return this.typeArguments;
+       }
+
+       /**
+        * Returns the name of the method invoked in this expression.
+        *
+        * @return the method name node
+        */
+       public SimpleName getName() {
+               if (this.methodName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.methodName == null) {
+                                       preLazyInit();
+                                       this.methodName = new SimpleName(this.ast);
+                                       postLazyInit(this.methodName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.methodName;
+       }
+
+       /**
+        * Sets the name of the method invoked in this expression to the
+        * given name.
+        *
+        * @param name the new method name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */
+       public void setName(SimpleName name) {
+               if (name == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.methodName;
+               preReplaceChild(oldChild, name, NAME_PROPERTY);
+               this.methodName = name;
+               postReplaceChild(oldChild, name, NAME_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of argument expressions in this
+        * "super" method invocation expression.
+        *
+        * @return the live list of argument expressions
+        *    (element type: <code>Expression</code>)
+        */
+       public List arguments() {
+               return this.arguments;
+       }
+
+       /**
+        * Resolves and returns the binding for the method invoked by this
+        * expression.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        *
+        * @return the method binding, or <code>null</code> if the binding cannot
+        * be resolved
+        * @since 2.1
+        */
+       public IMethodBinding resolveMethodBinding() {
+               return this.ast.getBindingResolver().resolveMethod(this);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 4 * 4;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalQualifier == null ? 0 : getQualifier().treeSize())
+                       + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
+                       + (this.methodName == null ? 0 : getName().treeSize())
+                       + (this.arguments == null ? 0 : this.arguments.listSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SwitchCase.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SwitchCase.java
new file mode 100644 (file)
index 0000000..ba6cd5c
--- /dev/null
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Switch case AST node type. A switch case is a special kind of node used only
+ * in switch statements. It is a <code>Statement</code> in name only.
+ * <p>
+ * <pre>
+ * SwitchCase:
+ *             <b>case</b> Expression  <b>:</b>
+ *             <b>default</b> <b>:</b>
+ * </pre>
+ * </p>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SwitchCase extends Statement {
+       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(SwitchCase.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(SwitchCase.class, propertyList);
+               addProperty(EXPRESSION_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 expression; <code>null</code> for none; lazily initialized (but
+        * does <b>not</b> default to none).
+        * @see #expressionInitialized
+        */
+       private Expression optionalExpression = null;
+
+       /**
+        * Indicates whether <code>optionalExpression</code> has been initialized.
+        */
+       private boolean expressionInitialized = false;
+       
+       /**
+        * Creates a new AST node for a switch case pseudo-statement owned by the 
+        * given AST. By default, there is an unspecified, but legal, expression.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       SwitchCase(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) 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.
+        */
+       final int getNodeType0() {
+               return SWITCH_CASE;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               SwitchCase result = new SwitchCase(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setExpression(
+                       (Expression) ASTNode.copySubtree(target, getExpression()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getExpression());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this switch case, or 
+        * <code>null</code> if there is none (the "default:" case).
+        * 
+        * @return the expression node, or <code>null</code> if there is none
+        */ 
+       public Expression getExpression() {
+               if (!this.expressionInitialized) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (!this.expressionInitialized) {
+                                       preLazyInit();
+                                       this.optionalExpression = new SimpleName(this.ast);
+                                       this.expressionInitialized = true;
+                                       postLazyInit(this.optionalExpression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.optionalExpression;
+       }
+       
+       /**
+        * Sets the expression of this switch case, or clears it (turns it into
+        * the  "default:" case).
+        * 
+        * @param expression the expression node, or <code>null</code> to 
+        *    turn it into the  "default:" case
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               ASTNode oldChild = this.optionalExpression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.optionalExpression = expression;
+               this.expressionInitialized = true;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns whether this switch case represents the "default:" case.
+        * <p>
+        * This convenience method is equivalent to
+        * <code>getExpression() == null</code>.
+        * </p>
+        * 
+        * @return <code>true</code> if this is the default switch case, and
+        *    <code>false</code> if this is a non-default switch case
+        */ 
+       public boolean isDefault()  {
+               return getExpression() == null;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.optionalExpression == null ? 0 : optionalExpression.treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SwitchStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SwitchStatement.java
new file mode 100644 (file)
index 0000000..e9116f0
--- /dev/null
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Switch statement AST node type.
+ * <p>
+ * <pre>
+ * SwitchStatement:
+ *             <b>switch</b> <b>(</b> Expression <b>)</b> 
+ *                     <b>{</b> { SwitchCase | Statement } } <b>}</b>
+ * SwitchCase:
+ *             <b>case</b> Expression  <b>:</b>
+ *             <b>default</b> <b>:</b>
+ * </pre>
+ * <code>SwitchCase</code> nodes are treated as a kind of
+ * <code>Statement</code>.
+ * </p>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SwitchStatement extends Statement {
+                       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(SwitchStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "statements" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor STATEMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(SwitchStatement.class, "statements", Statement.class, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(SwitchStatement.class, propertyList);
+               addProperty(EXPRESSION_PROPERTY, propertyList);
+               addProperty(STATEMENTS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 expression; lazily initialized; defaults to a unspecified, but legal,
+        * expression.
+        */
+       private Expression expression = null;
+
+       /**
+        * The statements and SwitchCase nodes
+        * (element type: <code>Statement</code>).
+        * Defaults to an empty list.
+        */
+       private ASTNode.NodeList statements =
+               new ASTNode.NodeList(STATEMENTS_PROPERTY);
+       
+       /**
+        * Creates a new unparented switch statement node owned by the given 
+        * AST. By default, the swicth statement has an unspecified, but legal,
+        * expression, and an empty list of switch groups.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       SwitchStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == STATEMENTS_PROPERTY) {
+                       return statements();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return SWITCH_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               SwitchStatement result = new SwitchStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setExpression((Expression) getExpression().clone(target));
+               result.statements().addAll(ASTNode.copySubtrees(target, statements()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getExpression());
+                       acceptChildren(visitor, this.statements);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this switch statement.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new SimpleName(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.expression;
+       }
+               
+       /**
+        * Sets the expression of this switch statement.
+        * 
+        * @param expression the new expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+       
+       /**
+        * Returns the live ordered list of statements for this switch statement.
+        * Within this list, <code>SwitchCase</code> nodes mark the start of 
+        * the switch groups.
+        * 
+        * @return the live list of statement nodes
+        *    (element type: <code>Statement</code>)
+        */ 
+       public List statements() {
+               return this.statements;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.expression == null ? 0 : getExpression().treeSize())
+                       + this.statements.listSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SynchronizedStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/SynchronizedStatement.java
new file mode 100644 (file)
index 0000000..bd96786
--- /dev/null
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Synchronized statement AST node type.
+ *
+ * <pre>
+ * SynchronizedStatement:
+ *    <b>synchronized</b> <b>(</b> Expression <b>)</b> Block
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class SynchronizedStatement extends Statement {
+
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(SynchronizedStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "body" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor BODY_PROPERTY = 
+               new ChildPropertyDescriptor(SynchronizedStatement.class, "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(SynchronizedStatement.class, propertyList);
+               addProperty(EXPRESSION_PROPERTY, propertyList);
+               addProperty(BODY_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 expression; lazily initialized; defaults to an unspecified, but 
+        * legal, expression.
+        */
+       private Expression expression = null;
+
+       /**
+        * The body; lazily initialized; defaults to an empty block.
+        */
+       private Block body = null;
+
+       /**
+        * Creates a new unparented synchronized statement node owned by the given 
+        * AST. By default, the expression is unspecified, but legal, and the
+        * blody is an empty block.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       SynchronizedStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == BODY_PROPERTY) {
+                       if (get) {
+                               return getBody();
+                       } else {
+                               setBody((Block) 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.
+        */
+       final int getNodeType0() {
+               return SYNCHRONIZED_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               SynchronizedStatement result = new SynchronizedStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setExpression((Expression) getExpression().clone(target));
+               result.setBody((Block) getBody().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getExpression());
+                       acceptChild(visitor, getBody());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this synchronized statement.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new SimpleName(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.expression;
+       }
+       
+       /**
+        * Sets the expression of this synchronized statement.
+        * 
+        * @param expression the expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the body of this synchronized statement.
+        * 
+        * @return the body block node
+        */ 
+       public Block getBody() {
+               if (this.body == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.body == null) {
+                                       preLazyInit();
+                                       this.body = new Block(this.ast);
+                                       postLazyInit(this.body, BODY_PROPERTY);
+                               }
+                       }
+               }
+               return this.body;
+       }
+       
+       /**
+        * Sets the body of this synchronized statement.
+        * 
+        * @param block the body statement node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setBody(Block block) {
+               if (block == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.body;
+               preReplaceChild(oldChild, block, BODY_PROPERTY);
+               this.body = block;
+               postReplaceChild(oldChild, block, BODY_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.expression == null ? 0 : getExpression().treeSize())
+                       + (this.body == null ? 0 : getBody().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TagElement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TagElement.java
new file mode 100644 (file)
index 0000000..e3d8182
--- /dev/null
@@ -0,0 +1,400 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AST node for a tag within a doc comment.
+ * Tag elements nested within another tag element are called
+ * inline doc tags.
+ * <pre>
+ * TagElement:
+ *     [ <b>@</b> Identifier ] { DocElement }
+ * DocElement:
+ *     TextElement
+ *     Name
+ *     MethodRef
+ *     MemberRef
+ *     <b>{</b> TagElement <b>}</b>
+ * </pre>
+ * 
+ * @see Javadoc
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class TagElement extends ASTNode implements IDocElement {
+
+       /**
+        * The "tagName" structural property of this node type.
+        * 
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor TAG_NAME_PROPERTY = 
+               new SimplePropertyDescriptor(TagElement.class, "tagName", String.class, OPTIONAL); //$NON-NLS-1$
+       
+       /**
+        * The "fragments" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(TagElement.class, "fragments", IDocElement.class, 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;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(TagElement.class, propertyList);
+               addProperty(TAG_NAME_PROPERTY, propertyList);
+               addProperty(FRAGMENTS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+       
+       /**
+        * 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;
+       }
+       
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_AUTHOR = "@author"; //$NON-NLS-1$
+
+       /**
+        * Standard inline doc tag name (value {@value}).
+        * <p>
+        * Note that this tag first appeared in J2SE 5.
+        * </p>
+        * @since 3.1
+        */
+       public static final String TAG_CODE = "@code"; //$NON-NLS-1$
+
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_DEPRECATED = "@deprecated"; //$NON-NLS-1$
+
+       /**
+        * Standard inline doc tag name (value {@value}).
+        */
+       public static final String TAG_DOCROOT = "@docRoot"; //$NON-NLS-1$
+
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_EXCEPTION = "@exception"; //$NON-NLS-1$
+
+       /**
+        * Standard inline doc tag name (value {@value}).
+        */
+       public static final String TAG_INHERITDOC = "@inheritDoc"; //$NON-NLS-1$
+
+       /**
+        * Standard inline doc tag name (value {@value}).
+        */
+       public static final String TAG_LINK = "@link"; //$NON-NLS-1$
+
+       /**
+        * Standard inline doc tag name (value {@value}).
+        */
+       public static final String TAG_LINKPLAIN = "@linkplain"; //$NON-NLS-1$
+
+       /**
+        * Standard inline doc tag name (value {@value}).
+        * <p>
+        * Note that this tag first appeared in J2SE 5.
+        * </p>
+        * @since 3.1
+        */
+       public static final String TAG_LITERAL = "@literal"; //$NON-NLS-1$
+
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_PARAM = "@param"; //$NON-NLS-1$
+
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_RETURN = "@return"; //$NON-NLS-1$
+
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_SEE = "@see"; //$NON-NLS-1$
+
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_SERIAL = "@serial"; //$NON-NLS-1$
+
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_SERIALDATA= "@serialData"; //$NON-NLS-1$
+
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_SERIALFIELD= "@serialField"; //$NON-NLS-1$
+
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_SINCE = "@since"; //$NON-NLS-1$
+
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_THROWS = "@throws"; //$NON-NLS-1$
+
+       /**
+        * Standard inline doc tag name (value {@value}).
+        */
+       public static final String TAG_VALUE= "@value"; //$NON-NLS-1$
+
+       /**
+        * Standard doc tag name (value {@value}).
+        */
+       public static final String TAG_VERSION = "@version"; //$NON-NLS-1$
+
+       /**
+        * The tag name, or null if none; defaults to null.
+        */
+       private String optionalTagName = null;
+       
+       /**
+        * The list of doc elements (element type: <code>IDocElement</code>). 
+        * Defaults to an empty list.
+        */
+       private ASTNode.NodeList fragments = 
+               new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+       /**
+        * Creates a new AST node for a tag element owned by the given AST.
+        * The new node has no name and an empty list of fragments.
+        * <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
+        */
+       TagElement(AST ast) {
+               super(ast);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == TAG_NAME_PROPERTY) {
+                       if (get) {
+                               return getTagName();
+                       } else {
+                               setTagName((String) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == FRAGMENTS_PROPERTY) {
+                       return fragments();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return TAG_ELEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               TagElement result = new TagElement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setTagName(getTagName());
+               result.fragments().addAll(ASTNode.copySubtrees(target, fragments()));
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChildren(visitor, this.fragments);
+               }
+               visitor.endVisit(this);
+       }
+
+       /**
+        * Returns this node's tag name, or <code>null</code> if none.
+        * For top level doc tags such as parameter tags, the tag name
+     * includes the "@" character ("@param").
+        * For inline doc tags such as link tags, the tag name
+     * includes the "@" character ("@link").
+     * The tag name may also be <code>null</code>; this is used to
+     * represent the material at the start of a doc comment preceding
+     * the first explicit tag.
+     *
+        * @return the tag name, or <code>null</code> if none
+        */ 
+       public String getTagName() {
+               return this.optionalTagName;
+       }
+       
+       /**
+        * Sets the tag name of this node to the given value.
+        * For top level doc tags such as parameter tags, the tag name
+        * includes the "@" character ("@param").
+        * For inline doc tags such as link tags, the tag name
+        * includes the "@" character ("@link").
+        * The tag name may also be <code>null</code>; this is used to
+        * represent the material at the start of a doc comment preceding
+        * the first explicit tag.
+        *
+        * @param tagName the tag name, or <code>null</code> if none
+        */ 
+       public void setTagName(String tagName) {
+               preValueChange(TAG_NAME_PROPERTY);
+               this.optionalTagName = tagName;
+               postValueChange(TAG_NAME_PROPERTY);
+       }
+               
+       /**
+        * Returns the live list of fragments in this tag element. 
+        * <p>
+        * The fragments cover everything following the tag name
+        * (or everything if there is no tag name), and generally omit
+        * embedded line breaks (and leading whitespace on new lines,
+        * including any leading "*"). {@link org.eclipse.jdt.core.dom.TagElement}
+        * nodes are used to represent tag elements (e.g., "@link")
+        * nested within this tag element. 
+        * </p>
+        * <p>
+        * Here are some typical examples:
+        * <ul>
+        * <li>"@see Foo#bar()" - TagElement with tag name "@see";
+        * fragments() contains a single MethodRef node</li>
+        * <li>"@param args the program arguments" -
+        * TagElement with tag name "@param";
+        * 2 fragments: SimpleName ("args"), TextElement
+        * (" the program arguments")</li>
+        * <li>"@return See {&#64;link #foo foo} instead." - 
+        * TagElement with tag name "@return";
+        * 3 fragments: TextElement ("See "),
+        * TagElement (for "&#64;link #foo foo"),
+        * TextElement (" instead.")</li>
+        * </ul>
+        * The use of Name, MethodRef, and MemberRef nodes within
+        * tag elements allows these fragments to be queried for
+        * binding information.
+        * </p>
+        * <p>
+        * Adding and removing nodes from this list affects this node
+        * dynamically. The nodes in this list may be of various
+        * types, including {@link TextElement}, 
+        * {@link org.eclipse.jdt.core.dom.TagElement}, {@link Name}, 
+        * {@link MemberRef}, and {@link MethodRef}.
+        * Clients should assume that the list of types may grow in
+        * the future, and write their code to deal with unexpected
+        * nodes types. However, attempts to add a non-proscribed type
+        * of node will trigger an exception.
+        * 
+        * @return the live list of doc elements in this tag element
+        * (element type: <code>ASTNode</code>)
+        */ 
+       public List fragments() {
+               return this.fragments;
+       }
+
+       /**
+        * Returns whether this tag element is nested within another
+        * tag element. Nested tag elements appears enclosed in 
+        * "{" and "}"; certain doc tags, including "@link" and
+        * "@linkplain" are only meaningful as nested tags.
+        * Top-level (i.e., non-nested) doc tags begin on a new line;
+        * certain doc tags, including "@param" and
+        * "@see" are only meaningful as top-level tags.
+        * <p>
+        * This convenience methods checks to see whether the parent
+        * of this node is of type {@link org.eclipse.jdt.core.dom.TagElement}.
+        * </p>
+        * 
+        * @return <code>true</code> if this node is a nested tag element,
+        * and false if this node is either parented by a doc comment node
+        * ({@link Javadoc}), or is unparented
+        */
+       public boolean isNested() {
+               return (getParent() instanceof TagElement);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               int size = BASE_NODE_SIZE + 2 * 4 + stringSize(this.optionalTagName);
+               return size;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize() + this.fragments.listSize();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TextElement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TextElement.java
new file mode 100644 (file)
index 0000000..d30e9e8
--- /dev/null
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+
+/**
+ * AST node for a text element within a doc comment.
+ * <pre>
+ * TextElement:
+ *     Sequence of characters not including a close comment delimiter <b>*</b><b>/</b>
+ * </pre>
+ * 
+ * @see Javadoc
+ * @since 3.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public final class TextElement extends ASTNode implements IDocElement {
+
+       /**
+        * The "text" structural property of this node type.
+        * 
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor TEXT_PROPERTY = 
+               new SimplePropertyDescriptor(TextElement.class, "text", String.class, MANDATORY); //$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;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(TextElement.class, propertyList);
+               addProperty(TEXT_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+       
+       /**
+        * 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 text element; defaults to the empty string.
+        */
+       private String text = Util.EMPTY_STRING;
+       
+       /**
+        * Creates a new AST node for a text element owned by the given AST.
+        * The new node has an empty text string.
+        * <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
+        */
+       TextElement(AST ast) {
+               super(ast);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
+               if (property == TEXT_PROPERTY) {
+                       if (get) {
+                               return getText();
+                       } else {
+                               setText((String) value);
+                               return null;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetObjectProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return TEXT_ELEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               TextElement result = new TextElement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setText(getText());
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               visitor.visit(this);
+               visitor.endVisit(this);
+       }
+
+       /**
+        * Returns this node's text.
+        * 
+        * @return the text of this node
+        */ 
+       public String getText() {
+               return this.text;
+       }
+       
+       /**
+        * Sets the text of this node to the given value.
+        * <p>
+        * The text element typically includes leading and trailing
+        * whitespace that separates it from the immediately preceding
+        * or following elements. The text element must not include
+        * a block comment closing delimiter "*"+"/".
+        * </p>
+        * 
+        * @param text the text of this node
+        * @exception IllegalArgumentException if the text is null
+        * or contains a block comment closing delimiter
+        */ 
+       public void setText(String text) {
+               if (text == null) {
+                       throw new IllegalArgumentException();
+               }
+               if (text.indexOf("*/") > 0) { //$NON-NLS-1$
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(TEXT_PROPERTY);
+               this.text = text;
+               postValueChange(TEXT_PROPERTY);
+       }
+               
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               int size = BASE_NODE_SIZE + 1 * 4;
+               if (this.text != Util.EMPTY_STRING) {
+                       // everything but our empty string costs
+                       size += stringSize(this.text);
+               }
+               return size;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ThisExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ThisExpression.java
new file mode 100644 (file)
index 0000000..c51431a
--- /dev/null
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Simple or qualified "this" AST node type.
+ *
+ * <pre>
+ * ThisExpression:
+ *     [ ClassName <b>.</b> ] <b>this</b>
+ * </pre>
+ * <p>
+ * See <code>FieldAccess</code> for guidelines on handling other expressions
+ * that resemble qualified names.
+ * </p>
+ * 
+ * @see FieldAccess
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ThisExpression extends Expression {
+                       
+       /**
+        * The "qualifier" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor QUALIFIER_PROPERTY = 
+               new ChildPropertyDescriptor(ThisExpression.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(ThisExpression.class, propertyList);
+               addProperty(QUALIFIER_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 optional qualifier; <code>null</code> for none; defaults to none.
+        */
+       private Name optionalQualifier = null;
+
+       /**
+        * Creates a new AST node for a "this" expression owned by the 
+        * given AST. By default, there is no qualifier.
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ThisExpression(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == QUALIFIER_PROPERTY) {
+                       if (get) {
+                               return getQualifier();
+                       } else {
+                               setQualifier((Name) 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.
+        */
+       final int getNodeType0() {
+               return THIS_EXPRESSION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ThisExpression result = new ThisExpression(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setQualifier((Name) ASTNode.copySubtree(target, getQualifier()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getQualifier());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the qualifier of this "this" expression, or 
+        * <code>null</code> if there is none.
+        * 
+        * @return the qualifier name node, or <code>null</code> if there is none
+        */ 
+       public Name getQualifier() {
+               return this.optionalQualifier;
+       }
+       
+       /**
+        * Sets or clears the qualifier of this "this" expression.
+        * 
+        * @param name the qualifier name node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setQualifier(Name name) {
+               ASTNode oldChild = this.optionalQualifier;
+               preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+               this.optionalQualifier = name;
+               postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Operator as free
+               return BASE_NODE_SIZE + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.optionalQualifier == null ? 0 : getQualifier().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ThrowStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/ThrowStatement.java
new file mode 100644 (file)
index 0000000..01fa197
--- /dev/null
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Throw statement AST node type.
+ *
+ * <pre>
+ * ThrowStatement:
+ *    <b>throw</b> Expression <b>;</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class ThrowStatement extends Statement {
+                       
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(ThrowStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(ThrowStatement.class, propertyList);
+               addProperty(EXPRESSION_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 expression; lazily initialized; defaults to a unspecified, but legal,
+        * expression.
+        */
+       private Expression expression = null;
+
+       /**
+        * Creates a new unparented throw statement node owned by the given 
+        * AST. By default, the throw statement has an unspecified, but legal,
+        * expression.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       ThrowStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) 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.
+        */
+       final int getNodeType0() {
+               return THROW_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               ThrowStatement result = new ThrowStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setExpression((Expression) getExpression().clone(target));
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getExpression());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this throw statement.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new SimpleName(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.expression;
+       }
+               
+       /**
+        * Sets the expression of this throw statement.
+        * 
+        * @param expression the new expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.expression == null ? 0 : getExpression().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TryStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TryStatement.java
new file mode 100644 (file)
index 0000000..c12a904
--- /dev/null
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Try statement AST node type.
+ *
+ * <pre>
+ * TryStatement:
+ *     <b>try</b> Block 
+ *         { CatchClause }
+ *         [ <b>finally</b> Block ]
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class TryStatement extends Statement {
+       
+       /**
+        * The "body" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor BODY_PROPERTY = 
+               new ChildPropertyDescriptor(TryStatement.class, "body", Block.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "catchClauses" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor CATCH_CLAUSES_PROPERTY = 
+               new ChildListPropertyDescriptor(TryStatement.class, "catchClauses", CatchClause.class, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "finally" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor FINALLY_PROPERTY = 
+               new ChildPropertyDescriptor(TryStatement.class, "finally", Block.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(4);
+               createPropertyList(TryStatement.class, propertyList);
+               addProperty(BODY_PROPERTY, propertyList);
+               addProperty(CATCH_CLAUSES_PROPERTY, propertyList);
+               addProperty(FINALLY_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 body; lazily initialized; defaults to an empty block.
+        */
+       private Block body = null;
+
+       /**
+        * The catch clauses (element type: <code>CatchClause</code>).
+        * Defaults to an empty list.
+        */
+       private ASTNode.NodeList catchClauses =
+               new ASTNode.NodeList(CATCH_CLAUSES_PROPERTY);
+       
+       /**
+        * The finally block, or <code>null</code> if none.
+        * Defaults to none.
+        */
+       private Block optionalFinallyBody = null;
+
+                       
+       /**
+        * Creates a new AST node for a try statement owned by the given 
+        * AST. By default, the try statement has an empty block, no catch
+        * clauses, and no finally block.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       TryStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == BODY_PROPERTY) {
+                       if (get) {
+                               return getBody();
+                       } else {
+                               setBody((Block) child);
+                               return null;
+                       }
+               }
+               if (property == FINALLY_PROPERTY) {
+                       if (get) {
+                               return getFinally();
+                       } else {
+                               setFinally((Block) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == CATCH_CLAUSES_PROPERTY) {
+                       return catchClauses();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return TRY_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               TryStatement result = new TryStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setBody((Block) getBody().clone(target));
+               result.catchClauses().addAll(
+                       ASTNode.copySubtrees(target, catchClauses()));
+               result.setFinally(
+                       (Block) ASTNode.copySubtree(target, getFinally()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getBody());
+                       acceptChildren(visitor, this.catchClauses);
+                       acceptChild(visitor, getFinally());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the body of this try statement.
+        * 
+        * @return the try body
+        */ 
+       public Block getBody() {
+               if (this.body == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.body == null) {
+                                       preLazyInit();
+                                       this.body = new Block(this.ast);
+                                       postLazyInit(this.body, BODY_PROPERTY);
+                               }
+                       }
+               }
+               return this.body;
+       }
+       
+       /**
+        * Sets the body of this try statement.
+        * 
+        * @param body the block node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setBody(Block body) {
+               if (body == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.body;
+               preReplaceChild(oldChild, body, BODY_PROPERTY);
+               this.body = body;
+               postReplaceChild(oldChild, body, BODY_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of catch clauses for this try statement.
+        * 
+        * @return the live list of catch clauses
+        *    (element type: <code>CatchClause</code>)
+        */ 
+       public List catchClauses() {
+               return this.catchClauses;
+       }
+               
+       /**
+        * Returns the finally block of this try statement, or <code>null</code> if 
+        * this try statement has <b>no</b> finally block.
+        * 
+        * @return the finally block, or <code>null</code> if this try statement
+        *    has none
+        */ 
+       public Block getFinally() {
+               return this.optionalFinallyBody;
+       }
+
+       /**
+        * Sets or clears the finally block of this try statement.
+        * 
+        * @param block the finally block node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setFinally(Block block) {
+               ASTNode oldChild = this.optionalFinallyBody;
+               preReplaceChild(oldChild, block, FINALLY_PROPERTY);
+               this.optionalFinallyBody = block;
+               postReplaceChild(oldChild, block, FINALLY_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.body == null ? 0 : getBody().treeSize())
+                       + this.catchClauses.listSize()
+                       + (this.optionalFinallyBody == null ? 0 : getFinally().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Type.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/Type.java
new file mode 100644 (file)
index 0000000..4fa9e53
--- /dev/null
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Abstract base class of all type AST node types. A type node represents a 
+ * reference to a primitive type (including void), to an array type, or to a
+ * simple named type (or type variable), to a qualified type, to a
+ * parameterized type, or to a wildcard type. Note that not all of these
+ * are meaningful in all contexts; for example, a wildcard type is only
+ * meaningful in the type argument position of a parameterized type.
+ * <p>
+ * <pre>
+ * Type:
+ *    PrimitiveType
+ *    ArrayType
+ *    SimpleType
+ *    QualifiedType
+ *    ParameterizedType
+ *    WildcardType
+ * PrimitiveType:
+ *    <b>byte</b>
+ *    <b>short</b>
+ *    <b>char</b>
+ *    <b>int</b>
+ *    <b>long</b>
+ *    <b>float</b>
+ *    <b>double</b>
+ *    <b>boolean</b>
+ *    <b>void</b>
+ * ArrayType:
+ *    Type <b>[</b> <b>]</b>
+ * SimpleType:
+ *    TypeName
+ * ParameterizedType:
+ *    Type <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b>
+ * QualifiedType:
+ *    Type <b>.</b> SimpleName
+ * WildcardType:
+ *    <b>?</b> [ ( <b>extends</b> | <b>super</b>) Type ] 
+ * </pre>
+ * </p>
+ * 
+ * @since 2.0
+ */
+public abstract class Type extends ASTNode {
+       
+       /**
+        * Creates a new AST node for a type owned by the given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       Type(AST ast) {
+               super(ast);
+       }
+       
+       /**
+        * Returns whether this type is a primitive type
+        * (<code>PrimitiveType</code>). 
+        * 
+        * @return <code>true</code> if this is a primitive type, and 
+        *    <code>false</code> otherwise
+        */
+       public final boolean isPrimitiveType() {
+               return (this instanceof PrimitiveType);
+       }
+
+       /**
+        * Returns whether this type is a simple type 
+        * (<code>SimpleType</code>).
+        * 
+        * @return <code>true</code> if this is a simple type, and 
+        *    <code>false</code> otherwise
+        */
+       public final boolean isSimpleType() {
+               return (this instanceof SimpleType);
+       }
+
+       /**
+        * Returns whether this type is an array type
+        * (<code>ArrayType</code>).
+        * 
+        * @return <code>true</code> if this is an array type, and 
+        *    <code>false</code> otherwise
+        */
+       public final boolean isArrayType() {
+               return (this instanceof ArrayType);
+       }
+
+       /**
+        * Returns whether this type is a parameterized type
+        * (<code>ParameterizedType</code>). 
+        * 
+        * @return <code>true</code> if this is a parameterized type, and 
+        *    <code>false</code> otherwise
+        * @since 3.1
+        */
+       public final boolean isParameterizedType() {
+               return (this instanceof ParameterizedType);
+       }
+
+       /**
+        * Returns whether this type is a qualified type
+        * (<code>QualifiedType</code>). 
+        * <p>
+        * Note that a type like "A.B" can be represented either of two ways:
+        * <ol>
+        * <li>
+        * <code>QualifiedType(SimpleType(SimpleName("A")),SimpleName("B"))</code>
+        * </li>
+        * <li>
+        * <code>SimpleType(QualifiedName(SimpleName("A"),SimpleName("B")))</code>
+        * </li>
+        * </ol>
+        * The first form is preferred when "A" is known to be a type. However, a 
+        * parser cannot always determine this. Clients should be prepared to handle
+        * either rather than make assumptions. (Note also that the first form
+        * became possible as of JLS3; only the second form existed in the 
+        * JLS2 API.)
+        * </p>
+        * 
+        * @return <code>true</code> if this is a qualified type, and 
+        *    <code>false</code> otherwise
+        * @since 3.1
+        */
+       public final boolean isQualifiedType() {
+               return (this instanceof QualifiedType);
+       }
+
+       /**
+        * Returns whether this type is a wildcard type
+        * (<code>WildcardType</code>).
+        * <p>
+        * Note that a wildcard type is only meaningful as a 
+        * type argument of a <code>ParameterizedType</code> node.
+        * </p>
+        * 
+        * @return <code>true</code> if this is a wildcard type, and 
+        *    <code>false</code> otherwise
+        * @since 3.1
+        */
+       public final boolean isWildcardType() {
+               return (this instanceof WildcardType);
+       }
+
+       /**
+        * Resolves and returns the binding for this type.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the type binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public final ITypeBinding resolveBinding() {
+               return this.ast.getBindingResolver().resolveType(this);
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeBinding.java
new file mode 100644 (file)
index 0000000..6d2ef28
--- /dev/null
@@ -0,0 +1,1235 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.ast.Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.Wildcard;
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
+import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
+import net.sourceforge.phpdt.internal.compiler.lookup.CaptureBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.RawTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TagBits;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeVariableBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.WildcardBinding;
+import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
+import net.sourceforge.phpdt.internal.compiler.util.SuffixConstants;
+import net.sourceforge.phpdt.internal.core.JavaElement;
+import net.sourceforge.phpdt.internal.core.PackageFragment;
+
+/**
+ * Internal implementation of type bindings.
+ */
+class TypeBinding implements ITypeBinding {
+       protected static final IMethodBinding[] NO_METHOD_BINDINGS = new IMethodBinding[0];
+
+       private static final String NO_NAME = ""; //$NON-NLS-1$
+       protected static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
+       protected static final IVariableBinding[] NO_VARIABLE_BINDINGS = new IVariableBinding[0];
+
+       private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+               Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.STRICTFP;
+
+       net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding;
+       private String key;
+       private BindingResolver resolver;
+       private IVariableBinding[] fields;
+       private IAnnotationBinding[] annotations;
+       private IMethodBinding[] methods;
+       private ITypeBinding[] members;
+       private ITypeBinding[] interfaces;
+       private ITypeBinding[] typeArguments;
+       private ITypeBinding[] bounds;
+       private ITypeBinding[] typeParameters;
+
+       public TypeBinding(BindingResolver resolver, net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding binding) {
+               this.binding = binding;
+               this.resolver = resolver;
+       }
+
+       public ITypeBinding createArrayType(int dimension) {
+               int realDimensions = dimension;
+               realDimensions += this.getDimensions();
+               if (realDimensions < 1 || realDimensions > 255) {
+                       throw new IllegalArgumentException();
+               }
+               return this.resolver.resolveArrayType(this, dimension);
+       }
+
+       public IAnnotationBinding[] getAnnotations() {
+               if (this.annotations != null) {
+                       return this.annotations;
+               }
+               if (this.binding.isAnnotationType() || this.binding.isClass() || this.binding.isEnum() || this.binding.isInterface()) {
+                       net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding refType =
+                               (net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding) this.binding;
+                       net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = refType.getAnnotations();
+                       int length = internalAnnotations == null ? 0 : internalAnnotations.length;
+                       if (length != 0) {
+                               IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
+                               int convertedAnnotationCount = 0;
+                               for (int i = 0; i < length; i++) {
+                                       net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
+                                       IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
+                                       if (annotationInstance == null) {
+                                               continue;
+                                       }
+                                       tempAnnotations[convertedAnnotationCount++] = annotationInstance;
+                               }
+                               if (convertedAnnotationCount != length) {
+                                       if (convertedAnnotationCount == 0) {
+                                               return this.annotations = AnnotationBinding.NoAnnotations;
+                                       }
+                                       System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
+                               }
+                               return this.annotations = tempAnnotations;
+                       }
+               }
+               return this.annotations = AnnotationBinding.NoAnnotations;
+       }
+
+       /*
+        * @see ITypeBinding#getBinaryName()
+        * @since 3.0
+        */
+       public String getBinaryName() {
+               if (this.binding.isCapture()) {
+                       return null; // no binary name for capture binding
+               } else if (this.binding.isTypeVariable()) {
+                       TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+                       net.sourceforge.phpdt.internal.compiler.lookup.Binding declaring = typeVariableBinding.declaringElement;
+                       StringBuffer binaryName = new StringBuffer();
+                       switch(declaring.kind()) {
+                               case net.sourceforge.phpdt.internal.compiler.lookup.Binding.METHOD :
+                                       MethodBinding methodBinding = (MethodBinding) declaring;
+                                       char[] constantPoolName = methodBinding.declaringClass.constantPoolName();
+                                       if (constantPoolName == null) return null;
+                                       binaryName
+                                               .append(CharOperation.replaceOnCopy(constantPoolName, '/', '.'))
+                                               .append('$')
+                                               .append(methodBinding.signature())
+                                               .append('$')
+                                               .append(typeVariableBinding.sourceName);
+                                       break;
+                               default :
+                                       net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding = (net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) declaring;
+                                       constantPoolName = typeBinding.constantPoolName();
+                                       if (constantPoolName == null) return null;
+                                       binaryName
+                                               .append(CharOperation.replaceOnCopy(constantPoolName, '/', '.'))
+                                               .append('$')
+                                               .append(typeVariableBinding.sourceName);
+                       }
+                       return String.valueOf(binaryName);
+               }
+               char[] constantPoolName = this.binding.constantPoolName();
+               if (constantPoolName == null) return null;
+               char[] dotSeparated = CharOperation.replaceOnCopy(constantPoolName, '/', '.');
+               return new String(dotSeparated);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getBound()
+        */
+       public ITypeBinding getBound() {
+               switch (this.binding.kind()) {
+                       case Binding.WILDCARD_TYPE :
+                       case Binding.INTERSECTION_TYPE :
+                               WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
+                               if (wildcardBinding.bound != null) {
+                                       return this.resolver.getTypeBinding(wildcardBinding.bound);
+                               }
+                               break;
+               }
+               return null;
+       }
+
+       /*
+        * @see ITypeBinding#getComponentType()
+        */
+       public ITypeBinding getComponentType() {
+               if (!this.isArray()) {
+                       return null;
+               }
+               ArrayBinding arrayBinding = (ArrayBinding) binding;
+               return resolver.getTypeBinding(arrayBinding.elementsType());
+       }
+
+       /*
+        * @see ITypeBinding#getDeclaredFields()
+        */
+       public synchronized IVariableBinding[] getDeclaredFields() {
+               if (this.fields != null) {
+                       return this.fields;
+               }
+               try {
+                       if (isClass() || isInterface() || isEnum()) {
+                               ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                               FieldBinding[] fieldBindings = referenceBinding.availableFields(); // resilience
+                               int length = fieldBindings.length;
+                               if (length != 0) {
+                                       int convertedFieldCount = 0;
+                                       IVariableBinding[] newFields = new IVariableBinding[length];
+                                       for (int i = 0; i < length; i++) {
+                                               FieldBinding fieldBinding = fieldBindings[i];
+                                               IVariableBinding variableBinding = this.resolver.getVariableBinding(fieldBinding);
+                                               if (variableBinding == null) {
+                                                       return this.fields = NO_VARIABLE_BINDINGS;
+                                               }
+                                               newFields[convertedFieldCount++] = variableBinding;
+                                       }
+
+                                       if (convertedFieldCount != length) {
+                                               if (convertedFieldCount == 0) {
+                                                       return this.fields = NO_VARIABLE_BINDINGS;
+                                               }                                               
+                                               System.arraycopy(newFields, 0, (newFields = new IVariableBinding[convertedFieldCount]), 0, convertedFieldCount);
+                                       }                                       
+                                       return this.fields = newFields;
+                               }
+                       }
+               } catch (RuntimeException e) {
+                       /* in case a method cannot be resolvable due to missing jars on the classpath
+                        * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+                        */
+                       net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declared fields"); //$NON-NLS-1$
+               }
+               return this.fields = NO_VARIABLE_BINDINGS;
+       }
+
+       /*
+        * @see ITypeBinding#getDeclaredMethods()
+        */
+       public synchronized IMethodBinding[] getDeclaredMethods() {
+               if (this.methods != null) {
+                       return this.methods;
+               }
+               try {
+                       if (isClass() || isInterface() || isEnum()) {
+                               ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                               net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding[] internalMethods = referenceBinding.availableMethods(); // be resilient
+                               int length = internalMethods.length;
+                               if (length != 0) {
+                                       int convertedMethodCount = 0;
+                                       IMethodBinding[] newMethods = new IMethodBinding[length];
+                                       for (int i = 0; i < length; i++) {
+                                               net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding methodBinding = internalMethods[i];
+                                               if (methodBinding.isDefaultAbstract() || methodBinding.isSynthetic() || (methodBinding.isConstructor() && isInterface())) {
+                                                       continue;
+                                               }
+                                               IMethodBinding methodBinding2 = this.resolver.getMethodBinding(methodBinding);
+                                               if (methodBinding2 != null) {
+                                                       newMethods[convertedMethodCount++] = methodBinding2;
+                                               }
+                                       }
+                                       if (convertedMethodCount != length) {
+                                               if (convertedMethodCount == 0) {
+                                                       return this.methods = NO_METHOD_BINDINGS;
+                                               }
+                                               System.arraycopy(newMethods, 0, (newMethods = new IMethodBinding[convertedMethodCount]), 0, convertedMethodCount);
+                                       }
+                                       return this.methods = newMethods;
+                               }
+                       }
+               } catch (RuntimeException e) {
+                       /* in case a method cannot be resolvable due to missing jars on the classpath
+                        * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+                        */
+                       net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declared methods"); //$NON-NLS-1$
+               }
+               return this.methods = NO_METHOD_BINDINGS;
+       }
+
+       /*
+        * @see ITypeBinding#getDeclaredModifiers()
+        */
+       public int getDeclaredModifiers() {
+               return getModifiers();
+       }
+
+       /*
+        * @see ITypeBinding#getDeclaredTypes()
+        */
+       public synchronized ITypeBinding[] getDeclaredTypes() {
+               if (this.members != null) {
+                       return this.members;
+               }
+               try {
+                       if (isClass() || isInterface() || isEnum()) {
+                               ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                               ReferenceBinding[] internalMembers = referenceBinding.memberTypes();
+                               int length = internalMembers.length;
+                               if (length != 0) {
+                                       ITypeBinding[] newMembers = new ITypeBinding[length];
+                                       for (int i = 0; i < length; i++) {
+                                               ITypeBinding typeBinding = this.resolver.getTypeBinding(internalMembers[i]);
+                                               if (typeBinding == null) {
+                                                       return this.members = NO_TYPE_BINDINGS;
+                                               }
+                                               newMembers[i] = typeBinding;
+                                       }
+                                       return this.members = newMembers;
+                               }
+                       }
+               } catch (RuntimeException e) {
+                       /* in case a method cannot be resolvable due to missing jars on the classpath
+                        * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+                        */
+                       net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declared methods"); //$NON-NLS-1$
+               }
+               return this.members = NO_TYPE_BINDINGS;
+       }
+
+       /*
+        * @see ITypeBinding#getDeclaringMethod()
+        */
+       public synchronized IMethodBinding getDeclaringMethod() {
+               if (this.binding instanceof LocalTypeBinding) {
+                       LocalTypeBinding localTypeBinding = (LocalTypeBinding) this.binding;
+                       MethodBinding methodBinding = localTypeBinding.enclosingMethod;
+                       if (methodBinding != null) {
+                               try {
+                                       return this.resolver.getMethodBinding(localTypeBinding.enclosingMethod);
+                               } catch (RuntimeException e) {
+                                       /* in case a method cannot be resolvable due to missing jars on the classpath
+                                        * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+                                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+                                        */
+                                       net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declaring method"); //$NON-NLS-1$
+                               }
+                       }
+               } else if (this.binding.isTypeVariable()) {
+                       TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+                       Binding declaringElement = typeVariableBinding.declaringElement;
+                       if (declaringElement instanceof MethodBinding) {
+                               try {
+                                       return this.resolver.getMethodBinding((MethodBinding)declaringElement);
+                               } catch (RuntimeException e) {
+                                       /* in case a method cannot be resolvable due to missing jars on the classpath
+                                        * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+                                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+                                        */
+                                       net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declaring method"); //$NON-NLS-1$
+                               }
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * @see ITypeBinding#getDeclaringClass()
+        */
+       public synchronized ITypeBinding getDeclaringClass() {
+               if (isClass() || isInterface() || isEnum()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       if (referenceBinding.isNestedType()) {
+                               try {
+                                       return this.resolver.getTypeBinding(referenceBinding.enclosingType());
+                               } catch (RuntimeException e) {
+                                       /* in case a method cannot be resolvable due to missing jars on the classpath
+                                        * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+                                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+                                        */
+                                       net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declaring class"); //$NON-NLS-1$
+                               }
+                       }
+               } else if (this.binding.isTypeVariable()) {
+                       TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+                       Binding declaringElement = typeVariableBinding.isCapture() ? ((CaptureBinding) typeVariableBinding).sourceType : typeVariableBinding.declaringElement;
+                       if (declaringElement instanceof ReferenceBinding) {
+                               try {
+                                       return this.resolver.getTypeBinding((ReferenceBinding)declaringElement);
+                               } catch (RuntimeException e) {
+                                       /* in case a method cannot be resolvable due to missing jars on the classpath
+                                        * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+                                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+                                        */
+                                       net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve declaring class"); //$NON-NLS-1$
+                               }
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * @see ITypeBinding#getDimensions()
+        */
+       public int getDimensions() {
+               if (!this.isArray()) {
+                       return 0;
+               }
+               ArrayBinding arrayBinding = (ArrayBinding) binding;
+               return arrayBinding.dimensions;
+       }
+
+       /*
+        * @see ITypeBinding#getElementType()
+        */
+       public ITypeBinding getElementType() {
+               if (!this.isArray()) {
+                       return null;
+               }
+               ArrayBinding arrayBinding = (ArrayBinding) binding;
+               return resolver.getTypeBinding(arrayBinding.leafComponentType);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeDeclaration()
+        */
+       public ITypeBinding getTypeDeclaration() {
+               if (this.binding instanceof ParameterizedTypeBinding)
+                       return this.resolver.getTypeBinding(((ParameterizedTypeBinding)this.binding).genericType());
+               return this;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getErasure()
+        */
+       public ITypeBinding getErasure() {
+               return this.resolver.getTypeBinding(this.binding.erasure());
+       }
+
+       public synchronized ITypeBinding[] getInterfaces() {
+               if (this.interfaces != null) {
+                       return this.interfaces;
+               }
+               if (this.binding == null)
+                       return this.interfaces = NO_TYPE_BINDINGS;
+               switch (this.binding.kind()) {
+                       case Binding.ARRAY_TYPE :
+                       case Binding.BASE_TYPE :
+                               return this.interfaces = NO_TYPE_BINDINGS;
+               }
+               ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+               ReferenceBinding[] internalInterfaces = null;
+               try {
+                       internalInterfaces = referenceBinding.superInterfaces();
+               } catch (RuntimeException e) {
+                       /* in case a method cannot be resolvable due to missing jars on the classpath
+                        * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+                        */
+                       net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve interfaces"); //$NON-NLS-1$
+               }
+               int length = internalInterfaces == null ? 0 : internalInterfaces.length;
+               if (length != 0) {
+                       ITypeBinding[] newInterfaces = new ITypeBinding[length];
+                       int interfacesCounter = 0;
+                       for (int i = 0; i < length; i++) {
+                               ITypeBinding typeBinding = this.resolver.getTypeBinding(internalInterfaces[i]);
+                               if (typeBinding == null) {
+                                       continue;
+                               }
+                               newInterfaces[interfacesCounter++] = typeBinding;
+                       }
+                       if (length != interfacesCounter) {
+                               System.arraycopy(newInterfaces, 0, (newInterfaces = new ITypeBinding[interfacesCounter]), 0, interfacesCounter);
+                       }
+                       return this.interfaces = newInterfaces;
+               }
+               return this.interfaces = NO_TYPE_BINDINGS;
+       }
+
+       public IJavaElement getJavaElement() {
+               JavaElement element = getUnresolvedJavaElement();
+               if (element != null)
+                       return element.resolved(this.binding);
+               if (isRecovered()) {
+                       IPackageBinding packageBinding = getPackage();
+                       if (packageBinding != null) {
+                               final IJavaElement javaElement = packageBinding.getJavaElement();
+                               if (javaElement != null && javaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
+                                       // best effort: we don't know if the recovered binding is a binary or source binding, so go with a compilation unit
+                                       return ((PackageFragment) javaElement).getCompilationUnit(new String(this.binding.sourceName()) + SuffixConstants.SUFFIX_STRING_java);
+                               }
+                       }
+                       return null;
+               }
+               return null;
+       }
+
+       private JavaElement getUnresolvedJavaElement() {
+               return getUnresolvedJavaElement(this.binding);
+       }
+       private JavaElement getUnresolvedJavaElement(net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding ) {
+               if (this.resolver instanceof DefaultBindingResolver) {
+                       DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
+                       return net.sourceforge.phpdt.internal.core.util.Util.getUnresolvedJavaElement(
+                                       typeBinding,
+                                       defaultBindingResolver.workingCopyOwner,
+                                       defaultBindingResolver.getBindingsToNodesMap());
+               } else {
+                       return net.sourceforge.phpdt.internal.core.util.Util.getUnresolvedJavaElement(typeBinding, null, null);
+               }
+       }
+
+       /*
+        * @see IBinding#getKey()
+        */
+       public String getKey() {
+               if (this.key == null) {
+                       this.key = new String(this.binding.computeUniqueKey());
+               }
+               return this.key;
+       }
+
+       /*
+        * @see IBinding#getKind()
+        */
+       public int getKind() {
+               return IBinding.TYPE;
+       }
+
+       /*
+        * @see IBinding#getModifiers()
+        */
+       public int getModifiers() {
+               if (isClass()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+                       if (referenceBinding.isAnonymousType()) {
+                               return accessFlags & ~Modifier.FINAL;
+                       }
+                       return accessFlags;
+               } else if (isAnnotation()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+                       // clear the AccAbstract, AccAnnotation and the AccInterface bits
+                       return accessFlags & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation);
+               } else if (isInterface()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+                       // clear the AccAbstract and the AccInterface bits
+                       return accessFlags & ~(ClassFileConstants.AccAbstract | ClassFileConstants.AccInterface);
+               } else if (isEnum()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       final int accessFlags = referenceBinding.getAccessFlags() & VALID_MODIFIERS;
+                       // clear the AccEnum bits
+                       return accessFlags & ~ClassFileConstants.AccEnum;
+               } else {
+                       return Modifier.NONE;
+               }
+       }
+
+       public String getName() {
+               StringBuffer buffer;
+               switch (this.binding.kind()) {
+
+                       case Binding.WILDCARD_TYPE :
+                       case Binding.INTERSECTION_TYPE:
+                               WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
+                               buffer = new StringBuffer();
+                               buffer.append(TypeConstants.WILDCARD_NAME);
+                               if (wildcardBinding.bound != null) {
+                                       switch(wildcardBinding.boundKind) {
+                                       case Wildcard.SUPER :
+                                               buffer.append(TypeConstants.WILDCARD_SUPER);
+                                           break;
+                                       case Wildcard.EXTENDS :
+                                               buffer.append(TypeConstants.WILDCARD_EXTENDS);
+                                       }
+                                       buffer.append(getBound().getName());
+                               }
+                               return String.valueOf(buffer);
+
+                       case Binding.TYPE_PARAMETER :
+                               if (isCapture()) {
+                                       return NO_NAME;
+                               }
+                               TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+                               return new String(typeVariableBinding.sourceName);
+
+                       case Binding.PARAMETERIZED_TYPE :
+                               ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
+                               buffer = new StringBuffer();
+                               buffer.append(parameterizedTypeBinding.sourceName());
+                               ITypeBinding[] tArguments = getTypeArguments();
+                               final int typeArgumentsLength = tArguments.length;
+                               if (typeArgumentsLength != 0) {
+                                       buffer.append('<');
+                                       for (int i = 0; i < typeArgumentsLength; i++) {
+                                               if (i > 0) {
+                                                       buffer.append(',');
+                                               }
+                                               buffer.append(tArguments[i].getName());
+                                       }
+                                       buffer.append('>');
+                               }
+                               return String.valueOf(buffer);
+
+                       case Binding.RAW_TYPE :
+                               return getTypeDeclaration().getName();
+
+                       case Binding.ARRAY_TYPE :
+                               ITypeBinding elementType = getElementType();
+                               if (elementType.isLocal() || elementType.isAnonymous() || elementType.isCapture()) {
+                                       return NO_NAME;
+                               }
+                               int dimensions = getDimensions();
+                               char[] brackets = new char[dimensions * 2];
+                               for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+                                       brackets[i] = ']';
+                                       brackets[i - 1] = '[';
+                               }
+                               buffer = new StringBuffer(elementType.getName());
+                               buffer.append(brackets);
+                               return String.valueOf(buffer);
+
+                       default :
+                               if (isPrimitive() || isNullType()) {
+                                       BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
+                                       return new String(baseTypeBinding.simpleName);
+                               }
+                               if (isAnonymous()) {
+                                       return NO_NAME;
+                               }
+                               return new String(this.binding.sourceName());
+               }
+       }
+
+       /*
+        * @see ITypeBinding#getPackage()
+        */
+       public IPackageBinding getPackage() {
+               switch (this.binding.kind()) {
+                       case Binding.BASE_TYPE :
+                       case Binding.ARRAY_TYPE :
+                       case Binding.TYPE_PARAMETER : // includes capture scenario
+                       case Binding.WILDCARD_TYPE :
+                       case Binding.INTERSECTION_TYPE:
+                               return null;
+               }
+               ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+               return this.resolver.getPackageBinding(referenceBinding.getPackage());
+       }
+
+       /**
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getQualifiedName()
+        */
+       public String getQualifiedName() {
+               StringBuffer buffer;
+               switch (this.binding.kind()) {
+
+                       case Binding.WILDCARD_TYPE :
+                       case Binding.INTERSECTION_TYPE:
+                               WildcardBinding wildcardBinding = (WildcardBinding) this.binding;
+                               buffer = new StringBuffer();
+                               buffer.append(TypeConstants.WILDCARD_NAME);
+                               final ITypeBinding bound = getBound();
+                               if (bound != null) {
+                                       switch(wildcardBinding.boundKind) {
+                                               case Wildcard.SUPER :
+                                                       buffer.append(TypeConstants.WILDCARD_SUPER);
+                                                       break;
+                                               case Wildcard.EXTENDS :
+                                                       buffer.append(TypeConstants.WILDCARD_EXTENDS);
+                                       }
+                                       buffer.append(bound.getQualifiedName());
+                               }
+                               return String.valueOf(buffer);
+
+                       case Binding.RAW_TYPE :
+                               return getTypeDeclaration().getQualifiedName();
+
+                       case Binding.ARRAY_TYPE :
+                               ITypeBinding elementType = getElementType();
+                               if (elementType.isLocal() || elementType.isAnonymous() || elementType.isCapture()) {
+                                       return elementType.getQualifiedName();
+                               }
+                               final int dimensions = getDimensions();
+                               char[] brackets = new char[dimensions * 2];
+                               for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+                                       brackets[i] = ']';
+                                       brackets[i - 1] = '[';
+                               }
+                               buffer = new StringBuffer(elementType.getQualifiedName());
+                               buffer.append(brackets);
+                               return String.valueOf(buffer);
+
+                       case Binding.TYPE_PARAMETER :
+                               if (isCapture()) {
+                                       return NO_NAME;
+                               }
+                               TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+                               return new String(typeVariableBinding.sourceName);
+
+                       case Binding.PARAMETERIZED_TYPE :
+                               buffer = new StringBuffer();
+                               if (isMember()) {
+                                       buffer
+                                               .append(getDeclaringClass().getQualifiedName())
+                                               .append('.');
+                                       ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
+                                       buffer.append(parameterizedTypeBinding.sourceName());
+                                       ITypeBinding[] tArguments = getTypeArguments();
+                                       final int typeArgumentsLength = tArguments.length;
+                                       if (typeArgumentsLength != 0) {
+                                               buffer.append('<');
+                                               for (int i = 0; i < typeArgumentsLength; i++) {
+                                                       if (i > 0) {
+                                                               buffer.append(',');
+                                                       }
+                                                       buffer.append(tArguments[i].getQualifiedName());
+                                               }
+                                               buffer.append('>');
+                                       }
+                                       return String.valueOf(buffer);
+                               }
+                               buffer.append(getTypeDeclaration().getQualifiedName());
+                               ITypeBinding[] tArguments = getTypeArguments();
+                               final int typeArgumentsLength = tArguments.length;
+                               if (typeArgumentsLength != 0) {
+                                       buffer.append('<');
+                                       for (int i = 0; i < typeArgumentsLength; i++) {
+                                               if (i > 0) {
+                                                       buffer.append(',');
+                                               }
+                                               buffer.append(tArguments[i].getQualifiedName());
+                                       }
+                                       buffer.append('>');
+                               }
+                               return String.valueOf(buffer);
+
+                       default :
+                               if (isAnonymous() || this.binding.isLocalType()) {
+                                       return NO_NAME;
+                               }
+                               if (isPrimitive() || isNullType()) {
+                                       BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding;
+                                       return new String(baseTypeBinding.simpleName);
+                               }
+                               if (isMember()) {
+                                       buffer = new StringBuffer();
+                                       buffer
+                                               .append(getDeclaringClass().getQualifiedName())
+                                               .append('.');
+                                       buffer.append(getName());
+                                       return String.valueOf(buffer);
+                               }
+                               PackageBinding packageBinding = this.binding.getPackage();
+                               buffer = new StringBuffer();
+                               if (packageBinding != null && packageBinding.compoundName != CharOperation.NO_CHAR_CHAR) {
+                                       buffer.append(CharOperation.concatWith(packageBinding.compoundName, '.')).append('.');
+                               }
+                               buffer.append(getName());
+                               return String.valueOf(buffer);
+               }
+       }
+
+       /*
+        * @see ITypeBinding#getSuperclass()
+        */
+       public synchronized ITypeBinding getSuperclass() {
+               if (this.binding == null)
+                       return null;
+               switch (this.binding.kind()) {
+                       case Binding.ARRAY_TYPE :
+                       case Binding.BASE_TYPE :
+                               return null;
+                       default:
+                               // no superclass for interface types (interface | annotation type)
+                               if (this.binding.isInterface())
+                                       return null;
+               }
+               ReferenceBinding superclass = null;
+               try {
+                       superclass = ((ReferenceBinding)this.binding).superclass();
+               } catch (RuntimeException e) {
+                       /* in case a method cannot be resolvable due to missing jars on the classpath
+                        * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=57871
+                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=63550
+                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=64299
+                        */
+                       net.sourceforge.phpdt.internal.core.util.Util.log(e, "Could not retrieve superclass"); //$NON-NLS-1$
+                       return this.resolver.resolveWellKnownType("java.lang.Object"); //$NON-NLS-1$
+               }
+               if (superclass == null) {
+                       return null;
+               }
+               return this.resolver.getTypeBinding(superclass);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeArguments()
+        */
+       public ITypeBinding[] getTypeArguments() {
+               if (this.typeArguments != null) {
+                       return this.typeArguments;
+               }
+               if (this.binding.isParameterizedType()) {
+                       ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) this.binding;
+                       final net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] arguments = parameterizedTypeBinding.arguments;
+                       if (arguments != null) {
+                               int argumentsLength = arguments.length;
+                               ITypeBinding[] newTypeArguments = new ITypeBinding[argumentsLength];
+                               for (int i = 0; i < argumentsLength; i++) {
+                                       ITypeBinding typeBinding = this.resolver.getTypeBinding(arguments[i]);
+                                       if (typeBinding == null) {
+                                               return this.typeArguments = NO_TYPE_BINDINGS;
+                                       }
+                                       newTypeArguments[i] = typeBinding;
+                               }
+                               return this.typeArguments = newTypeArguments;
+                       }
+               }
+               return this.typeArguments = NO_TYPE_BINDINGS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeBounds()
+        */
+       public ITypeBinding[] getTypeBounds() {
+               if (this.bounds != null) {
+                       return this.bounds;
+               }
+               if (this.binding instanceof TypeVariableBinding) {
+                       TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+                       ReferenceBinding varSuperclass = typeVariableBinding.superclass();
+                       net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding firstClassOrArrayBound = typeVariableBinding.firstBound;
+                       int boundsLength = 0;
+                       if (firstClassOrArrayBound != null) {
+                               if (firstClassOrArrayBound == varSuperclass) {
+                                       boundsLength++;
+                               } else if (firstClassOrArrayBound.isArrayType()) { // capture of ? extends/super arrayType
+                                       boundsLength++;
+                               } else {
+                                       firstClassOrArrayBound = null;
+                               }
+                       }
+                       ReferenceBinding[] superinterfaces = typeVariableBinding.superInterfaces();
+                       int superinterfacesLength = 0;
+                       if (superinterfaces != null) {
+                               superinterfacesLength = superinterfaces.length;
+                               boundsLength += superinterfacesLength;
+                       }
+                       if (boundsLength != 0) {
+                               ITypeBinding[] typeBounds = new ITypeBinding[boundsLength];
+                               int boundsIndex = 0;
+                               if (firstClassOrArrayBound != null) {
+                                       ITypeBinding typeBinding = this.resolver.getTypeBinding(firstClassOrArrayBound);
+                                       if (typeBinding == null) {
+                                               return this.bounds = NO_TYPE_BINDINGS;
+                                       }
+                                       typeBounds[boundsIndex++] = typeBinding;
+                               }
+                               if (superinterfaces != null) {
+                                       for (int i = 0; i < superinterfacesLength; i++, boundsIndex++) {
+                                               ITypeBinding typeBinding = this.resolver.getTypeBinding(superinterfaces[i]);
+                                               if (typeBinding == null) {
+                                                       return this.bounds = NO_TYPE_BINDINGS;
+                                               }
+                                               typeBounds[boundsIndex] = typeBinding;
+                                       }
+                               }
+                               return this.bounds = typeBounds;
+                       }
+               }
+               return this.bounds = NO_TYPE_BINDINGS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeParameters()
+        */
+       public ITypeBinding[] getTypeParameters() {
+               if (this.typeParameters != null) {
+                       return this.typeParameters;
+               }
+               switch(this.binding.kind()) {
+                       case Binding.RAW_TYPE :
+                       case Binding.PARAMETERIZED_TYPE :
+                               return this.typeParameters = NO_TYPE_BINDINGS;
+               }
+               TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+               int typeVariableBindingsLength = typeVariableBindings == null ? 0 : typeVariableBindings.length;
+               if (typeVariableBindingsLength != 0) {
+                       ITypeBinding[] newTypeParameters = new ITypeBinding[typeVariableBindingsLength];
+                       for (int i = 0; i < typeVariableBindingsLength; i++) {
+                               ITypeBinding typeBinding = this.resolver.getTypeBinding(typeVariableBindings[i]);
+                               if (typeBinding == null) {
+                                       return this.typeParameters = NO_TYPE_BINDINGS;
+                               }
+                               newTypeParameters[i] = typeBinding;
+                       }
+                       return this.typeParameters = newTypeParameters;
+               }
+               return this.typeParameters = NO_TYPE_BINDINGS;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#getWildcard()
+        * @since 3.1
+        */
+       public ITypeBinding getWildcard() {
+               if (this.binding instanceof CaptureBinding) {
+                       CaptureBinding captureBinding = (CaptureBinding) this.binding;
+                       return this.resolver.getTypeBinding(captureBinding.wildcard);
+               }
+               return null;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isGenericType()
+        * @since 3.1
+        */
+       public boolean isGenericType() {
+               // equivalent to return getTypeParameters().length > 0;
+               if (isRawType()) {
+                       return false;
+               }
+               TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
+               return (typeVariableBindings != null && typeVariableBindings.length > 0);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isAnnotation()
+        */
+       public boolean isAnnotation() {
+               return this.binding.isAnnotationType();
+       }
+
+       /*
+        * @see ITypeBinding#isAnonymous()
+        */
+       public boolean isAnonymous() {
+               if (isClass() || isInterface() || isEnum()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       return referenceBinding.isAnonymousType();
+               }
+               return false;
+       }
+
+       /*
+        * @see ITypeBinding#isArray()
+        */
+       public boolean isArray() {
+               return binding.isArrayType();
+       }
+
+       /* (non-Javadoc)
+        * @see ITypeBinding#isAssignmentCompatible(ITypeBinding)
+        */
+       public boolean isAssignmentCompatible(ITypeBinding type) {
+               try {
+                       if (this == type) return true;
+                       if (!(type instanceof TypeBinding)) return false;
+                       TypeBinding other = (TypeBinding) type;
+                       Scope scope = this.resolver.scope();
+                       if (scope == null) return false;
+                       return this.binding.isCompatibleWith(other.binding) || scope.isBoxingCompatibleWith(this.binding, other.binding);
+               } catch (AbortCompilation e) {
+                       // don't surface internal exception to clients
+                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+                       return false;
+               }
+       }
+
+       /* (non-Javadoc)
+        * @see ITypeBinding#isCapture()
+        */
+       public boolean isCapture() {
+               return this.binding.isCapture();
+       }
+
+       /* (non-Javadoc)
+        * @see ITypeBinding#isCastCompatible(ITypeBinding)
+        */
+       public boolean isCastCompatible(ITypeBinding type) {
+               try {
+                       Expression expression = new Expression() {
+                               public StringBuffer printExpression(int indent,StringBuffer output) {
+                                       return null;
+                               }
+                       };
+                       Scope scope = this.resolver.scope();
+                       if (scope == null) return false;
+                       if (!(type instanceof TypeBinding)) return false;
+                       net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding expressionType = ((TypeBinding) type).binding;
+                       // simulate capture in case checked binding did not properly get extracted from a reference
+                       expressionType = expressionType.capture(scope, 0);
+                       return expression.checkCastTypesCompatibility(scope, this.binding, expressionType, null);
+               } catch (AbortCompilation e) {
+                       // don't surface internal exception to clients
+                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+                       return false;
+               }
+       }
+
+       /*
+        * @see ITypeBinding#isClass()
+        */
+       public boolean isClass() {
+               switch (this.binding.kind()) {
+                       case Binding.TYPE_PARAMETER :
+                       case Binding.WILDCARD_TYPE :
+                       case Binding.INTERSECTION_TYPE :
+                               return false;
+               }
+               return this.binding.isClass();
+       }
+
+       /*
+        * @see IBinding#isDeprecated()
+        */
+       public boolean isDeprecated() {
+               if (isClass() || isInterface() || isEnum()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       return referenceBinding.isDeprecated();
+               }
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see ITypeBinding#isEnum()
+        */
+       public boolean isEnum() {
+               return this.binding.isEnum();
+       }
+
+       /*
+        * @see IBinding#isEqualTo(Binding)
+        * @since 3.1
+        */
+       public boolean isEqualTo(IBinding other) {
+               if (other == this) {
+                       // identical binding - equal (key or no key)
+                       return true;
+               }
+               if (other == null) {
+                       // other binding missing
+                       return false;
+               }
+               if (!(other instanceof TypeBinding)) {
+                       return false;
+               }
+               net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding otherBinding = ((TypeBinding) other).binding;
+               // check return type
+               return BindingComparator.isEqual(this.binding, otherBinding);
+       }
+
+       /*
+        * @see ITypeBinding#isFromSource()
+        */
+       public boolean isFromSource() {
+               if (isClass() || isInterface() || isEnum()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       if (referenceBinding.isRawType()) {
+                               return !((RawTypeBinding) referenceBinding).genericType().isBinaryBinding();
+                       } else if (referenceBinding.isParameterizedType()) {
+                               ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) referenceBinding;
+                               net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding erasure = parameterizedTypeBinding.erasure();
+                               if (erasure instanceof ReferenceBinding) {
+                                       return !((ReferenceBinding) erasure).isBinaryBinding();
+                               }
+                               return false;
+                       } else {
+                               return !referenceBinding.isBinaryBinding();
+                       }
+               } else if (isTypeVariable()) {
+                       final TypeVariableBinding typeVariableBinding = (TypeVariableBinding) this.binding;
+                       final Binding declaringElement = typeVariableBinding.declaringElement;
+                       if (declaringElement instanceof MethodBinding) {
+                               MethodBinding methodBinding = (MethodBinding) declaringElement;
+                               return !methodBinding.declaringClass.isBinaryBinding();
+                       } else {
+                               final net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding typeBinding = (net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding) declaringElement;
+                               if (typeBinding instanceof ReferenceBinding) {
+                                       return !((ReferenceBinding) typeBinding).isBinaryBinding();
+                               } else if (typeBinding instanceof ArrayBinding) {
+                                       final ArrayBinding arrayBinding = (ArrayBinding) typeBinding;
+                                       final net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding leafComponentType = arrayBinding.leafComponentType;
+                                       if (leafComponentType instanceof ReferenceBinding) {
+                                               return !((ReferenceBinding) leafComponentType).isBinaryBinding();
+                                       }
+                               }
+                       }
+
+               } else if (isCapture()) {
+                       CaptureBinding captureBinding = (CaptureBinding) this.binding;
+                       return !captureBinding.sourceType.isBinaryBinding();
+               }
+               return false;
+       }
+
+       /*
+        * @see ITypeBinding#isInterface()
+        */
+       public boolean isInterface() {
+               switch (this.binding.kind()) {
+                       case Binding.TYPE_PARAMETER :
+                       case Binding.WILDCARD_TYPE :
+                       case Binding.INTERSECTION_TYPE :
+                               return false;
+               }
+               return this.binding.isInterface();
+       }
+
+       /*
+        * @see ITypeBinding#isLocal()
+        */
+       public boolean isLocal() {
+               if (isClass() || isInterface() || isEnum()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       return referenceBinding.isLocalType() && !referenceBinding.isMemberType();
+               }
+               return false;
+       }
+
+       /*
+        * @see ITypeBinding#isMember()
+        */
+       public boolean isMember() {
+               if (isClass() || isInterface() || isEnum()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       return referenceBinding.isMemberType();
+               }
+               return false;
+       }
+
+       /*
+        * @see ITypeBinding#isNested()
+        */
+       public boolean isNested() {
+               if (isClass() || isInterface() || isEnum()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       return referenceBinding.isNestedType();
+               }
+               return false;
+       }
+
+       /**
+        * @see ITypeBinding#isNullType()
+        */
+       public boolean isNullType() {
+               return this.binding == net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding.NULL;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isParameterizedType()
+        */
+       public boolean isParameterizedType() {
+               return this.binding.isParameterizedType() && ((ParameterizedTypeBinding) this.binding).arguments != null;
+       }
+
+       /*
+        * @see ITypeBinding#isPrimitive()
+        */
+       public boolean isPrimitive() {
+               return !isNullType() && binding.isBaseType();
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isRawType()
+        */
+       public boolean isRawType() {
+               return this.binding.isRawType();
+       }
+
+       /* (non-Javadoc)
+        * @see IBinding#isRecovered()
+        */
+       public boolean isRecovered() {
+               return (this.binding.tagBits & TagBits.HasMissingType) != 0;
+       }
+
+       /* (non-Javadoc)
+        * @see ITypeBinding#isSubTypeCompatible(ITypeBinding)
+        */
+       public boolean isSubTypeCompatible(ITypeBinding type) {
+               try {
+                       if (this == type) return true;
+                       if (this.binding.isBaseType()) return false;
+                       if (!(type instanceof TypeBinding)) return false;
+                       TypeBinding other = (TypeBinding) type;
+                       if (other.binding.isBaseType()) return false;
+                       return this.binding.isCompatibleWith(other.binding);
+               } catch (AbortCompilation e) {
+                       // don't surface internal exception to clients
+                       // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
+                       return false;
+               }
+       }
+
+       /**
+        * @see IBinding#isSynthetic()
+        */
+       public boolean isSynthetic() {
+               return false;
+       }
+
+       /*
+        * @see ITypeBinding#isTopLevel()
+        */
+       public boolean isTopLevel() {
+               if (isClass() || isInterface() || isEnum()) {
+                       ReferenceBinding referenceBinding = (ReferenceBinding) this.binding;
+                       return !referenceBinding.isNestedType();
+               }
+               return false;
+       }
+
+       /*
+        * @see ITypeBinding#isTypeVariable()
+        */
+       public boolean isTypeVariable() {
+               return this.binding.isTypeVariable() && !this.binding.isCapture();
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isUpperbound()
+        */
+       public boolean isUpperbound() {
+               switch (this.binding.kind()) {
+                       case Binding.WILDCARD_TYPE :
+                               return ((WildcardBinding) this.binding).boundKind == Wildcard.EXTENDS;
+                       case Binding.INTERSECTION_TYPE :
+                               return true;
+               }
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.ITypeBinding#isWildcardType()
+        */
+       public boolean isWildcardType() {
+               return this.binding.isWildcard();
+       }
+
+       /*
+        * For debugging purpose only.
+        * @see java.lang.Object#toString()
+        */
+       public String toString() {
+               return this.binding.toString();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeDeclaration.java
new file mode 100644 (file)
index 0000000..46a87bc
--- /dev/null
@@ -0,0 +1,824 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Type declaration AST node type. A type declaration
+ * is the union of a class declaration and an interface declaration.
+ * For JLS2:
+ * <pre>
+ * TypeDeclaration:
+ *             ClassDeclaration
+ *             InterfaceDeclaration
+ * ClassDeclaration:
+ *      [ Javadoc ] { Modifier } <b>class</b> Identifier
+ *                     [ <b>extends</b> Type]
+ *                     [ <b>implements</b> Type { <b>,</b> Type } ]
+ *                     <b>{</b> { ClassBodyDeclaration | <b>;</b> } <b>}</b>
+ * InterfaceDeclaration:
+ *      [ Javadoc ] { Modifier } <b>interface</b> Identifier
+ *                     [ <b>extends</b> Type { <b>,</b> Type } ]
+ *                     <b>{</b> { InterfaceBodyDeclaration | <b>;</b> } <b>}</b>
+ * </pre>
+ * For JLS3, type parameters and reified modifiers
+ * (and annotations) were added, and the superclass type name and superinterface 
+ * types names are generalized to type so that parameterized types can be 
+ * referenced:
+ * <pre>
+ * TypeDeclaration:
+ *             ClassDeclaration
+ *             InterfaceDeclaration
+ * ClassDeclaration:
+ *      [ Javadoc ] { ExtendedModifier } <b>class</b> Identifier
+ *                     [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
+ *                     [ <b>extends</b> Type ]
+ *                     [ <b>implements</b> Type { <b>,</b> Type } ]
+ *                     <b>{</b> { ClassBodyDeclaration | <b>;</b> } <b>}</b>
+ * InterfaceDeclaration:
+ *      [ Javadoc ] { ExtendedModifier } <b>interface</b> Identifier
+ *                     [ <b>&lt;</b> TypeParameter { <b>,</b> TypeParameter } <b>&gt;</b> ]
+ *                     [ <b>extends</b> Type { <b>,</b> Type } ]
+ *                     <b>{</b> { InterfaceBodyDeclaration | <b>;</b> } <b>}</b>
+ * </pre>
+ * <p>
+ * When a Javadoc comment is present, the source
+ * range begins with the first character of the "/**" comment delimiter.
+ * When there is no Javadoc comment, the source range begins with the first
+ * character of the first modifier or annotation (if any), or the
+ * first character of the "class" or "interface" keyword (if no
+ * modifiers or annotations). The source range extends through the last character of the "}"
+ * token following the body declarations.
+ * </p>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class TypeDeclaration extends AbstractTypeDeclaration {
+       
+       /**
+        * The "javadoc" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor JAVADOC_PROPERTY = 
+               internalJavadocPropertyFactory(TypeDeclaration.class);
+
+       /**
+        * The "modifiers" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor MODIFIERS_PROPERTY = 
+               internalModifiersPropertyFactory(TypeDeclaration.class);
+       
+       /**
+        * The "modifiers" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
+               internalModifiers2PropertyFactory(TypeDeclaration.class);
+       
+       /**
+        * The "interface" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor INTERFACE_PROPERTY = 
+               new SimplePropertyDescriptor(TypeDeclaration.class, "interface", boolean.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY =
+               internalNamePropertyFactory(TypeDeclaration.class);
+
+       /**
+        * The "superclass" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor SUPERCLASS_PROPERTY = 
+               new ChildPropertyDescriptor(TypeDeclaration.class, "superclass", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "superInterfaces" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor SUPER_INTERFACES_PROPERTY = 
+               new ChildListPropertyDescriptor(TypeDeclaration.class, "superInterfaces", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "superclassType" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildPropertyDescriptor SUPERCLASS_TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(TypeDeclaration.class, "superclassType", Type.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "superInterfaceTypes" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor SUPER_INTERFACE_TYPES_PROPERTY = 
+               new ChildListPropertyDescriptor(TypeDeclaration.class, "superInterfaceTypes", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "typeParameters" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor TYPE_PARAMETERS_PROPERTY = 
+               new ChildListPropertyDescriptor(TypeDeclaration.class, "typeParameters", TypeParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "bodyDeclarations" structural property of this node type (added in JLS3 API).
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY = 
+               internalBodyDeclarationPropertyFactory(TypeDeclaration.class);
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.0
+        */
+       private static final List PROPERTY_DESCRIPTORS_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List propertyList = new ArrayList(8);
+               createPropertyList(TypeDeclaration.class, propertyList);
+               addProperty(JAVADOC_PROPERTY, propertyList);
+               addProperty(MODIFIERS_PROPERTY, propertyList);
+               addProperty(INTERFACE_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               addProperty(SUPERCLASS_PROPERTY, propertyList);
+               addProperty(SUPER_INTERFACES_PROPERTY, propertyList);
+               addProperty(BODY_DECLARATIONS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+               
+               propertyList = new ArrayList(9);
+               createPropertyList(TypeDeclaration.class, propertyList);
+               addProperty(JAVADOC_PROPERTY, propertyList);
+               addProperty(MODIFIERS2_PROPERTY, propertyList);
+               addProperty(INTERFACE_PROPERTY, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               addProperty(TYPE_PARAMETERS_PROPERTY, propertyList);
+               addProperty(SUPERCLASS_TYPE_PROPERTY, propertyList);
+               addProperty(SUPER_INTERFACE_TYPES_PROPERTY, propertyList);
+               addProperty(BODY_DECLARATIONS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * <code>true</code> for an interface, <code>false</code> for a class.
+        * Defaults to class.
+        */
+       private boolean isInterface = false;
+       
+       /**
+        * The type paramters (element type: <code>TypeParameter</code>). 
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * @since 3.1
+        */
+       private ASTNode.NodeList typeParameters = null;
+
+       /**
+        * The optional superclass name; <code>null</code> if none.
+        * Defaults to none. Note that this field is not used for
+        * interface declarations. Not used in 3.0.
+        */
+       private Name optionalSuperclassName = null;
+
+       /**
+        * The superinterface names (element type: <code>Name</code>). 
+        * JLS2 only; defaults to an empty list. Not used in JLS3.
+        * (see constructor).
+        * 
+        */
+       private ASTNode.NodeList superInterfaceNames = null;
+
+       /**
+        * The optional superclass type; <code>null</code> if none.
+        * Defaults to none. Note that this field is not used for
+        * interface declarations. Null in JLS2. Added in JLS3.
+        * @since 3.1
+        */
+       private Type optionalSuperclassType = null;
+
+       /**
+        * The superinterface types (element type: <code>Type</code>). 
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * @since 3.1
+        */
+       private ASTNode.NodeList superInterfaceTypes = null;
+
+       /**
+        * Creates a new AST node for a type declaration owned by the given 
+        * AST. By default, the type declaration is for a class of an
+        * unspecified, but legal, name; no modifiers; no javadoc; 
+        * no type parameters; no superclass or superinterfaces; and an empty list
+        * of body 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
+        */
+       TypeDeclaration(AST ast) {
+               super(ast);
+               if (ast.apiLevel == AST.JLS2_INTERNAL) {
+                       this.superInterfaceNames = new ASTNode.NodeList(SUPER_INTERFACES_PROPERTY);
+               }
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY);
+                       this.superInterfaceTypes = new ASTNode.NodeList(SUPER_INTERFACE_TYPES_PROPERTY);
+               }
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+               if (property == MODIFIERS_PROPERTY) {
+                       if (get) {
+                               return getModifiers();
+                       } else {
+                               internalSetModifiers(value);
+                               return 0;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetIntProperty(property, get, value);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+               if (property == INTERFACE_PROPERTY) {
+                       if (get) {
+                               return isInterface();
+                       } else {
+                               setInterface(value);
+                               return false;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetBooleanProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == JAVADOC_PROPERTY) {
+                       if (get) {
+                               return getJavadoc();
+                       } else {
+                               setJavadoc((Javadoc) child);
+                               return null;
+                       }
+               }
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) child);
+                               return null;
+                       }
+               }
+               if (property == SUPERCLASS_PROPERTY) {
+                       if (get) {
+                               return getSuperclass();
+                       } else {
+                               setSuperclass((Name) child);
+                               return null;
+                       }
+               }
+               if (property == SUPERCLASS_TYPE_PROPERTY) {
+                       if (get) {
+                               return getSuperclassType();
+                       } else {
+                               setSuperclassType((Type) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == MODIFIERS2_PROPERTY) {
+                       return modifiers();
+               }
+               if (property == TYPE_PARAMETERS_PROPERTY) {
+                       return typeParameters();
+               }
+               if (property == SUPER_INTERFACES_PROPERTY) {
+                       return superInterfaces();
+               }
+               if (property == SUPER_INTERFACE_TYPES_PROPERTY) {
+                       return superInterfaceTypes();
+               }
+               if (property == BODY_DECLARATIONS_PROPERTY) {
+                       return bodyDeclarations();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildPropertyDescriptor internalJavadocProperty() {
+               return JAVADOC_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final ChildListPropertyDescriptor internalModifiers2Property() {
+               return MODIFIERS2_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on BodyDeclaration.
+        */
+       final SimplePropertyDescriptor internalModifiersProperty() {
+               return MODIFIERS_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on AbstractTypeDeclaration.
+        */
+       final ChildPropertyDescriptor internalNameProperty() {
+               return NAME_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on AbstractTypeDeclaration.
+        */
+       final ChildListPropertyDescriptor internalBodyDeclarationsProperty() {
+               return BODY_DECLARATIONS_PROPERTY;
+       }
+
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return TYPE_DECLARATION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               TypeDeclaration result = new TypeDeclaration(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setJavadoc(
+                       (Javadoc) ASTNode.copySubtree(target, getJavadoc()));
+               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                       result.internalSetModifiers(getModifiers());
+                       result.setSuperclass(
+                                       (Name) ASTNode.copySubtree(target, getSuperclass()));
+                       result.superInterfaces().addAll(
+                                       ASTNode.copySubtrees(target, superInterfaces()));
+               }
+               result.setInterface(isInterface());
+               result.setName((SimpleName) getName().clone(target));
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+                       result.typeParameters().addAll(
+                                       ASTNode.copySubtrees(target, typeParameters()));
+                       result.setSuperclassType(
+                                       (Type) ASTNode.copySubtree(target, getSuperclassType()));
+                       result.superInterfaceTypes().addAll(
+                                       ASTNode.copySubtrees(target, superInterfaceTypes()));
+               }
+               result.bodyDeclarations().addAll(
+                       ASTNode.copySubtrees(target, bodyDeclarations()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                               acceptChild(visitor, getJavadoc());
+                               acceptChild(visitor, getName());
+                               acceptChild(visitor, getSuperclass());
+                               acceptChildren(visitor, this.superInterfaceNames);
+                               acceptChildren(visitor, this.bodyDeclarations);
+                       }
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChild(visitor, getJavadoc());
+                               acceptChildren(visitor, this.modifiers);
+                               acceptChild(visitor, getName());
+                               acceptChildren(visitor, this.typeParameters);
+                               acceptChild(visitor, getSuperclassType());
+                               acceptChildren(visitor, this.superInterfaceTypes);
+                               acceptChildren(visitor, this.bodyDeclarations);
+                       }
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns whether this type declaration declares a class or an 
+        * interface.
+        * 
+        * @return <code>true</code> if this is an interface declaration,
+        *    and <code>false</code> if this is a class declaration
+        */ 
+       public boolean isInterface() {
+               return this.isInterface;
+       }
+       
+       /**
+        * Sets whether this type declaration declares a class or an 
+        * interface.
+        * 
+        * @param isInterface <code>true</code> if this is an interface
+        *    declaration, and <code>false</code> if this is a class
+        *        declaration
+        */ 
+       public void setInterface(boolean isInterface) {
+               preValueChange(INTERFACE_PROPERTY);
+               this.isInterface = isInterface;
+               postValueChange(INTERFACE_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of type parameters of this type 
+        * declaration (added in JLS3 API). This list is non-empty for parameterized types.
+        * 
+        * @return the live list of type parameters
+        *    (element type: <code>TypeParameter</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public List typeParameters() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.typeParameters == null) {
+                       unsupportedIn2();
+               }
+               return this.typeParameters;
+       }
+       
+       /**
+        * Returns the name of the superclass declared in this type
+        * declaration, or <code>null</code> if there is none (JLS2 API only).
+        * <p>
+        * Note that this child is not relevant for interface 
+        * declarations (although it does still figure in subtree
+        * equality comparisons).
+        * </p>
+        * 
+        * @return the superclass name node, or <code>null</code> if 
+        *    there is none
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @deprecated In the JLS3 API, this method is replaced by
+        * {@link #getSuperclassType()}, which returns a <code>Type</code>
+        * instead of a <code>Name</code>.
+        */ 
+       public Name getSuperclass() {
+               return internalGetSuperclass();
+       }
+       
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ final Name internalGetSuperclass() {
+               supportedOnlyIn2();
+               return this.optionalSuperclassName;
+       }
+
+       /**
+       * Returns the superclass declared in this type
+       * declaration, or <code>null</code> if there is none (added in JLS3 API).
+       * <p>
+       * Note that this child is not relevant for interface 
+       * declarations (although it does still figure in subtree
+       * equality comparisons).
+       * </p>
+       * 
+       * @return the superclass type node, or <code>null</code> if 
+       *    there is none
+       * @exception UnsupportedOperationException if this operation is used in
+       * a JLS2 AST
+       * @since 3.1
+       */ 
+       public Type getSuperclassType() {
+           unsupportedIn2();
+               return this.optionalSuperclassType;
+       }
+
+       /**
+        * Sets or clears the name of the superclass declared in this type
+        * declaration (JLS2 API only).
+        * <p>
+        * Note that this child is not relevant for interface 
+        * declarations (although it does still figure in subtree
+        * equality comparisons).
+        * </p>
+        * 
+        * @param superclassName the superclass name node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @deprecated In the JLS3 API, this method is replaced by 
+        * {@link #setSuperclassType(Type)}, which expects a
+        * <code>Type</code> instead of a <code>Name</code>.
+        */ 
+       public void setSuperclass(Name superclassName) {
+               internalSetSuperclass(superclassName);
+       }
+       
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ final void internalSetSuperclass(Name superclassName) {
+           supportedOnlyIn2();
+               ASTNode oldChild = this.optionalSuperclassName;
+               preReplaceChild(oldChild, superclassName, SUPERCLASS_PROPERTY);
+               this.optionalSuperclassName = superclassName;
+               postReplaceChild(oldChild, superclassName, SUPERCLASS_PROPERTY);
+       }
+
+       /**
+        * Sets or clears the superclass declared in this type
+        * declaration (added in JLS3 API).
+        * <p>
+        * Note that this child is not relevant for interface declarations
+        * (although it does still figure in subtree equality comparisons).
+        * </p>
+        * 
+        * @param superclassType the superclass type node, or <code>null</code> if 
+        *    there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public void setSuperclassType(Type superclassType) {
+           unsupportedIn2();
+               ASTNode oldChild = this.optionalSuperclassType;
+               preReplaceChild(oldChild, superclassType, SUPERCLASS_TYPE_PROPERTY);
+               this.optionalSuperclassType = superclassType;
+               postReplaceChild(oldChild, superclassType, SUPERCLASS_TYPE_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of names of superinterfaces of this type 
+        * declaration (JLS2 API only). For a class declaration, these are the names
+        * of the interfaces that this class implements; for an interface
+        * declaration, these are the names of the interfaces that this interface
+        * extends.
+        * 
+        * @return the live list of interface names
+        *    (element type: <code>Name</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @deprecated In the JLS3 API, this method is replaced by 
+        * {@link #superInterfaceTypes()}.
+        */ 
+       public List superInterfaces() {
+               return internalSuperInterfaces();
+       }
+       
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ final List internalSuperInterfaces() {
+               // more efficient than just calling supportedOnlyIn2() to check
+               if (this.superInterfaceNames == null) {
+                       supportedOnlyIn2();
+               }
+               return this.superInterfaceNames;
+       }
+       
+       /**
+        * Returns the live ordered list of superinterfaces of this type 
+        * declaration (added in JLS3 API). For a class declaration, these are the interfaces
+        * that this class implements; for an interface declaration,
+        * these are the interfaces that this interface extends.
+        * 
+        * @return the live list of interface types
+        *    (element type: <code>Type</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public List superInterfaceTypes() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.superInterfaceTypes == null) {
+                       unsupportedIn2();
+               }
+               return this.superInterfaceTypes;
+       }
+       
+       /**
+        * Returns the ordered list of field declarations of this type 
+        * declaration. For a class declaration, these are the
+        * field declarations; for an interface declaration, these are
+        * the constant declarations.
+        * <p>
+        * This convenience method returns this node's body declarations
+        * with non-fields filtered out. Unlike <code>bodyDeclarations</code>,
+        * this method does not return a live result.
+        * </p>
+        * 
+        * @return the (possibly empty) list of field declarations
+        */ 
+       public FieldDeclaration[] getFields() {
+               List bd = bodyDeclarations();
+               int fieldCount = 0;
+               for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+                       if (it.next() instanceof FieldDeclaration) {
+                               fieldCount++;
+                       }
+               }
+               FieldDeclaration[] fields = new FieldDeclaration[fieldCount];
+               int next = 0;
+               for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+                       Object decl = it.next();
+                       if (decl instanceof FieldDeclaration) {
+                               fields[next++] = (FieldDeclaration) decl;
+                       }
+               }
+               return fields;
+       }
+
+       /**
+        * Returns the ordered list of method declarations of this type 
+        * declaration.
+        * <p>
+        * This convenience method returns this node's body declarations
+        * with non-methods filtered out. Unlike <code>bodyDeclarations</code>,
+        * this method does not return a live result.
+        * </p>
+        * 
+        * @return the (possibly empty) list of method (and constructor) 
+        *    declarations
+        */ 
+       public MethodDeclaration[] getMethods() {
+               List bd = bodyDeclarations();
+               int methodCount = 0;
+               for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+                       if (it.next() instanceof MethodDeclaration) {
+                               methodCount++;
+                       }
+               }
+               MethodDeclaration[] methods = new MethodDeclaration[methodCount];
+               int next = 0;
+               for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+                       Object decl = it.next();
+                       if (decl instanceof MethodDeclaration) {
+                               methods[next++] = (MethodDeclaration) decl;
+                       }
+               }
+               return methods;
+       }
+
+       /**
+        * Returns the ordered list of member type declarations of this type 
+        * declaration.
+        * <p>
+        * This convenience method returns this node's body declarations
+        * with non-types filtered out. Unlike <code>bodyDeclarations</code>,
+        * this method does not return a live result.
+        * </p>
+        * 
+        * @return the (possibly empty) list of member type declarations
+        */ 
+       public TypeDeclaration[] getTypes() {
+               List bd = bodyDeclarations();
+               int typeCount = 0;
+               for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+                       if (it.next() instanceof TypeDeclaration) {
+                               typeCount++;
+                       }
+               }
+               TypeDeclaration[] memberTypes = new TypeDeclaration[typeCount];
+               int next = 0;
+               for (Iterator it = bd.listIterator(); it.hasNext(); ) {
+                       Object decl = it.next();
+                       if (decl instanceof TypeDeclaration) {
+                               memberTypes[next++] = (TypeDeclaration) decl;
+                       }
+               }
+               return memberTypes;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on AsbtractTypeDeclaration.
+        */
+       ITypeBinding internalResolveBinding() {
+               return this.ast.getBindingResolver().resolveType(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 6 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return memSize()
+                       + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize())
+                       + (this.modifiers == null ? 0 : this.modifiers.listSize())
+                       + (this.typeName == null ? 0 : getName().treeSize())
+                       + (this.typeParameters == null ? 0 : this.typeParameters.listSize())
+                       + (this.optionalSuperclassName == null ? 0 : getSuperclass().treeSize())
+                       + (this.optionalSuperclassType == null ? 0 : getSuperclassType().treeSize())
+                       + (this.superInterfaceNames == null ? 0 : this.superInterfaceNames.listSize())
+                       + (this.superInterfaceTypes == null ? 0 : this.superInterfaceTypes.listSize())
+                       + this.bodyDeclarations.listSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeDeclarationStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeDeclarationStatement.java
new file mode 100644 (file)
index 0000000..c4cfe6e
--- /dev/null
@@ -0,0 +1,359 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Local type declaration statement AST node type.
+ * <p>
+ * This kind of node is used to convert a type declaration
+ * node into a statement node by wrapping it.
+ * </p>
+ * For JLS2:
+ * <pre>
+ * TypeDeclarationStatement:
+ *    TypeDeclaration
+ * </pre>
+ * For JLS3, the kinds of type declarations grew to include enum declarations:
+ * <pre>
+ * TypeDeclarationStatement:
+ *    TypeDeclaration
+ *    EnumDeclaration
+ * </pre>
+ * Although allowed at the AST, not all arrangements of AST nodes are meaningful;
+ * in particular, only class and enum declarations are meaningful in the context of 
+ * a block.
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class TypeDeclarationStatement extends Statement {
+       
+       /**
+        * The "typeDeclaration" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor TYPE_DECLARATION_PROPERTY = 
+               new ChildPropertyDescriptor(TypeDeclarationStatement.class, "typeDeclaration", TypeDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "declaration" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildPropertyDescriptor DECLARATION_PROPERTY = 
+               new ChildPropertyDescriptor(TypeDeclarationStatement.class, "declaration", AbstractTypeDeclaration.class, MANDATORY, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(TypeDeclarationStatement.class, propertyList);
+               addProperty(TYPE_DECLARATION_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+               
+               propertyList = new ArrayList(2);
+               createPropertyList(TypeDeclarationStatement.class, propertyList);
+               addProperty(DECLARATION_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The type declaration; lazily initialized; defaults to a unspecified, 
+        * but legal, type declaration. In JLS2, corresponds to TYPE_DECLARATION_PROPERTY.
+     * After JLS2, corresponds to DECLARATION_PROPERTY.
+     * @see #typeDeclProperty
+        */
+       private AbstractTypeDeclaration typeDecl = null;
+    
+    /**
+     * The child property stored on the <code>typeDecl</code> instance variable.
+     * In JLS2, corresponds to TYPE_DECLARATION_PROPERTY. After JLS2, corresponds to 
+     * DECLARATION_PROPERTY.
+     * 
+     * @return the property corresponding to the <code>typeDecl</code> instance variable;
+     * never <code>null</code>
+     */
+    private ChildPropertyDescriptor typeDeclProperty () {
+        if (getAST().apiLevel() == AST.JLS2_INTERNAL) {
+            return TYPE_DECLARATION_PROPERTY;
+        } else {
+            return DECLARATION_PROPERTY;
+        }
+    }
+
+
+       /**
+        * Creates a new unparented local type declaration statement node owned 
+        * by the given AST. By default, the local type declaration is an
+        * unspecified, but legal, type declaration.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       TypeDeclarationStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        * @since 3.0
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == TYPE_DECLARATION_PROPERTY) {
+                       if (get) {
+                               return getTypeDeclaration();
+                       } else {
+                               setTypeDeclaration((TypeDeclaration) child);
+                               return null;
+                       }
+               }
+               if (property == DECLARATION_PROPERTY) {
+                       if (get) {
+                               return getDeclaration();
+                       } else {
+                               setDeclaration((AbstractTypeDeclaration) 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.
+        */
+       final int getNodeType0() {
+               return TYPE_DECLARATION_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               TypeDeclarationStatement result = 
+                       new TypeDeclarationStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setDeclaration(
+                       (AbstractTypeDeclaration) getDeclaration().clone(target));
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getDeclaration());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the abstract type declaration of this local type declaration
+        * statement (added in JLS3 API).
+        * 
+        * @return the type declaration node
+        * @since 3.1
+        */ 
+       public AbstractTypeDeclaration getDeclaration() {
+               if (this.typeDecl == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.typeDecl == null) {
+                                       preLazyInit();
+                                       this.typeDecl = new TypeDeclaration(this.ast);
+                                       postLazyInit(this.typeDecl, typeDeclProperty());
+                               }
+                       }
+               }
+               return this.typeDecl;
+       }
+               
+       /**
+        * Sets the abstract type declaration of this local type declaration
+        * statement (added in JLS3 API).
+        * 
+        * @param decl the type declaration node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        * @since 3.1
+        */ 
+       public void setDeclaration(AbstractTypeDeclaration decl) {
+               if (decl == null) {
+                       throw new IllegalArgumentException();
+               }
+               // a TypeDeclarationStatement may occur inside an 
+               // TypeDeclaration - must check cycles
+               ASTNode oldChild = this.typeDecl;
+               ChildPropertyDescriptor typeDeclProperty = typeDeclProperty();
+               preReplaceChild(oldChild, decl, typeDeclProperty);
+               this.typeDecl= decl;
+               postReplaceChild(oldChild, decl, typeDeclProperty);
+       }
+       
+       /**
+        * Returns the type declaration of this local type declaration
+        * statement (JLS2 API only).
+        * 
+        * @return the type declaration node
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @deprecated In the JLS3 API, this method is replaced by 
+        * {@link #getDeclaration()}, which returns <code>AbstractTypeDeclaration</code>
+        * instead of <code>TypeDeclaration</code>.
+        */ 
+       public TypeDeclaration getTypeDeclaration() {
+               return internalGetTypeDeclaration();
+       }
+       
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ final TypeDeclaration internalGetTypeDeclaration() {
+               supportedOnlyIn2();
+               return (TypeDeclaration) getDeclaration();
+       }
+               
+       /**
+        * Sets the type declaration of this local type declaration
+        * statement (JLS2 API only).
+        * 
+        * @param decl the type declaration node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+     * @deprecated In the JLS3 API, this method is replaced by 
+     * {@link #setDeclaration(AbstractTypeDeclaration)} which takes
+     * <code>AbstractTypeDeclaration</code> instead of
+     * <code>TypeDeclaration</code>.
+        */ 
+       public void setTypeDeclaration(TypeDeclaration decl) {
+               internalSetTypeDeclaration(decl);
+       }
+       
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ final void internalSetTypeDeclaration(TypeDeclaration decl) {
+           supportedOnlyIn2();
+               // forward to non-deprecated replacement method
+               setDeclaration(decl);
+       }
+       
+       /**
+        * Resolves and returns the binding for the class or interface declared in
+        * this type declaration statement.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public ITypeBinding resolveBinding() {
+               // forward request to the wrapped type declaration
+               AbstractTypeDeclaration d = getDeclaration();
+               if (d instanceof TypeDeclaration) {
+                       return ((TypeDeclaration) d).resolveBinding();
+               } else if (d instanceof AnnotationTypeDeclaration) {
+                       return ((AnnotationTypeDeclaration) d).resolveBinding();
+               } else {
+                       // shouldn't happen
+                       return null;
+               }
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.typeDecl == null ? 0 : getDeclaration().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeLiteral.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeLiteral.java
new file mode 100644 (file)
index 0000000..9fa0565
--- /dev/null
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type literal AST node type.
+ *
+ * <pre>
+ * TypeLiteral:
+ *     ( Type | <b>void</b> ) <b>.</b> <b>class</b>
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class TypeLiteral extends Expression {
+
+       /**
+        * The "type" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(TypeLiteral.class, "type", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(2);
+               createPropertyList(TypeLiteral.class, propertyList);
+               addProperty(TYPE_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 type; lazily initialized; defaults to a unspecified,
+        * legal type.
+        */
+       private Type type = null;
+
+       /**
+        * Creates a new AST node for a type literal owned by the given 
+        * AST. By default, the expression has an unspecified (but legal) type.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       TypeLiteral(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == TYPE_PROPERTY) {
+                       if (get) {
+                               return getType();
+                       } else {
+                               setType((Type) 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.
+        */
+       final int getNodeType0() {
+               return TYPE_LITERAL;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               TypeLiteral result = new TypeLiteral(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setType((Type) getType().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       acceptChild(visitor, getType());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the type in this type literal expression.
+        * 
+        * @return the type
+        */ 
+       public Type getType() {
+               if (this.type == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.type == null) {
+                                       preLazyInit();
+                                       this.type = this.ast.newPrimitiveType(PrimitiveType.INT);
+                                       postLazyInit(this.type, TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.type;
+       }
+
+       /**
+        * Sets the type in this type literal expression to the given type.
+        * 
+        * @param type the new type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setType(Type type) {
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.type;
+               preReplaceChild(oldChild, type, TYPE_PROPERTY);
+               this.type = type;
+               postReplaceChild(oldChild, type, TYPE_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Operator as free
+               return BASE_NODE_SIZE + 1 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.type == null ? 0 : getType().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeParameter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/TypeParameter.java
new file mode 100644 (file)
index 0000000..23cab71
--- /dev/null
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type parameter node (added in JLS3 API).
+ * <pre>
+ * TypeParameter:
+ *    TypeVariable [ <b>extends</b> Type { <b>&</b> Type } ]
+ * </pre>
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class TypeParameter extends ASTNode {
+       
+       /**
+        * The "name" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(TypeParameter.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "typeBounds" structural property of this node type.
+        */
+       public static final ChildListPropertyDescriptor TYPE_BOUNDS_PROPERTY = 
+               new ChildListPropertyDescriptor(TypeParameter.class, "typeBounds", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(TypeParameter.class, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               addProperty(TYPE_BOUNDS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                       
+       /** 
+        * The type variable node; lazily initialized; defaults to an unspecfied, 
+        * but legal, name.
+        */
+       private SimpleName typeVariableName = null;
+       
+       /**
+        * The type bounds (element type: <code>Type</code>). 
+        * Defaults to an empty list.
+        */
+       private ASTNode.NodeList typeBounds =
+               new ASTNode.NodeList(TYPE_BOUNDS_PROPERTY);
+       
+       /**
+        * Creates a new unparented node for a parameterized type owned by the
+        * given AST. By default, an unspecified, but legal, type variable name, 
+        * and no type bounds.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       TypeParameter(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == TYPE_BOUNDS_PROPERTY) {
+                       return typeBounds();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return TYPE_PARAMETER;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               TypeParameter result = new TypeParameter(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setName((SimpleName) ((ASTNode) getName()).clone(target));
+               result.typeBounds().addAll(
+                       ASTNode.copySubtrees(target, typeBounds()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getName());
+                       acceptChildren(visitor, this.typeBounds);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the name of the type variable declared in this type parameter.
+        * 
+        * @return the name of the type variable
+        */ 
+       public SimpleName getName() {
+               if (this.typeVariableName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.typeVariableName == null) {
+                                       preLazyInit();
+                                       this.typeVariableName = new SimpleName(this.ast);
+                                       postLazyInit(this.typeVariableName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.typeVariableName;
+       }
+       
+       /**
+        * Resolves and returns the binding for this type parameter.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public final ITypeBinding resolveBinding() {
+               return this.ast.getBindingResolver().resolveTypeParameter(this);
+       }
+       
+       /**
+        * Sets the name of the type variable of this type parameter to the given
+        * name.
+        * 
+        * @param typeName the new name of this type parameter 
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setName(SimpleName typeName) {
+               if (typeName == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.typeVariableName;
+               preReplaceChild(oldChild, typeName, NAME_PROPERTY);
+               this.typeVariableName = typeName;
+               postReplaceChild(oldChild, typeName, NAME_PROPERTY);
+       }
+
+       /**
+        * Returns the live ordered list of type bounds of this type parameter.
+        * For the type parameter to be plausible, there can be at most one
+        * class in the list, and it must be first, and the remaining ones must be
+        * interfaces; the list should not contain primitive types (but array types
+        * and parameterized types are allowed).
+        * 
+        * @return the live list of type bounds
+        *    (element type: <code>Type</code>)
+        */ 
+       public List typeBounds() {
+               return this.typeBounds;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Code as free
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.typeVariableName == null ? 0 : getName().treeSize())
+                       + this.typeBounds.listSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableBinding.java
new file mode 100644 (file)
index 0000000..e5a8376
--- /dev/null
@@ -0,0 +1,357 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.util.IModifierConstants;
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TagBits;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeIds;
+import net.sourceforge.phpdt.internal.core.JavaElement;
+import net.sourceforge.phpdt.internal.core.LocalVariable;
+import net.sourceforge.phpdt.internal.core.util.Util;
+
+/**
+ * Internal implementation of variable bindings.
+ */
+class VariableBinding implements IVariableBinding {
+
+       private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
+               Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT | Modifier.VOLATILE;
+
+       private net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding binding;
+       private ITypeBinding declaringClass;
+       private String key;
+       private String name;
+       private BindingResolver resolver;
+       private ITypeBinding type;
+       private IAnnotationBinding[] annotations;
+       
+       VariableBinding(BindingResolver resolver,net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding binding) {
+               this.resolver = resolver;
+               this.binding = binding;
+       }
+
+       public IAnnotationBinding[] getAnnotations() {
+               if (this.annotations != null) {
+                       return this.annotations;
+               }
+               net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = this.binding.getAnnotations();
+               int length = internalAnnotations == null ? 0 : internalAnnotations.length;
+               if (length != 0) {
+                       IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
+                       int convertedAnnotationCount = 0;
+                       for (int i = 0; i < length; i++) {
+                               net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
+                               final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
+                               if (annotationInstance == null) {
+                                       continue;
+                               }
+                               tempAnnotations[convertedAnnotationCount++] = annotationInstance;
+                       }
+                       if (convertedAnnotationCount != length) {
+                               if (convertedAnnotationCount == 0) {
+                                       return this.annotations = AnnotationBinding.NoAnnotations;
+                               }
+                               System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
+                       }
+                       return this.annotations = tempAnnotations;
+               }
+               return this.annotations = AnnotationBinding.NoAnnotations;
+       }
+
+       /* (non-Javadoc)
+        * @see IVariableBinding#getConstantValue()
+        * @since 3.0
+        */
+       public Object getConstantValue() {
+               Constant c = this.binding.constant();
+               if (c == null || c == Constant.NotAConstant) return null;
+               switch (c.typeID()) {
+                       case TypeIds.T_boolean:
+                               return Boolean.valueOf(c.booleanValue());
+                       case TypeIds.T_byte:
+                               return new Byte(c.byteValue());
+                       case TypeIds.T_char:
+                               return new Character(c.charValue());
+                       case TypeIds.T_double:
+                               return new Double(c.doubleValue());
+                       case TypeIds.T_float:
+                               return new Float(c.floatValue());
+                       case TypeIds.T_int:
+                               return new Integer(c.intValue());
+                       case TypeIds.T_long:
+                               return new Long(c.longValue());
+                       case TypeIds.T_short:
+                               return new Short(c.shortValue());
+                       case TypeIds.T_JavaLangString:
+                               return c.stringValue();
+               }
+               return null;
+       }
+
+       /*
+        * @see IVariableBinding#getDeclaringClass()
+        */
+       public ITypeBinding getDeclaringClass() {
+               if (isField()) {
+                       if (this.declaringClass == null) {
+                               FieldBinding fieldBinding = (FieldBinding) this.binding;
+                               this.declaringClass = this.resolver.getTypeBinding(fieldBinding.declaringClass);
+                       }
+                       return this.declaringClass;
+               } else {
+                       return null;
+               }
+       }
+
+       /*
+        * @see IVariableBinding#getDeclaringMethod()
+        */
+       public IMethodBinding getDeclaringMethod() {
+               if (!isField()) {
+                       ASTNode node = this.resolver.findDeclaringNode(this);
+                       while (true) {
+                               if (node == null) break;
+                               switch(node.getNodeType()) {
+                                       case ASTNode.INITIALIZER :
+                                               return null;
+                                       case ASTNode.METHOD_DECLARATION :
+                                               MethodDeclaration methodDeclaration = (MethodDeclaration) node;
+                                               return methodDeclaration.resolveBinding();
+                                       default:
+                                               node = node.getParent();
+                               }
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * @see IBinding#getJavaElement()
+        */
+       public IJavaElement getJavaElement() {
+               JavaElement element = getUnresolvedJavaElement();
+               if (element == null)
+                       return null;
+               return element.resolved(this.binding);
+       }
+
+       /*
+        * @see IBinding#getKey()
+        */
+       public String getKey() {
+               if (this.key == null) {
+                       this.key = new String(this.binding.computeUniqueKey());
+               }
+               return this.key;
+       }
+
+       /*
+        * @see IBinding#getKind()
+        */
+       public int getKind() {
+               return IBinding.VARIABLE;
+       }
+
+       /*
+        * @see IBinding#getModifiers()
+        */
+       public int getModifiers() {
+               if (isField()) {
+                       return ((FieldBinding) this.binding).getAccessFlags() & VALID_MODIFIERS;
+               }
+               if (binding.isFinal()) {
+                       return IModifierConstants.ACC_FINAL;
+               }
+               return Modifier.NONE;
+       }
+
+       /*
+        * @see IBinding#getName()
+        */
+       public String getName() {
+               if (this.name == null) {
+                       this.name = new String(this.binding.name);
+               }
+               return this.name;
+       }
+
+       /*
+        * @see IVariableBinding#getType()
+        */
+       public ITypeBinding getType() {
+               if (this.type == null) {
+                       this.type = this.resolver.getTypeBinding(this.binding.type);
+               }
+               return this.type;
+       }
+
+       private JavaElement getUnresolvedJavaElement() {
+               if (isField()) {
+                       if (this.resolver instanceof DefaultBindingResolver) {
+                               DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
+                               return Util.getUnresolvedJavaElement(
+                                               (FieldBinding) this.binding,
+                                               defaultBindingResolver.workingCopyOwner,
+                                               defaultBindingResolver.getBindingsToNodesMap());
+                       } else {
+                               return Util.getUnresolvedJavaElement((FieldBinding) this.binding, null, null);
+                       }
+               }
+               // local variable
+               IMethodBinding declaringMethod = getDeclaringMethod();
+               if (declaringMethod == null) return null;
+               JavaElement method = (JavaElement) declaringMethod.getJavaElement();
+               if (method == null) return null;
+               if (!(this.resolver instanceof DefaultBindingResolver)) return null;
+               VariableDeclaration localVar = (VariableDeclaration) ((DefaultBindingResolver) this.resolver).bindingsToAstNodes.get(this);
+               if (localVar == null) return null;
+               int nameStart;
+               int nameLength;
+               int sourceStart;
+               int sourceLength;
+               if (localVar instanceof SingleVariableDeclaration) {
+                       sourceStart = localVar.getStartPosition();
+                       sourceLength = localVar.getLength();
+                       SimpleName simpleName = ((SingleVariableDeclaration) localVar).getName();
+                       nameStart = simpleName.getStartPosition();
+                       nameLength = simpleName.getLength();
+               } else {
+                       nameStart =  localVar.getStartPosition();
+                       nameLength = localVar.getLength();
+                       ASTNode node = localVar.getParent();
+                       sourceStart = node.getStartPosition();
+                       sourceLength = node.getLength();
+               }
+               char[] typeSig = this.binding.type.genericTypeSignature();
+               return new LocalVariable(method, localVar.getName().getIdentifier(), sourceStart, sourceStart+sourceLength-1, nameStart, nameStart+nameLength-1, new String(typeSig), ((LocalVariableBinding) this.binding).declaration.annotations);
+       }
+
+       /*
+        * @see IVariableBinding#getVariableDeclaration()
+        * @since 3.1
+        */
+       public IVariableBinding getVariableDeclaration() {
+               if (this.isField()) {
+                       FieldBinding fieldBinding = (FieldBinding) this.binding;
+                       return this.resolver.getVariableBinding(fieldBinding.original());
+               }
+               return this;
+       }
+
+       /*
+        * @see IVariableBinding#getVariableId()
+        */
+       public int getVariableId() {
+               return this.binding.id;
+       }
+
+       /*
+        * @see IVariableBinding#isParameter()
+        */
+       public boolean isParameter() {
+               return (this.binding.tagBits & TagBits.IsArgument) != 0;
+       }
+       /*
+        * @see IBinding#isDeprecated()
+        */
+       public boolean isDeprecated() {
+               if (isField()) {
+                       return ((FieldBinding) this.binding).isDeprecated();
+               }
+               return false;
+       }
+
+       /*
+        * @see IVariableBinding#isEnumConstant()
+        * @since 3.1
+        */
+       public boolean isEnumConstant() {
+               return (this.binding.modifiers & ClassFileConstants.AccEnum) != 0;
+       }
+
+       /*
+        * @see IBinding#isEqualTo(Binding)
+        * @since 3.1
+        */
+       public boolean isEqualTo(IBinding other) {
+               if (other == this) {
+                       // identical binding - equal (key or no key)
+                       return true;
+               }
+               if (other == null) {
+                       // other binding missing
+                       return false;
+               }
+               if (!(other instanceof VariableBinding)) {
+                       return false;
+               }
+               net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding otherBinding = ((VariableBinding) other).binding;
+               if (this.binding instanceof FieldBinding) {
+                       if (otherBinding instanceof FieldBinding) {
+                               return BindingComparator.isEqual((FieldBinding) this.binding, (FieldBinding) otherBinding);
+                       } else {
+                               return false;
+                       }
+               } else {
+                       if (BindingComparator.isEqual(this.binding, otherBinding)) {
+                               IMethodBinding declaringMethod = this.getDeclaringMethod();
+                               IMethodBinding otherDeclaringMethod = ((VariableBinding) other).getDeclaringMethod();
+                               if (declaringMethod == null) {
+                                       if (otherDeclaringMethod != null) {
+                                               return false;
+                                       }
+                                       return true;
+                               }
+                               return declaringMethod.isEqualTo(otherDeclaringMethod);
+                       }
+                       return false;
+               }
+       }
+
+       /*
+        * @see IVariableBinding#isField()
+        */
+       public boolean isField() {
+               return this.binding instanceof FieldBinding;
+       }
+
+       /*
+        * @see IBinding#isSynthetic()
+        */
+       public boolean isSynthetic() {
+               if (isField()) {
+                       return ((FieldBinding) this.binding).isSynthetic();
+               }
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see org.eclipse.jdt.core.dom.IBinding#isRecovered()
+        */
+       public boolean isRecovered() {
+               return false;
+       }
+
+       /*
+        * For debugging purpose only.
+        * @see java.lang.Object#toString()
+        */
+       public String toString() {
+               return this.binding.toString();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclaration.java
new file mode 100644 (file)
index 0000000..8825c75
--- /dev/null
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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 net.sourceforge.phpdt.core.dom;
+
+/**
+ * Abstract base class of all AST node types that declare a single local 
+ * variable.
+ * <p>
+ * <pre>
+ * VariableDeclaration:
+ *    SingleVariableDeclaration
+ *    VariableDeclarationFragment
+ * </pre>
+ * </p>
+ * 
+ * @see SingleVariableDeclaration
+ * @see VariableDeclarationFragment
+ * @since 2.0
+ */
+public abstract class VariableDeclaration extends ASTNode {
+       
+       /**
+        * Returns structural property descriptor for the "extraDimensions" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        * @since 3.1
+        */
+       abstract SimplePropertyDescriptor internalExtraDimensionsProperty();
+
+       /**
+        * Returns structural property descriptor for the "extraDimensions" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        * @since 3.1
+        */
+       public final SimplePropertyDescriptor getExtraDimensionsProperty() {
+               return internalExtraDimensionsProperty();
+       }
+
+       /**
+        * Returns structural property descriptor for the "initializer" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        * @since 3.1
+        */
+       abstract ChildPropertyDescriptor internalInitializerProperty();
+
+       /**
+        * Returns structural property descriptor for the "initializer" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        * @since 3.1
+        */
+       public final ChildPropertyDescriptor getInitializerProperty() {
+               return internalInitializerProperty();
+       }
+
+       /**
+        * Returns structural property descriptor for the "name" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        * @since 3.1
+        */
+       abstract ChildPropertyDescriptor internalNameProperty();
+
+       /**
+        * Returns structural property descriptor for the "name" property
+        * of this node.
+        * 
+        * @return the property descriptor
+        * @since 3.1
+        */
+       public final ChildPropertyDescriptor getNameProperty() {
+               return internalNameProperty();
+       }
+
+       /**
+        * Creates a new AST node for a variable declaration owned by the given AST.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       VariableDeclaration(AST ast) {
+               super(ast);
+       }
+       
+       /**
+        * Returns the name of the variable declared in this variable declaration.
+        * 
+        * @return the variable name node
+        */ 
+       public abstract SimpleName getName();
+               
+       /**
+        * Sets the name of the variable declared in this variable declaration 
+        * to the given name.
+        * 
+        * @param variableName the new variable name
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public abstract void setName(SimpleName variableName);
+
+       /**
+        * Returns the number of extra array dimensions over and above the 
+        * explicitly-specified type.
+        * <p>
+        * For example, <code>int x[][]</code> has a type of 
+        * <code>int</code> and two extra array dimensions; 
+        * <code>int[][] x</code> has a type of <code>int[][]</code>
+        * and zero extra array dimensions. The two constructs have different
+        * ASTs, even though there are really syntactic variants of the same
+        * variable declaration.
+        * </p>
+        * 
+        * @return the number of extra array dimensions
+        * @since 2.1
+        */ 
+       public abstract int getExtraDimensions();
+
+       /**
+        * Sets the number of extra array dimensions over and above the 
+        * explicitly-specified type.
+        * <p>
+        * For example, <code>int x[][]</code> has a type of 
+        * <code>int</code> and two extra array dimensions; 
+        * <code>int[][] x</code> has a type of <code>int[][]</code>
+        * and zero extra array dimensions. The two constructs have different
+        * ASTs, even though there are really syntactic variants of the same
+        * variable declaration.
+        * </p>
+        * 
+        * @param dimensions the number of array dimensions
+        * @exception IllegalArgumentException if the number of dimensions is
+        *    negative
+        * @since 2.1
+        */ 
+       public abstract void setExtraDimensions(int dimensions);
+
+       /**
+        * Returns the initializer of this variable declaration, or 
+        * <code>null</code> if there is none.
+        * 
+        * @return the initializer expression node, or <code>null</code> if 
+        *    there is none
+        */ 
+       public abstract Expression getInitializer();
+       
+       /**
+        * Sets or clears the initializer of this variable declaration.
+        * 
+        * @param initializer the initializer expression node, or <code>null</code>
+        *    if there is none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public abstract void setInitializer(Expression initializer);
+
+       /**
+        * Resolves and returns the binding for the variable declared in this
+        * variable declaration.
+        * <p>
+        * Note that bindings are generally unavailable unless requested when the
+        * AST is being built.
+        * </p>
+        * 
+        * @return the binding, or <code>null</code> if the binding cannot be 
+        *    resolved
+        */     
+       public IVariableBinding resolveBinding() {
+               return this.ast.getBindingResolver().resolveVariable(this);
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclarationExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclarationExpression.java
new file mode 100644 (file)
index 0000000..f6ce5f3
--- /dev/null
@@ -0,0 +1,435 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Local variable declaration expression AST node type.
+ * <p>
+ * This kind of node collects together several variable declaration fragments
+ * (<code>VariableDeclarationFragment</code>) into a single expression
+ * (<code>Expression</code>), all sharing the same modifiers and base type.
+ * This type of node can be used as the initializer of a
+ * <code>ForStatement</code>, or wrapped in an <code>ExpressionStatement</code>
+ * to form the equivalent of a <code>VariableDeclarationStatement</code>.
+ * </p>
+ * For JLS2:
+ * <pre>
+ * VariableDeclarationExpression:
+ *    { Modifier } Type VariableDeclarationFragment
+ *         { <b>,</b> VariableDeclarationFragment } 
+ * </pre>
+ * For JLS3, the modifier flags were replaced by
+ * a list of modifier nodes (intermixed with annotations):
+ * <pre>
+ * VariableDeclarationExpression:
+ *    { ExtendedModifier } Type VariableDeclarationFragment
+ *         { <b>,</b> VariableDeclarationFragment } 
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class VariableDeclarationExpression extends Expression {
+
+       /**
+        * The "modifiers" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor MODIFIERS_PROPERTY = 
+               new SimplePropertyDescriptor(VariableDeclarationExpression.class, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "modifiers" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
+               new ChildListPropertyDescriptor(VariableDeclarationExpression.class, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "type" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(VariableDeclarationExpression.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "fragments" structural property of this node type).
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(VariableDeclarationExpression.class, "fragments", VariableDeclarationFragment.class, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List propertyList = new ArrayList(4);
+               createPropertyList(VariableDeclarationExpression.class, propertyList);
+               addProperty(MODIFIERS_PROPERTY, propertyList);
+               addProperty(TYPE_PROPERTY, propertyList);
+               addProperty(FRAGMENTS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+               
+               propertyList = new ArrayList(4);
+               createPropertyList(VariableDeclarationExpression.class, propertyList);
+               addProperty(MODIFIERS2_PROPERTY, propertyList);
+               addProperty(TYPE_PROPERTY, propertyList);
+               addProperty(FRAGMENTS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The extended modifiers (element type: <code>IExtendedModifier</code>). 
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * @since 3.0
+        */
+       private ASTNode.NodeList modifiers = null;
+       
+       /**
+        * The modifier flags; bit-wise or of Modifier flags.
+        * Defaults to none. Not used in 3.0.
+        */
+       private int modifierFlags = Modifier.NONE;
+               
+       /**
+        * The base type; lazily initialized; defaults to an unspecified,
+        * legal type.
+        */
+       private Type baseType = null;
+
+       /**
+        * The list of variable declaration fragments (element type: 
+        * <code VariableDeclarationFragment</code>).  Defaults to an empty list.
+        */
+       private ASTNode.NodeList variableDeclarationFragments = 
+               new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+       /**
+        * Creates a new unparented local variable declaration expression node
+        * owned by the given AST.  By default, the variable declaration has: no
+        * modifiers, an unspecified (but legal) type, and an empty list of variable
+        * declaration fragments (which is syntactically illegal).
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       VariableDeclarationExpression(AST ast) {
+               super(ast);
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY);
+               }
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+               if (property == MODIFIERS_PROPERTY) {
+                       if (get) {
+                               return getModifiers();
+                       } else {
+                               setModifiers(value);
+                               return 0;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetIntProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == TYPE_PROPERTY) {
+                       if (get) {
+                               return getType();
+                       } else {
+                               setType((Type) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == MODIFIERS2_PROPERTY) {
+                       return modifiers();
+               }
+               if (property == FRAGMENTS_PROPERTY) {
+                       return fragments();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return VARIABLE_DECLARATION_EXPRESSION;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               VariableDeclarationExpression result = 
+                       new VariableDeclarationExpression(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                       result.setModifiers(getModifiers());
+               }
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+               }
+               result.setType((Type) getType().clone(target));
+               result.fragments().addAll(
+                       ASTNode.copySubtrees(target, fragments()));
+               return result;
+
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChildren(visitor, this.modifiers);
+                       }
+                       acceptChild(visitor, getType());
+                       acceptChildren(visitor, variableDeclarationFragments);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the live ordered list of modifiers and annotations
+        * of this declaration (added in JLS3 API).
+        * <p>
+        * Note that the final modifier is the only meaningful modifier for local
+        * variable declarations.
+        * </p>
+        * 
+        * @return the live list of modifiers and annotations
+        *    (element type: <code>IExtendedModifier</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public List modifiers() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.modifiers == null) {
+                       unsupportedIn2();
+               }
+               return this.modifiers;
+       }
+       
+       /**
+        * Returns the modifiers explicitly specified on this declaration.
+        * <p>
+        * In the JLS3 API, this method is a convenience method that
+        * computes these flags from <code>modifiers()</code>.
+        * </p>
+        * 
+        * @return the bit-wise or of <code>Modifier</code> constants
+        * @see Modifier
+        */ 
+       public int getModifiers() {
+               // more efficient than checking getAST().API_LEVEL
+               if (this.modifiers == null) {
+                       // JLS2 behavior - bona fide property
+                       return this.modifierFlags;
+               } else {
+                       // JLS3 behavior - convenient method
+                       // performance could be improved by caching computed flags
+                       // but this would require tracking changes to this.modifiers
+                       int computedModifierFlags = Modifier.NONE;
+                       for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+                               Object x = it.next();
+                               if (x instanceof Modifier) {
+                                       computedModifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+                               }
+                       }
+                       return computedModifierFlags;
+               }
+       }
+
+       /**
+        * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+        * <p>
+        * Note that the final modifier is the only meaningful modifier for local
+        * variable declarations.
+        * </p>
+        * 
+        * @param modifiers the given modifiers (bit-wise or of <code>Modifier</code> constants)
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @see Modifier
+        * @deprecated In the JLS3 API, this method is replaced by 
+        * {@link  #modifiers()} which contains a list of a <code>Modifier</code> nodes.
+        */ 
+       public void setModifiers(int modifiers) {
+               internalSetModifiers(modifiers);
+       }
+       
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ final void internalSetModifiers(int pmodifiers) {
+           supportedOnlyIn2();
+               preValueChange(MODIFIERS_PROPERTY);
+               this.modifierFlags = pmodifiers;
+               postValueChange(MODIFIERS_PROPERTY);
+       }
+
+       /**
+        * Returns the base type declared in this variable declaration.
+        * <p>
+        * N.B. The individual child variable declaration fragments may specify 
+        * additional array dimensions. So the type of the variable are not 
+        * necessarily exactly this type.
+        * </p>
+        * 
+        * @return the base type
+        */ 
+       public Type getType() {
+               if (this.baseType == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.baseType == null) {
+                                       preLazyInit();
+                                       this.baseType = this.ast.newPrimitiveType(PrimitiveType.INT);
+                                       postLazyInit(this.baseType, TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.baseType;
+       }
+
+       /**
+        * Sets the base type declared in this variable declaration to the given
+        * type.
+        * 
+        * @param type the new base type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setType(Type type) {
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.baseType;
+               preReplaceChild(oldChild, type, TYPE_PROPERTY);
+               this.baseType = type;
+               postReplaceChild(oldChild, type, TYPE_PROPERTY);
+       }
+
+       /**
+        * Returns the live list of variable declaration fragments in this 
+        * expression. Adding and removing nodes from this list affects this node
+        * dynamically. All nodes in this list must be 
+        * <code>VariableDeclarationFragment</code>s; attempts to add any other
+        * type of node will trigger an exception.
+        * 
+        * @return the live list of variable declaration fragments in this 
+        *    expression (element type: <code>VariableDeclarationFragment</code>)
+        */ 
+       public List fragments() {
+               return this.variableDeclarationFragments;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Operator as free
+               return BASE_NODE_SIZE + 4 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.modifiers == null ? 0 : this.modifiers.listSize())
+                       + (this.baseType == null ? 0 : getType().treeSize())
+                       + this.variableDeclarationFragments.listSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclarationFragment.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclarationFragment.java
new file mode 100644 (file)
index 0000000..0a437ac
--- /dev/null
@@ -0,0 +1,334 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Variable declaration fragment AST node type, used in field declarations, 
+ * local variable declarations, and <code>ForStatement</code> initializers.
+ * It contrast to <code>SingleVariableDeclaration</code>, fragments are
+ * missing the modifiers and the type; these are located in the fragment's
+ * parent node.
+ *
+ * <pre>
+ * VariableDeclarationFragment:
+ *    Identifier { <b>[</b><b>]</b> } [ <b>=</b> Expression ]
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class VariableDeclarationFragment extends VariableDeclaration {
+               
+       /**
+        * The "name" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor NAME_PROPERTY = 
+               new ChildPropertyDescriptor(VariableDeclarationFragment.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "extraDimensions" structural property of this node type.
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor EXTRA_DIMENSIONS_PROPERTY = 
+               new SimplePropertyDescriptor(VariableDeclarationFragment.class, "extraDimensions", int.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "initializer" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor INITIALIZER_PROPERTY = 
+               new ChildPropertyDescriptor(VariableDeclarationFragment.class, "initializer", Expression.class, OPTIONAL, 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;
+               
+       static {
+               List propertyList = new ArrayList(4);
+               createPropertyList(VariableDeclarationFragment.class, propertyList);
+               addProperty(NAME_PROPERTY, propertyList);
+               addProperty(EXTRA_DIMENSIONS_PROPERTY, propertyList);
+               addProperty(INITIALIZER_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 variable name; lazily initialized; defaults to an unspecified,
+        * legal Java identifier.
+        */
+       private SimpleName variableName = null;
+
+       /**
+        * The number of extra array dimensions that this variable has;
+        * defaults to 0.
+        */
+       private int extraArrayDimensions = 0;
+
+       /**
+        * The initializer expression, or <code>null</code> if none;
+        * defaults to none.
+        */
+       private Expression optionalInitializer = null;
+       
+       /**
+        * Creates a new AST node for a variable declaration fragment owned by the 
+        * given AST. By default, the variable declaration has: an unspecified 
+        * (but legal) variable name, no initializer, and no extra array dimensions.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       VariableDeclarationFragment(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        * @since 3.1
+        */
+       final SimplePropertyDescriptor internalExtraDimensionsProperty() {
+               return EXTRA_DIMENSIONS_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        * @since 3.1
+        */
+       final ChildPropertyDescriptor internalInitializerProperty() {
+               return INITIALIZER_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        * @since 3.1
+        */
+       final ChildPropertyDescriptor internalNameProperty() {
+               return NAME_PROPERTY;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+               if (property == EXTRA_DIMENSIONS_PROPERTY) {
+                       if (get) {
+                               return getExtraDimensions();
+                       } else {
+                               setExtraDimensions(value);
+                               return 0;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetIntProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == NAME_PROPERTY) {
+                       if (get) {
+                               return getName();
+                       } else {
+                               setName((SimpleName) child);
+                               return null;
+                       }
+               }
+               if (property == INITIALIZER_PROPERTY) {
+                       if (get) {
+                               return getInitializer();
+                       } else {
+                               setInitializer((Expression) 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.
+        */
+       final int getNodeType0() {
+               return VARIABLE_DECLARATION_FRAGMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               VariableDeclarationFragment result = new VariableDeclarationFragment(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setName((SimpleName) getName().clone(target));
+               result.setExtraDimensions(getExtraDimensions());
+               result.setInitializer(
+                       (Expression) ASTNode.copySubtree(target, getInitializer()));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getName());
+                       acceptChild(visitor, getInitializer());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        */ 
+       public SimpleName getName() {
+               if (this.variableName == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.variableName == null) {
+                                       preLazyInit();
+                                       this.variableName = new SimpleName(this.ast);
+                                       postLazyInit(this.variableName, NAME_PROPERTY);
+                               }
+                       }
+               }
+               return this.variableName;
+       }
+               
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        */ 
+       public void setName(SimpleName variableName) {
+               if (variableName == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.variableName;
+               preReplaceChild(oldChild, variableName, NAME_PROPERTY);
+               this.variableName = variableName;
+               postReplaceChild(oldChild, variableName, NAME_PROPERTY);
+       }
+
+       /**
+        * Returns the number of extra array dimensions this variable has over
+        * and above the type specified in the enclosing declaration.
+        * <p>
+        * For example, in the AST for <code>int[] i, j[], k[][]</code> the 
+        * variable declaration fragments for the variables <code>i</code>,
+        * <code>j</code>, and <code>k</code>, have 0, 1, and 2 extra array
+        * dimensions, respectively.
+        * </p>
+        * 
+        * @return the number of extra array dimensions this variable has over
+        *         and above the type specified in the enclosing declaration
+        * @since 2.0
+        */ 
+       public int getExtraDimensions() {
+               return this.extraArrayDimensions;
+       }
+
+       /**
+        * Sets the number of extra array dimensions this variable has over
+        * and above the type specified in the enclosing declaration.
+        * <p>
+        * For example, in the AST for <code>int[] i, j[], k[][]</code> the 
+        * variable declaration fragments for the variables <code>i</code>,
+        * <code>j</code>, and <code>k</code>, have 0, 1, and 2 extra array
+        * dimensions, respectively.
+        * </p>
+        * 
+        * @param dimensions the given dimensions
+        * @since 2.0
+        */ 
+       public void setExtraDimensions(int dimensions) {
+               if (dimensions < 0) {
+                       throw new IllegalArgumentException();
+               }
+               preValueChange(EXTRA_DIMENSIONS_PROPERTY);
+               this.extraArrayDimensions = dimensions;
+               postValueChange(EXTRA_DIMENSIONS_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        */ 
+       public Expression getInitializer() {
+               return this.optionalInitializer;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on VariableDeclaration.
+        */ 
+       public void setInitializer(Expression initializer) {
+               ASTNode oldChild = this.optionalInitializer;
+               preReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+               this.optionalInitializer = initializer;
+               postReplaceChild(oldChild, initializer, INITIALIZER_PROPERTY);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               // treat Operator as free
+               return BASE_NODE_SIZE + 3 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+                       memSize()
+                       + (this.variableName == null ? 0 : getName().treeSize())
+                       + (this.optionalInitializer == null ? 0 : getInitializer().treeSize());
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclarationStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/VariableDeclarationStatement.java
new file mode 100644 (file)
index 0000000..f504290
--- /dev/null
@@ -0,0 +1,437 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Local variable declaration statement AST node type.
+ * <p>
+ * This kind of node collects several variable declaration fragments
+ * (<code>VariableDeclarationFragment</code>) into a statement 
+ * (<code>Statement</code>), all sharing the same modifiers and base type.
+ * </p>
+ * For JLS2:
+ * <pre>
+ * VariableDeclarationStatement:
+ *    { Modifier } Type VariableDeclarationFragment 
+ *        { <b>,</b> VariableDeclarationFragment } <b>;</b>
+ * </pre>
+ * For JLS3, the modifier flags were replaced by
+ * a list of modifier nodes (intermixed with annotations):
+ * <pre>
+ * VariableDeclarationStatement:
+ *    { ExtendedModifier } Type VariableDeclarationFragment 
+ *        { <b>,</b> VariableDeclarationFragment } <b>;</b>
+ * </pre>
+ * <p>
+ * Note: This type of node is a convenience of sorts. 
+ * An equivalent way to represent the same statement is to use
+ * a <code>VariableDeclarationExpression</code>
+ * wrapped in an <code>ExpressionStatement</code>.
+ * </p>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class VariableDeclarationStatement extends Statement {
+       
+       /**
+        * The "modifiers" structural property of this node type (JLS2 API only).
+        * @since 3.0
+        */
+       public static final SimplePropertyDescriptor MODIFIERS_PROPERTY = 
+               new SimplePropertyDescriptor(VariableDeclarationStatement.class, "modifiers", int.class, MANDATORY); //$NON-NLS-1$
+       
+       /**
+        * The "modifiers" structural property of this node type (added in JLS3 API).
+        * @since 3.1
+        */
+       public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = 
+               new ChildListPropertyDescriptor(VariableDeclarationStatement.class, "modifiers", IExtendedModifier.class, CYCLE_RISK); //$NON-NLS-1$
+       
+       /**
+        * The "type" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor TYPE_PROPERTY = 
+               new ChildPropertyDescriptor(VariableDeclarationStatement.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "fragments" structural property of this node type).
+        * @since 3.0
+        */
+       public static final ChildListPropertyDescriptor FRAGMENTS_PROPERTY = 
+               new ChildListPropertyDescriptor(VariableDeclarationStatement.class, "fragments", VariableDeclarationFragment.class, 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_2_0;
+       
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        * @since 3.1
+        */
+       private static final List PROPERTY_DESCRIPTORS_3_0;
+       
+       static {
+               List propertyList = new ArrayList(4);
+               createPropertyList(VariableDeclarationStatement.class, propertyList);
+               addProperty(MODIFIERS_PROPERTY, propertyList);
+               addProperty(TYPE_PROPERTY, propertyList);
+               addProperty(FRAGMENTS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
+               
+               propertyList = new ArrayList(4);
+               createPropertyList(VariableDeclarationStatement.class, propertyList);
+               addProperty(MODIFIERS2_PROPERTY, propertyList);
+               addProperty(TYPE_PROPERTY, propertyList);
+               addProperty(FRAGMENTS_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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) {
+               if (apiLevel == AST.JLS2_INTERNAL) {
+                       return PROPERTY_DESCRIPTORS_2_0;
+               } else {
+                       return PROPERTY_DESCRIPTORS_3_0;
+               }
+       }
+                       
+       /**
+        * The extended modifiers (element type: <code>IExtendedModifier</code>). 
+        * Null in JLS2. Added in JLS3; defaults to an empty list
+        * (see constructor).
+        * @since 3.1
+        */
+       private ASTNode.NodeList modifiers = null;
+       
+       /**
+        * The modifier flagss; bit-wise or of Modifier flags.
+        * Defaults to none. Not used in JLS3.
+        */
+       private int modifierFlags = Modifier.NONE;
+               
+       /**
+        * The base type; lazily initialized; defaults to an unspecified,
+        * legal type.
+        */
+       private Type baseType = null;
+
+       /**
+        * The list of variable variable declaration fragments (element type: 
+        * <code VariableDeclarationFragment</code>).  Defaults to an empty list.
+        */
+       private ASTNode.NodeList variableDeclarationFragments = 
+               new ASTNode.NodeList(FRAGMENTS_PROPERTY);
+
+       /**
+        * Creates a new unparented local variable declaration statement node owned 
+        * by the given AST.  By default, the variable declaration has: no modifiers,
+        * an unspecified (but legal) type, and an empty list of variable 
+        * declaration fragments (which is syntactically illegal).
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       VariableDeclarationStatement(AST ast) {
+               super(ast);
+               if (ast.apiLevel >= AST.JLS3) {
+                       this.modifiers = new ASTNode.NodeList(MODIFIERS2_PROPERTY);
+               }
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) {
+               if (property == MODIFIERS_PROPERTY) {
+                       if (get) {
+                               return getModifiers();
+                       } else {
+                               setModifiers(value);
+                               return 0;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetIntProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == TYPE_PROPERTY) {
+                       if (get) {
+                               return getType();
+                       } else {
+                               setType((Type) 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.
+        */
+       final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+               if (property == MODIFIERS2_PROPERTY) {
+                       return modifiers();
+               }
+               if (property == FRAGMENTS_PROPERTY) {
+                       return fragments();
+               }
+               // allow default implementation to flag the error
+               return super.internalGetChildListProperty(property);
+       }
+               
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final int getNodeType0() {
+               return VARIABLE_DECLARATION_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               VariableDeclarationStatement result = 
+                       new VariableDeclarationStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
+                       result.setModifiers(getModifiers());
+               }
+               if (this.ast.apiLevel >= AST.JLS3) {
+                       result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers()));
+               }
+               result.setType((Type) getType().clone(target));
+               result.fragments().addAll(
+                       ASTNode.copySubtrees(target, fragments()));
+               return result;
+       }
+       
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       if (this.ast.apiLevel >= AST.JLS3) {
+                               acceptChildren(visitor, this.modifiers);
+                       }
+                       acceptChild(visitor, getType());
+                       acceptChildren(visitor, this.variableDeclarationFragments);
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the live ordered list of modifiers and annotations
+        * of this declaration (added in JLS3 API).
+        * <p>
+        * Note that the final modifier is the only meaningful modifier for local
+        * variable declarations.
+        * </p>
+        * 
+        * @return the live list of modifiers and annotations
+        *    (element type: <code>IExtendedModifier</code>)
+        * @exception UnsupportedOperationException if this operation is used in
+        * a JLS2 AST
+        * @since 3.1
+        */ 
+       public List modifiers() {
+               // more efficient than just calling unsupportedIn2() to check
+               if (this.modifiers == null) {
+                       unsupportedIn2();
+               }
+               return this.modifiers;
+       }
+       
+       /**
+        * Returns the modifiers explicitly specified on this declaration.
+        * <p>
+        * In the JLS3 API, this method is a convenience method that
+        * computes these flags from <code>modifiers()</code>.
+        * </p>
+        * 
+        * @return the bit-wise or of <code>Modifier</code> constants
+        * @see Modifier
+        */ 
+       public int getModifiers() {
+               // more efficient than checking getAST().API_LEVEL
+               if (this.modifiers == null) {
+                       // JLS2 behavior - bona fide property
+                       return this.modifierFlags;
+               } else {
+                       // JLS3 behavior - convenience method
+                       // performance could be improved by caching computed flags
+                       // but this would require tracking changes to this.modifiers
+                       int computedModifierFlags = Modifier.NONE;
+                       for (Iterator it = modifiers().iterator(); it.hasNext(); ) {
+                               Object x = it.next();
+                               if (x instanceof Modifier) {
+                                       computedModifierFlags |= ((Modifier) x).getKeyword().toFlagValue();
+                               }
+                       }
+                       return computedModifierFlags;
+               }
+       }
+
+       /**
+        * Sets the modifiers explicitly specified on this declaration (JLS2 API only).
+        * <p>
+        * Note that the final modifier is the only meaningful modifier for local
+        * variable declarations.
+        * </p>
+        * 
+        * @param modifiers the given modifiers (bit-wise or of <code>Modifier</code> constants)
+        * @exception UnsupportedOperationException if this operation is used in
+        * an AST later than JLS2
+        * @see Modifier
+        * @deprecated In the JLS3 API, this method is replaced by 
+        * {@link  #modifiers()} which contains a list of a <code>Modifier</code> nodes.
+        */ 
+       public void setModifiers(int modifiers) {
+               internalSetModifiers(modifiers);
+       }
+       
+       /**
+        * Internal synonym for deprecated method. Used to avoid
+        * deprecation warnings.
+        * @since 3.1
+        */
+       /*package*/ final void internalSetModifiers(int pmodifiers) {
+           supportedOnlyIn2();
+               preValueChange(MODIFIERS_PROPERTY);
+               this.modifierFlags = pmodifiers;
+               postValueChange(MODIFIERS_PROPERTY);
+       }
+
+       /**
+        * Returns the base type declared in this variable declaration statement.
+        * <p>
+        * N.B. The individual child variable declaration fragments may specify
+        * additional array dimensions. So the type of the variable are not 
+        * necessarily exactly this type.
+        * </p>
+        * 
+        * @return the base type
+        */ 
+       public Type getType() {
+               if (this.baseType == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.baseType == null) {
+                                       preLazyInit();
+                                       this.baseType = this.ast.newPrimitiveType(PrimitiveType.INT);
+                                       postLazyInit(this.baseType, TYPE_PROPERTY);
+                               }
+                       }
+               }
+               return this.baseType;
+       }
+
+       /**
+        * Sets the base type declared in this variable declaration statement to 
+        * the given type.
+        * 
+        * @param type the new base type
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        */ 
+       public void setType(Type type) {
+               if (type == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.baseType;
+               preReplaceChild(oldChild, type, TYPE_PROPERTY);
+               this.baseType = type;
+               postReplaceChild(oldChild, type, TYPE_PROPERTY);
+       }
+
+       /**
+        * Returns the live list of variable declaration fragments in this statement.
+        * Adding and removing nodes from this list affects this node dynamically.
+        * All nodes in this list must be <code>VariableDeclarationFragment</code>s;
+        * attempts to add any other type of node will trigger an
+        * exception.
+        * 
+        * @return the live list of variable declaration fragments in this 
+        *    statement (element type: <code>VariableDeclarationFragment</code>)
+        */ 
+       public List fragments() {
+               return this.variableDeclarationFragments;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 4 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.modifiers == null ? 0 : this.modifiers.listSize())
+                       + (this.baseType == null ? 0 : getType().treeSize())
+                       + this.variableDeclarationFragments.listSize();
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/WhileStatement.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/WhileStatement.java
new file mode 100644 (file)
index 0000000..23c342b
--- /dev/null
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * While statement AST node type.
+ *
+ * <pre>
+ * WhileStatement:
+ *    <b>while</b> <b>(</b> Expression <b>)</b> Statement
+ * </pre>
+ * 
+ * @since 2.0
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class WhileStatement extends Statement {
+
+       /**
+        * The "expression" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
+               new ChildPropertyDescriptor(WhileStatement.class, "expression", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "body" structural property of this node type.
+        * @since 3.0
+        */
+       public static final ChildPropertyDescriptor BODY_PROPERTY = 
+               new ChildPropertyDescriptor(WhileStatement.class, "body", Statement.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(WhileStatement.class, propertyList);
+               addProperty(EXPRESSION_PROPERTY, propertyList);
+               addProperty(BODY_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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 expression; lazily initialized; defaults to an unspecified, but 
+        * legal, expression.
+        */
+       private Expression expression = null;
+
+       /**
+        * The body statement; lazily initialized; defaults to an empty block 
+        * statement.
+        */
+       private Statement body = null;
+
+       /**
+        * Creates a new unparented while statement node owned by the given 
+        * AST. By default, the expresssion is unspecified, but legal, and
+        * the body statement is an empty block.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       WhileStatement(AST ast) {
+               super(ast);
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == EXPRESSION_PROPERTY) {
+                       if (get) {
+                               return getExpression();
+                       } else {
+                               setExpression((Expression) child);
+                               return null;
+                       }
+               }
+               if (property == BODY_PROPERTY) {
+                       if (get) {
+                               return getBody();
+                       } else {
+                               setBody((Statement) 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.
+        */
+       final int getNodeType0() {
+               return WHILE_STATEMENT;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               WhileStatement result = new WhileStatement(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.copyLeadingComment(this);
+               result.setExpression((Expression) getExpression().clone(target));
+               result.setBody((Statement) getBody().clone(target));
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getExpression());
+                       acceptChild(visitor, getBody());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns the expression of this while statement.
+        * 
+        * @return the expression node
+        */ 
+       public Expression getExpression() {
+               if (this.expression == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.expression == null) {
+                                       preLazyInit();
+                                       this.expression = new SimpleName(this.ast);
+                                       postLazyInit(this.expression, EXPRESSION_PROPERTY);
+                               }
+                       }
+               }
+               return this.expression;
+       }
+       
+       /**
+        * Sets the expression of this while statement.
+        * 
+        * @param expression the expression node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setExpression(Expression expression) {
+               if (expression == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.expression;
+               preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+               this.expression = expression;
+               postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
+       }
+
+       /**
+        * Returns the body of this while statement.
+        * 
+        * @return the body statement node
+        */ 
+       public Statement getBody() {
+               if (this.body == null) {
+                       // lazy init must be thread-safe for readers
+                       synchronized (this) {
+                               if (this.body == null) {
+                                       preLazyInit();
+                                       this.body = new Block(this.ast);
+                                       postLazyInit(this.body, BODY_PROPERTY);
+                               }
+                       }
+               }
+               return this.body;
+       }
+       
+       /**
+        * Sets the body of this while statement.
+        * <p>
+        * Special note: The Java language does not allow a local variable declaration
+        * to appear as the body of a while statement (they may only appear within a
+        * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+        * as the body of a <code>WhileStatement</code>. To get something that will
+        * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+        * inside a <code>Block</code>.
+        * </p>
+        * 
+        * @param statement the body statement node
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * <li>a cycle in would be created</li>
+        * </ul>
+        */ 
+       public void setBody(Statement statement) {
+               if (statement == null) {
+                       throw new IllegalArgumentException();
+               }
+               ASTNode oldChild = this.body;
+               preReplaceChild(oldChild, statement, BODY_PROPERTY);
+               this.body = statement;
+               postReplaceChild(oldChild, statement, BODY_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return super.memSize() + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return
+                       memSize()
+                       + (this.expression == null ? 0 : getExpression().treeSize())
+                       + (this.body == null ? 0 : getBody().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/WildcardType.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/WildcardType.java
new file mode 100644 (file)
index 0000000..a326d8a
--- /dev/null
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2008 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 net.sourceforge.phpdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Type node for a wildcard type (added in JLS3 API).
+ * <pre>
+ * WildcardType:
+ *    <b>?</b> [ ( <b>extends</b> | <b>super</b>) Type ] 
+ * </pre>
+ * <p>
+ * Not all node arrangements will represent legal Java constructs. In particular,
+ * it is nonsense if a wildcard type node appears anywhere other than as an
+ * argument of a <code>ParameterizedType</code> node.
+ * </p>
+ * 
+ * @since 3.1
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class WildcardType extends Type {
+       
+       /**
+        * The "bound" structural property of this node type.
+        */
+       public static final ChildPropertyDescriptor BOUND_PROPERTY = 
+               new ChildPropertyDescriptor(WildcardType.class, "bound", Type.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
+
+       /**
+        * The "upperBound" structural property of this node type.
+        */
+       public static final SimplePropertyDescriptor UPPER_BOUND_PROPERTY = 
+               new SimplePropertyDescriptor(WildcardType.class, "upperBound", boolean.class, MANDATORY); //$NON-NLS-1$
+
+       /**
+        * A list of property descriptors (element type: 
+        * {@link StructuralPropertyDescriptor}),
+        * or null if uninitialized.
+        */
+       private static final List PROPERTY_DESCRIPTORS;
+       
+       static {
+               List propertyList = new ArrayList(3);
+               createPropertyList(WildcardType.class, propertyList);
+               addProperty(BOUND_PROPERTY, propertyList);
+               addProperty(UPPER_BOUND_PROPERTY, propertyList);
+               PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+       }
+
+       /**
+        * 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})
+        */
+       public static List propertyDescriptors(int apiLevel) {
+               return PROPERTY_DESCRIPTORS;
+       }
+                       
+       /** 
+        * The optional type bound node; <code>null</code> if none;
+        * defaults to none.
+        */
+       private Type optionalBound = null;
+       
+       /**
+        * Indicates whether the wildcard bound is an upper bound
+        * ("extends") as opposed to a lower bound ("super"). 
+        * Defaults to <code>true</code> initially.
+        */
+       private boolean isUpperBound = true;
+
+       /**
+        * Creates a new unparented node for a wildcard type owned by the
+        * given AST. By default, no upper bound.
+        * <p>
+        * N.B. This constructor is package-private.
+        * </p>
+        * 
+        * @param ast the AST that is to own this node
+        */
+       WildcardType(AST ast) {
+               super(ast);
+           unsupportedIn2();
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final List internalStructuralPropertiesForType(int apiLevel) {
+               return propertyDescriptors(apiLevel);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
+               if (property == UPPER_BOUND_PROPERTY) {
+                       if (get) {
+                               return isUpperBound();
+                       } else {
+                               setUpperBound(value);
+                               return false;
+                       }
+               }
+               // allow default implementation to flag the error
+               return super.internalGetSetBooleanProperty(property, get, value);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+               if (property == BOUND_PROPERTY) {
+                       if (get) {
+                               return getBound();
+                       } else {
+                               setBound((Type) 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.
+        */
+       final int getNodeType0() {
+               return WILDCARD_TYPE;
+       }
+
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       ASTNode clone0(AST target) {
+               WildcardType result = new WildcardType(target);
+               result.setSourceRange(this.getStartPosition(), this.getLength());
+               result.setBound((Type) ASTNode.copySubtree(target, getBound()), isUpperBound());
+               return result;
+       }
+
+       /* (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.
+        */
+       void accept0(ASTVisitor visitor) {
+               boolean visitChildren = visitor.visit(this);
+               if (visitChildren) {
+                       // visit children in normal left to right reading order
+                       acceptChild(visitor, getBound());
+               }
+               visitor.endVisit(this);
+       }
+       
+       /**
+        * Returns whether this wildcard type is an upper bound
+        * ("extends") as opposed to a lower bound ("super").
+        * <p>
+        * Note that this property is irrelevant for wildcards
+        * that do not have a bound.
+        * </p>
+        * 
+        * @return <code>true</code> if an upper bound,
+        *    and <code>false</code> if a lower bound
+        * @see #setBound(Type)
+        */ 
+       public boolean isUpperBound() {
+               return this.isUpperBound;
+       }
+       
+       /**
+        * Returns the bound of this wildcard type if it has one.
+        * If {@link #isUpperBound isUpperBound} returns true, this
+        * is an upper bound ("? extends B"); if it returns false, this
+        * is a lower bound ("? super B").
+        * 
+        * @return the bound of this wildcard type, or <code>null</code>
+        * if none
+        * @see #setBound(Type)
+        */ 
+       public Type getBound() {
+               return this.optionalBound;
+       }
+       
+       /**
+        * Sets the bound of this wildcard type to the given type and
+        * marks it as an upper or a lower bound. The method is
+        * equivalent to calling <code>setBound(type); setUpperBound(isUpperBound)</code>.
+        * 
+        * @param type the new bound of this wildcard type, or <code>null</code>
+        * if none
+        * @param isUpperBound <code>true</code> for an upper bound ("? extends B"),
+        * and <code>false</code> for a lower bound ("? super B")
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        * @see #getBound()
+        * @see #isUpperBound()
+        */ 
+       public void setBound(Type type, boolean isUpperBound) {
+               setBound(type);
+               setUpperBound(isUpperBound);
+       }
+
+       /**
+        * Sets the bound of this wildcard type to the given type.
+        * 
+        * @param type the new bound of this wildcard type, or <code>null</code>
+        * if none
+        * @exception IllegalArgumentException if:
+        * <ul>
+        * <li>the node belongs to a different AST</li>
+        * <li>the node already has a parent</li>
+        * </ul>
+        * @see #getBound()
+        */ 
+       public void setBound(Type type) {
+               ASTNode oldChild = this.optionalBound;
+               preReplaceChild(oldChild, type, BOUND_PROPERTY);
+               this.optionalBound = type;
+               postReplaceChild(oldChild, type, BOUND_PROPERTY);
+       }
+
+       /**
+        * Sets whether this wildcard type is an upper bound
+        * ("extends") as opposed to a lower bound ("super").
+        * 
+        * @param isUpperBound <code>true</code> if an upper bound,
+        *    and <code>false</code> if a lower bound
+        * @see #isUpperBound()
+        */ 
+       public void setUpperBound(boolean isUpperBound) {
+               preValueChange(UPPER_BOUND_PROPERTY);
+               this.isUpperBound = isUpperBound;
+               postValueChange(UPPER_BOUND_PROPERTY);
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int memSize() {
+               return BASE_NODE_SIZE + 2 * 4;
+       }
+       
+       /* (omit javadoc for this method)
+        * Method declared on ASTNode.
+        */
+       int treeSize() {
+               return 
+               memSize()
+               + (this.optionalBound == null ? 0 : getBound().treeSize());
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/Annotation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/Annotation.java
new file mode 100644 (file)
index 0000000..7c35c84
--- /dev/null
@@ -0,0 +1,407 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+/**
+ * Annotation
+ */
+public abstract class Annotation extends Expression {
+       
+       final static MemberValuePair[] NoValuePairs = new MemberValuePair[0];
+       public int declarationSourceEnd;
+       public Binding recipient;
+       
+       public TypeReference type;
+       /** 
+        *  The representation of this annotation in the type system. 
+        */
+       private AnnotationBinding compilerAnnotation = null;
+       
+       public static long getRetentionPolicy(char[] policyName) {
+               if (policyName == null || policyName.length == 0)
+                       return 0;
+               switch(policyName[0]) {
+                       case 'C' :
+                               if (CharOperation.equals(policyName, TypeConstants.UPPER_CLASS)) 
+                                       return TagBits.AnnotationClassRetention;
+                               break;
+                       case 'S' :
+                               if (CharOperation.equals(policyName, TypeConstants.UPPER_SOURCE)) 
+                                       return TagBits.AnnotationSourceRetention;
+                               break;
+                       case 'R' :
+                               if (CharOperation.equals(policyName, TypeConstants.UPPER_RUNTIME)) 
+                                       return TagBits.AnnotationRuntimeRetention;
+                               break;
+               }
+               return 0; // unknown
+       }
+       
+       public static long getTargetElementType(char[] elementName) {
+               if (elementName == null || elementName.length == 0)
+                       return 0;
+               switch(elementName[0]) {
+                       case 'A' :
+                               if (CharOperation.equals(elementName, TypeConstants.UPPER_ANNOTATION_TYPE)) 
+                                       return TagBits.AnnotationForAnnotationType;
+                               break;
+                       case 'C' :
+                               if (CharOperation.equals(elementName, TypeConstants.UPPER_CONSTRUCTOR)) 
+                                       return TagBits.AnnotationForConstructor;
+                               break;
+                       case 'F' :
+                               if (CharOperation.equals(elementName, TypeConstants.UPPER_FIELD)) 
+                                       return TagBits.AnnotationForField;
+                               break;
+                       case 'L' :
+                               if (CharOperation.equals(elementName, TypeConstants.UPPER_LOCAL_VARIABLE)) 
+                                       return TagBits.AnnotationForLocalVariable;
+                               break;
+                       case 'M' :
+                               if (CharOperation.equals(elementName, TypeConstants.UPPER_METHOD)) 
+                                       return TagBits.AnnotationForMethod;
+                               break;
+                       case 'P' :
+                               if (CharOperation.equals(elementName, TypeConstants.UPPER_PARAMETER)) 
+                                       return TagBits.AnnotationForParameter;
+                               else if (CharOperation.equals(elementName, TypeConstants.UPPER_PACKAGE)) 
+                                       return TagBits.AnnotationForPackage;
+                               break;
+                       case 'T' :
+                               if (CharOperation.equals(elementName, TypeConstants.TYPE)) 
+                                       return TagBits.AnnotationForType;
+                               break;
+               }
+               return 0; // unknown
+       }               
+
+       public ElementValuePair[] computeElementValuePairs() {
+               return Binding.NO_ELEMENT_VALUE_PAIRS;
+       }
+
+       /**
+        * Compute the bit pattern for recognized standard annotations the compiler may need to act upon
+        */
+       private long detectStandardAnnotation(Scope scope, ReferenceBinding annotationType, MemberValuePair valueAttribute) {
+               long tagBits = 0;
+               switch (annotationType.id) {
+                       // retention annotation
+                       case TypeIds.T_JavaLangAnnotationRetention :
+                               if (valueAttribute != null) {
+                                       Expression expr = valueAttribute.value;
+                                       if ((expr.bits & Binding.VARIABLE) == Binding.FIELD) {
+                                               FieldBinding field = ((Reference)expr).fieldBinding();
+                                               if (field != null && field.declaringClass.id == T_JavaLangAnnotationRetentionPolicy) {
+                                                       tagBits |= getRetentionPolicy(field.name);
+                                               }
+                                       }
+                               }
+                               break;
+                       // target annotation
+                       case TypeIds.T_JavaLangAnnotationTarget :               
+                               tagBits |= TagBits.AnnotationTarget; // target specified (could be empty)
+                               if (valueAttribute != null) {
+                                       Expression expr = valueAttribute.value;
+                                       if (expr instanceof ArrayInitializer) {
+                                               ArrayInitializer initializer = (ArrayInitializer) expr;
+                                               final Expression[] expressions = initializer.expressions;
+                                               if (expressions != null) {
+                                                       for (int i = 0, length = expressions.length; i < length; i++) {
+                                                               Expression initExpr = expressions[i];
+                                                               if ((initExpr.bits & Binding.VARIABLE) == Binding.FIELD) {
+                                                                       FieldBinding field = ((Reference) initExpr).fieldBinding();
+                                                                       if (field != null && field.declaringClass.id == T_JavaLangAnnotationElementType) {
+                                                                               long element = getTargetElementType(field.name);
+                                                                               if ((tagBits & element) != 0) {
+                                                                                       scope.problemReporter().duplicateTargetInTargetAnnotation(annotationType, (NameReference)initExpr);
+                                                                               } else {
+                                                                                       tagBits |= element;
+                                                                               }
+                                                                       }                                                       
+                                                               }
+                                                       }
+                                               }
+                                       } else if ((expr.bits & Binding.VARIABLE) == Binding.FIELD) {
+                                               FieldBinding field = ((Reference) expr).fieldBinding();
+                                               if (field != null && field.declaringClass.id == T_JavaLangAnnotationElementType) {
+                                                       tagBits |= getTargetElementType(field.name);
+                                               }
+                                       }
+                               }
+                               break;
+                       // marker annotations
+                       case TypeIds.T_JavaLangDeprecated :
+                               tagBits |= TagBits.AnnotationDeprecated;
+                               break;
+                       case TypeIds.T_JavaLangAnnotationDocumented :
+                               tagBits |= TagBits.AnnotationDocumented;
+                               break;
+                       case TypeIds.T_JavaLangAnnotationInherited :
+                               tagBits |= TagBits.AnnotationInherited;
+                               break;
+                       case TypeIds.T_JavaLangOverride :
+                               tagBits |= TagBits.AnnotationOverride;
+                               break;
+                       case TypeIds.T_JavaLangSuppressWarnings :
+                               tagBits |= TagBits.AnnotationSuppressWarnings;
+                               break;
+               }
+               return tagBits;
+       }
+
+       public AnnotationBinding getCompilerAnnotation() {
+               return this.compilerAnnotation;
+       }
+
+       public abstract MemberValuePair[] memberValuePairs();
+       
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+               output.append('@');
+               this.type.printExpression(0, output);
+               return output;
+       }
+       
+       public void recordSuppressWarnings(Scope scope, int startSuppresss, int endSuppress, boolean isSuppressingWarnings) {
+               long suppressWarningIrritants = 0;
+               MemberValuePair[] pairs = this.memberValuePairs();
+               pairLoop: for (int i = 0, length = pairs.length; i < length; i++) {
+                       MemberValuePair pair = pairs[i];
+                       if (CharOperation.equals(pair.name, TypeConstants.VALUE)) {
+                               Expression value = pair.value;
+                               if (value instanceof ArrayInitializer) {
+                                       ArrayInitializer initializer = (ArrayInitializer) value;
+                                       Expression[] inits = initializer.expressions;
+                                       if (inits != null) {
+                                               for (int j = 0, initsLength = inits.length; j < initsLength; j++) {
+                                                       Constant cst = inits[j].constant;
+                                                       if (cst != Constant.NotAConstant && cst.typeID() == T_JavaLangString) {
+                                                               long irritants = CompilerOptions.warningTokenToIrritants(cst.stringValue());
+                                                               if (irritants != 0) {
+                                                                       if ((suppressWarningIrritants & irritants) == irritants) {
+                                                                               scope.problemReporter().unusedWarningToken(inits[j]);
+                                                                       } else {
+                                                                               suppressWarningIrritants |= irritants;
+                                                                       }
+                                                               } else {
+                                                                       scope.problemReporter().unhandledWarningToken(inits[j]);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       Constant cst = value.constant;
+                                       if (cst != Constant.NotAConstant && cst.typeID() == T_JavaLangString) {
+                                               long irritants = CompilerOptions.warningTokenToIrritants(cst.stringValue());
+                                               if (irritants != 0) {
+                                                       suppressWarningIrritants |= irritants;
+                                               } else {
+                                                       scope.problemReporter().unhandledWarningToken(value);
+                                               }
+                                       }       
+                               }
+                               break pairLoop;
+                       }
+               }
+               if (isSuppressingWarnings && suppressWarningIrritants != 0) {
+                       scope.referenceCompilationUnit().recordSuppressWarnings(suppressWarningIrritants, this, startSuppresss, endSuppress);
+               }
+       }
+       
+       public TypeBinding resolveType(BlockScope scope) {
+
+               if (this.compilerAnnotation != null)
+                       return this.resolvedType;
+               this.constant = Constant.NotAConstant;
+               
+               TypeBinding typeBinding = this.type.resolveType(scope);
+               if (typeBinding == null) {
+                       return null;
+               }
+               this.resolvedType = typeBinding;
+               // ensure type refers to an annotation type
+               if (!typeBinding.isAnnotationType() && typeBinding.isValidBinding()) {
+                       scope.problemReporter().typeMismatchError(typeBinding, scope.getJavaLangAnnotationAnnotation(), this.type, null);
+                       return null;
+               }
+
+               ReferenceBinding annotationType = (ReferenceBinding) this.resolvedType;
+               MethodBinding[] methods = annotationType.methods();
+               // clone valuePairs to keep track of unused ones
+               MemberValuePair[] originalValuePairs = memberValuePairs();
+               MemberValuePair valueAttribute = null; // remember the first 'value' pair
+               MemberValuePair[] pairs;
+               int pairsLength = originalValuePairs.length;
+               if (pairsLength > 0) {
+                       System.arraycopy(originalValuePairs, 0, pairs = new MemberValuePair[pairsLength], 0, pairsLength);
+               } else {
+                       pairs = originalValuePairs;
+               }               
+               
+               nextMember: for (int i = 0, requiredLength = methods.length; i < requiredLength; i++) {
+                       MethodBinding method = methods[i];
+                       char[] selector = method.selector;
+                       boolean foundValue = false;
+                       nextPair: for (int j = 0; j < pairsLength; j++) {
+                               MemberValuePair pair = pairs[j];
+                               if (pair == null) continue nextPair;
+                               char[] name = pair.name;
+                               if (CharOperation.equals(name, selector)) {
+                                       if (valueAttribute == null && CharOperation.equals(name, TypeConstants.VALUE)) {
+                                               valueAttribute = pair;
+                                       }
+                                       pair.binding = method;
+                                       pair.resolveTypeExpecting(scope, method.returnType);
+                                       pairs[j] = null; // consumed
+                                       foundValue = true;
+                                       
+                                       // check duplicates
+                                       boolean foundDuplicate = false;
+                                       for (int k = j+1; k < pairsLength; k++) {
+                                               MemberValuePair otherPair = pairs[k];
+                                               if (otherPair == null) continue;
+                                               if (CharOperation.equals(otherPair.name, selector)) {
+                                                       foundDuplicate = true;
+                                                       scope.problemReporter().duplicateAnnotationValue(annotationType, otherPair);
+                                                       otherPair.binding = method;
+                                                       otherPair.resolveTypeExpecting(scope, method.returnType);
+                                                       pairs[k] = null;
+                                               }
+                                       }
+                                       if (foundDuplicate) {
+                                               scope.problemReporter().duplicateAnnotationValue(annotationType, pair);
+                                               continue nextMember;
+                                       }
+                               }
+                       }
+                       if (!foundValue &&
+                                       (method.modifiers & ClassFileConstants.AccAnnotationDefault) == 0 &&
+                                       (this.bits & IsRecovered) == 0) {
+                               scope.problemReporter().missingValueForAnnotationMember(this, selector);
+                       }
+               }
+               // check unused pairs
+               for (int i = 0; i < pairsLength; i++) {
+                       if (pairs[i] != null) {
+                               scope.problemReporter().undefinedAnnotationValue(annotationType, pairs[i]);
+                               pairs[i].resolveTypeExpecting(scope, null); // resilient
+                       }
+               }
+//             if (scope.compilerOptions().storeAnnotations)
+               this.compilerAnnotation = scope.environment().createAnnotation((ReferenceBinding) this.resolvedType, this.computeElementValuePairs());
+               // recognize standard annotations ?
+               long tagBits = detectStandardAnnotation(scope, annotationType, valueAttribute);
+
+               // record annotation positions in the compilation result
+               scope.referenceCompilationUnit().recordSuppressWarnings(CompilerOptions.NonExternalizedString, null, this.sourceStart, this.declarationSourceEnd);
+               if (this.recipient != null) {
+                       if (tagBits != 0) {
+                               // tag bits onto recipient
+                               switch (this.recipient.kind()) {
+                                       case Binding.PACKAGE :
+                                               ((PackageBinding)this.recipient).tagBits |= tagBits;
+                                               break;
+                                       case Binding.TYPE :
+                                       case Binding.GENERIC_TYPE :
+                                               SourceTypeBinding sourceType = (SourceTypeBinding) this.recipient;
+                                               sourceType.tagBits |= tagBits;
+                                               if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) {
+                                                       TypeDeclaration typeDeclaration =  sourceType.scope.referenceContext;
+                                                       int start;
+                                                       if (scope.referenceCompilationUnit().types[0] == typeDeclaration) {
+                                                               start = 0;
+                                                       } else {
+                                                               start = typeDeclaration.declarationSourceStart;
+                                                       }
+                                                       recordSuppressWarnings(scope, start, typeDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings);
+                                               }
+                                               break;
+                                       case Binding.METHOD :
+                                               MethodBinding sourceMethod = (MethodBinding) this.recipient;
+                                               sourceMethod.tagBits |= tagBits;
+                                               if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) {
+                                                       sourceType = (SourceTypeBinding) sourceMethod.declaringClass;
+                                                       AbstractMethodDeclaration methodDeclaration = sourceType.scope.referenceContext.declarationOf(sourceMethod);
+                                                       recordSuppressWarnings(scope, methodDeclaration.declarationSourceStart, methodDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings);
+                                               }
+                                               break;
+                                       case Binding.FIELD :
+                                               FieldBinding sourceField = (FieldBinding) this.recipient;
+                                               sourceField.tagBits |= tagBits;
+                                               if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) {
+                                                       sourceType = (SourceTypeBinding) sourceField.declaringClass;
+                                                       FieldDeclaration fieldDeclaration = sourceType.scope.referenceContext.declarationOf(sourceField);
+                                                       recordSuppressWarnings(scope, fieldDeclaration.declarationSourceStart, fieldDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings);
+                                               }                                               
+                                               break;
+                                       case Binding.LOCAL :
+                                               LocalVariableBinding variable = (LocalVariableBinding) this.recipient;
+                                               variable.tagBits |= tagBits;
+                                               if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) {
+                                                        LocalDeclaration localDeclaration = variable.declaration;
+                                                       recordSuppressWarnings(scope, localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings);
+                                               }                                                                       
+                                               break;
+                               }                       
+                       }
+                       // check (meta)target compatibility
+                       checkTargetCompatibility: {
+                               long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference
+                               if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) // does not specify any target restriction
+                                       break checkTargetCompatibility;
+                                       
+                               switch (recipient.kind()) {
+                                       case Binding.PACKAGE :
+                                               if ((metaTagBits & TagBits.AnnotationForPackage) != 0)
+                                                       break checkTargetCompatibility;
+                                               break;
+                                       case Binding.TYPE :
+                                       case Binding.GENERIC_TYPE :
+                                               if (((ReferenceBinding)this.recipient).isAnnotationType()) {
+                                                       if ((metaTagBits & (TagBits.AnnotationForAnnotationType|TagBits.AnnotationForType)) != 0)
+                                                       break checkTargetCompatibility;
+                                               } else if ((metaTagBits & TagBits.AnnotationForType) != 0) 
+                                                       break checkTargetCompatibility;
+                                               break;
+                                       case Binding.METHOD :
+                                               if (((MethodBinding)this.recipient).isConstructor()) {
+                                                       if ((metaTagBits & TagBits.AnnotationForConstructor) != 0)
+                                                               break checkTargetCompatibility;
+                                               } else  if ((metaTagBits & TagBits.AnnotationForMethod) != 0)
+                                                       break checkTargetCompatibility;
+                                               break;
+                                       case Binding.FIELD :
+                                               if ((metaTagBits & TagBits.AnnotationForField) != 0)
+                                                       break checkTargetCompatibility;
+                                               break;
+                                       case Binding.LOCAL :
+                                               if ((((LocalVariableBinding)this.recipient).tagBits & TagBits.IsArgument) != 0) {
+                                                       if ((metaTagBits & TagBits.AnnotationForParameter) != 0)
+                                                               break checkTargetCompatibility;
+                                               } else  if ((annotationType.tagBits & TagBits.AnnotationForLocalVariable) != 0)
+                                                       break checkTargetCompatibility;
+                                               break;
+                               }                       
+                               scope.problemReporter().disallowedTargetForAnnotation(this);
+                       }
+               }
+               return this.resolvedType;
+       }
+       
+       public abstract void traverse(ASTVisitor visitor, BlockScope scope);
+       
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/ClassLiteralAccess.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/ClassLiteralAccess.java
new file mode 100644 (file)
index 0000000..5f7c5f6
--- /dev/null
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class ClassLiteralAccess extends Expression {
+       
+       public TypeReference type;
+       public TypeBinding targetType;
+       FieldBinding syntheticField;
+
+       public ClassLiteralAccess(int sourceEnd, TypeReference type) {
+               this.type = type;
+               type.bits |= IgnoreRawTypeCheck; // no need to worry about raw type usage
+               this.sourceStart = type.sourceStart;
+               this.sourceEnd = sourceEnd;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // if reachable, request the addition of a synthetic field for caching the class descriptor
+               SourceTypeBinding sourceType = currentScope.outerMostClassScope().enclosingSourceType();
+               // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=22334
+               if (!sourceType.isInterface()
+                               && !targetType.isBaseType()
+                               && currentScope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) {
+                       syntheticField = sourceType.addSyntheticFieldForClassLiteral(targetType, currentScope);
+               }
+               return flowInfo;
+       }
+
+       /**
+        * MessageSendDotClass code generation
+        *
+        * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+        * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+        * @param valueRequired boolean
+        */
+       public void generateCode(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               boolean valueRequired) {
+               int pc = codeStream.position;
+
+               // in interface case, no caching occurs, since cannot make a cache field for interface
+               if (valueRequired) {
+                       codeStream.generateClassLiteralAccessForType(type.resolvedType, syntheticField);
+                       codeStream.generateImplicitConversion(this.implicitConversion);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               return type.print(0, output).append(".class"); //$NON-NLS-1$
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+
+               constant = Constant.NotAConstant;
+               if ((targetType = type.resolveType(scope, true /* check bounds*/)) == null)
+                       return null;
+
+               if (targetType.isArrayType()) {
+                       ArrayBinding arrayBinding = (ArrayBinding) this.targetType;
+                       TypeBinding leafComponentType = arrayBinding.leafComponentType;
+                       if (leafComponentType == TypeBinding.VOID) {
+                               scope.problemReporter().cannotAllocateVoidArray(this);
+                               return null;
+                       } else if (leafComponentType.isTypeVariable()) {
+                               scope.problemReporter().illegalClassLiteralForTypeVariable((TypeVariableBinding)leafComponentType, this);
+                       }
+               } else if (this.targetType.isTypeVariable()) {
+                       scope.problemReporter().illegalClassLiteralForTypeVariable((TypeVariableBinding)targetType, this);
+               }
+               ReferenceBinding classType = scope.getJavaLangClass();
+               if (classType.isGenericType()) {
+                       // Integer.class --> Class<Integer>, perform boxing of base types (int.class --> Class<Integer>)
+                       TypeBinding boxedType = null;
+                       if (targetType.id == T_void) {
+                               boxedType = scope.environment().getResolvedType(JAVA_LANG_VOID, scope);
+                       } else {
+                               boxedType = scope.boxing(targetType);
+                       }
+                       this.resolvedType = scope.environment().createParameterizedType(classType, new TypeBinding[]{ boxedType }, null/*not a member*/);
+               } else {
+                       this.resolvedType = classType;
+               }
+               return this.resolvedType;
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       type.traverse(visitor, blockScope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/MemberValuePair.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/MemberValuePair.java
new file mode 100644 (file)
index 0000000..dd6e8ad
--- /dev/null
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ElementValuePair;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+/**
+ * MemberValuePair node
+ */
+public class MemberValuePair extends ASTNode {
+       
+       public char[] name;
+       public Expression value;
+       public MethodBinding binding;
+       /** 
+        *  The representation of this pair in the type system. 
+        */
+       public ElementValuePair compilerElementPair = null;
+       
+       public MemberValuePair(char[] token, int sourceStart, int sourceEnd, Expression value) {
+               this.name = token;
+               this.sourceStart = sourceStart;
+               this.sourceEnd = sourceEnd;
+               this.value = value;
+               if (value instanceof ArrayInitializer) {
+                       value.bits |= IsAnnotationDefaultValue;
+               }
+       }
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#print(int, java.lang.StringBuffer)
+        */
+       public StringBuffer print(int indent, StringBuffer output) {
+               output
+                       .append(name)
+                       .append(" = "); //$NON-NLS-1$
+               value.print(0, output);
+               return output;
+       }
+       
+       public void resolveTypeExpecting(BlockScope scope, TypeBinding requiredType) {
+               
+               if (this.value == null) {
+                       this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding);
+                       return;
+               }
+               if (requiredType == null) {
+                       // fault tolerance: keep resolving
+                       if (this.value instanceof ArrayInitializer) {
+                               this.value.resolveTypeExpecting(scope, null);
+                       } else {
+                               this.value.resolveType(scope);
+                       }
+                       this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding);
+                       return;
+               }
+
+               this.value.setExpectedType(requiredType); // needed in case of generic method invocation
+               TypeBinding valueType;
+               if (this.value instanceof ArrayInitializer) {
+                       ArrayInitializer initializer = (ArrayInitializer) this.value;
+                       valueType = initializer.resolveTypeExpecting(scope, this.binding.returnType);
+               } else if (this.value instanceof ArrayAllocationExpression) {
+                       scope.problemReporter().annotationValueMustBeArrayInitializer(this.binding.declaringClass, this.name, this.value);
+                       this.value.resolveType(scope);
+                       valueType = null; // no need to pursue
+               } else {
+                       valueType = this.value.resolveType(scope);
+               }
+               this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding);
+               if (valueType == null)
+                       return;
+
+               TypeBinding leafType = requiredType.leafComponentType();
+               if (!((this.value.isConstantValueOfTypeAssignableToType(valueType, requiredType)
+                               || (requiredType.isBaseType() && BaseTypeBinding.isWidening(requiredType.id, valueType.id)))
+                               || valueType.isCompatibleWith(requiredType))) {
+
+                       if (!(requiredType.isArrayType() 
+                                       && requiredType.dimensions() == 1 
+                                       && (this.value.isConstantValueOfTypeAssignableToType(valueType, leafType)
+                                                       || (leafType.isBaseType() && BaseTypeBinding.isWidening(leafType.id, valueType.id)))
+                                                       || valueType.isCompatibleWith(leafType))) {
+                               
+                               if (leafType.isAnnotationType() && !valueType.isAnnotationType()) {
+                                       scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, this.value, leafType);                          
+                               } else {
+                                       scope.problemReporter().typeMismatchError(valueType, requiredType, this.value, null);
+                               }
+                               return; // may allow to proceed to find more errors at once
+                       }
+               } else {
+                       scope.compilationUnitScope().recordTypeConversion(requiredType.leafComponentType(), valueType.leafComponentType());
+                       this.value.computeConversion(scope, requiredType, valueType);                           
+               }
+               
+               // annotation methods can only return base types, String, Class, enum type, annotation types and arrays of these
+               checkAnnotationMethodType: {
+                       switch (leafType.erasure().id) {
+                               case T_byte :
+                               case T_short :
+                               case T_char :
+                               case T_int :
+                               case T_long :
+                               case T_float :
+                               case T_double :
+                               case T_boolean :
+                               case T_JavaLangString :
+                                       if (this.value instanceof ArrayInitializer) {
+                                               ArrayInitializer initializer = (ArrayInitializer) this.value;
+                                               final Expression[] expressions = initializer.expressions;
+                                               if (expressions != null) {
+                                                       for (int i =0, max = expressions.length; i < max; i++) {
+                                                               Expression expression = expressions[i];
+                                                               if (expression.resolvedType == null) continue; // fault-tolerance
+                                                               if (expression.constant == Constant.NotAConstant) {
+                                                                       scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, expressions[i], false);
+                                                               }
+                                                       }
+                                               }
+                                       } else if (this.value.constant == Constant.NotAConstant) {
+                                               if (valueType.isArrayType()) {
+                                                       scope.problemReporter().annotationValueMustBeArrayInitializer(this.binding.declaringClass, this.name, this.value);
+                                               } else {
+                                                       scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value, false);
+                                               }
+                                       }
+                                       break checkAnnotationMethodType;
+                               case T_JavaLangClass :
+                                       if (this.value instanceof ArrayInitializer) {
+                                               ArrayInitializer initializer = (ArrayInitializer) this.value;
+                                               final Expression[] expressions = initializer.expressions;
+                                               if (expressions != null) {
+                                                       for (int i =0, max = expressions.length; i < max; i++) {
+                                                               Expression currentExpression = expressions[i];
+                                                               if (!(currentExpression instanceof ClassLiteralAccess)) {
+                                                                       scope.problemReporter().annotationValueMustBeClassLiteral(this.binding.declaringClass, this.name, currentExpression);
+                                                               }
+                                                       }
+                                               }
+                                       } else if (!(this.value instanceof ClassLiteralAccess)) {
+                                               scope.problemReporter().annotationValueMustBeClassLiteral(this.binding.declaringClass, this.name, this.value);
+                                       }
+                                       break checkAnnotationMethodType;
+                       }
+                       if (leafType.isEnum()) {
+                               if (this.value instanceof NullLiteral) {
+                                       scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value, true);
+                               } else if (this.value instanceof ArrayInitializer) {
+                                       ArrayInitializer initializer = (ArrayInitializer) this.value;
+                                       final Expression[] expressions = initializer.expressions;
+                                       if (expressions != null) {
+                                               for (int i =0, max = expressions.length; i < max; i++) {
+                                                       Expression currentExpression = expressions[i];
+                                                       if (currentExpression instanceof NullLiteral) {
+                                                               scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, currentExpression, true);
+                                                       } else if (currentExpression instanceof NameReference) {
+                                                               NameReference nameReference = (NameReference) currentExpression;
+                                                               final Binding nameReferenceBinding = nameReference.binding;
+                                                               if (nameReferenceBinding.kind() == Binding.FIELD) {
+                                                                       FieldBinding fieldBinding = (FieldBinding) nameReferenceBinding;
+                                                                       if (!fieldBinding.declaringClass.isEnum()) {
+                                                                               scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, currentExpression, true);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               } else if (this.value instanceof NameReference) {
+                                       NameReference nameReference = (NameReference) this.value;
+                                       final Binding nameReferenceBinding = nameReference.binding;
+                                       if (nameReferenceBinding.kind() == Binding.FIELD) {
+                                               FieldBinding fieldBinding = (FieldBinding) nameReferenceBinding;
+                                               if (!fieldBinding.declaringClass.isEnum()) {
+                                                       if (!fieldBinding.type.isArrayType()) {
+                                                               scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value, true);
+                                                       } else {
+                                                               scope.problemReporter().annotationValueMustBeArrayInitializer(this.binding.declaringClass, this.name, this.value);
+                                                       }
+                                               }
+                                       }
+                               }
+                               break checkAnnotationMethodType;
+                       }
+                       if (leafType.isAnnotationType()) {
+                               if (!valueType.leafComponentType().isAnnotationType()) { // check annotation type and also reject null literal
+                                       scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, this.value, leafType);
+                               } else if (this.value instanceof ArrayInitializer) {
+                                       ArrayInitializer initializer = (ArrayInitializer) this.value;
+                                       final Expression[] expressions = initializer.expressions;
+                                       if (expressions != null) {
+                                               for (int i =0, max = expressions.length; i < max; i++) {
+                                                       Expression currentExpression = expressions[i];
+                                                       if (currentExpression instanceof NullLiteral || !(currentExpression instanceof Annotation)) {
+                                                               scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, currentExpression, leafType);
+                                                       }
+                                               }
+                                       }
+                               } else if (!(this.value instanceof Annotation)) {
+                                       scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, this.value, leafType);
+                               }
+                               break checkAnnotationMethodType;
+                       }
+               }
+       }
+       
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               if (visitor.visit(this, scope)) {
+                       if (this.value != null) {
+                               this.value.traverse(visitor, scope);
+                       }
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/classfmt/ClassFileConstants.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/classfmt/ClassFileConstants.java
new file mode 100644 (file)
index 0000000..a5dce4c
--- /dev/null
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.internal.compiler.classfmt;
+
+import net.sourceforge.phpdt.internal.compiler.ast.ASTNode;
+
+public interface ClassFileConstants {
+       
+       int AccDefault = 0;
+       /*
+        * Modifiers
+        */
+       int AccPublic       = 0x0001;
+       int AccPrivate      = 0x0002;
+       int AccProtected    = 0x0004;
+       int AccStatic       = 0x0008;
+       int AccFinal        = 0x0010;
+       int AccSynchronized = 0x0020;
+       int AccVolatile     = 0x0040;
+       int AccBridge       = 0x0040;
+       int AccTransient    = 0x0080;
+       int AccVarargs      = 0x0080;
+       int AccNative       = 0x0100;
+       int AccInterface    = 0x0200;
+       int AccAbstract     = 0x0400;
+       int AccStrictfp     = 0x0800;
+       int AccSynthetic    = 0x1000;
+       int AccAnnotation   = 0x2000;
+       int AccEnum         = 0x4000;
+
+       /**
+        * Other VM flags.
+        */
+       int AccSuper = 0x0020;
+
+       /**
+        * Extra flags for types and members attributes.
+        */
+       int AccAnnotationDefault = ASTNode.Bit18; // indicate presence of an attribute  "DefaultValue" (annotation method)
+       int AccDeprecated = ASTNode.Bit21; // indicate presence of an attribute "Deprecated"
+
+       int Utf8Tag = 1;
+       int IntegerTag = 3;
+       int FloatTag = 4;
+       int LongTag = 5;
+       int DoubleTag = 6;
+       int ClassTag = 7;
+       int StringTag = 8;
+       int FieldRefTag = 9;
+       int MethodRefTag = 10;
+       int InterfaceMethodRefTag = 11;
+       int NameAndTypeTag = 12;
+       
+       int ConstantMethodRefFixedSize = 5;
+       int ConstantClassFixedSize = 3;
+       int ConstantDoubleFixedSize = 9;
+       int ConstantFieldRefFixedSize = 5;
+       int ConstantFloatFixedSize = 5;
+       int ConstantIntegerFixedSize = 5;
+       int ConstantInterfaceMethodRefFixedSize = 5;
+       int ConstantLongFixedSize = 9;
+       int ConstantStringFixedSize = 3;
+       int ConstantUtf8FixedSize = 3;
+       int ConstantNameAndTypeFixedSize = 5;
+       
+       int MAJOR_VERSION_1_1 = 45;
+       int MAJOR_VERSION_1_2 = 46;
+       int MAJOR_VERSION_1_3 = 47;
+       int MAJOR_VERSION_1_4 = 48;
+       int MAJOR_VERSION_1_5 = 49; 
+       int MAJOR_VERSION_1_6 = 50; 
+       int MAJOR_VERSION_1_7 = 51; 
+       
+       int MINOR_VERSION_0 = 0;
+       int MINOR_VERSION_1 = 1;
+       int MINOR_VERSION_2 = 2;
+       int MINOR_VERSION_3 = 3;
+       int MINOR_VERSION_4 = 4;
+
+       // JDK 1.1 -> 1.7, comparable value allowing to check both major/minor version at once 1.4.1 > 1.4.0
+       // 16 unsigned bits for major, then 16 bits for minor
+       long JDK1_1 = ((long)ClassFileConstants.MAJOR_VERSION_1_1 << 16) + ClassFileConstants.MINOR_VERSION_3; // 1.1. is 45.3
+       long JDK1_2 =  ((long)ClassFileConstants.MAJOR_VERSION_1_2 << 16) + ClassFileConstants.MINOR_VERSION_0;
+       long JDK1_3 =  ((long)ClassFileConstants.MAJOR_VERSION_1_3 << 16) + ClassFileConstants.MINOR_VERSION_0;
+       long JDK1_4 = ((long)ClassFileConstants.MAJOR_VERSION_1_4 << 16) + ClassFileConstants.MINOR_VERSION_0;
+       long JDK1_5 = ((long)ClassFileConstants.MAJOR_VERSION_1_5 << 16) + ClassFileConstants.MINOR_VERSION_0;  
+       long JDK1_6 = ((long)ClassFileConstants.MAJOR_VERSION_1_6 << 16) + ClassFileConstants.MINOR_VERSION_0;  
+       long JDK1_7 = ((long)ClassFileConstants.MAJOR_VERSION_1_7 << 16) + ClassFileConstants.MINOR_VERSION_0;  
+
+       /*
+        * cldc1.1 is 45.3, but we modify it to be different from JDK1_1.
+        * In the code gen, we will generate the same target value as JDK1_1
+        */ 
+       long CLDC_1_1 = ((long)ClassFileConstants.MAJOR_VERSION_1_1 << 16) + ClassFileConstants.MINOR_VERSION_4;
+
+       // jdk level used to denote future releases: optional behavior is not enabled for now, but may become so. In order to enable these,
+       // search for references to this constant, and change it to one of the official JDT constants above.
+       long JDK_DEFERRED = Long.MAX_VALUE;
+
+       int INT_ARRAY = 10;
+       int BYTE_ARRAY = 8;
+       int BOOLEAN_ARRAY = 4;
+       int SHORT_ARRAY = 9;
+       int CHAR_ARRAY = 5;
+       int LONG_ARRAY = 11;
+       int FLOAT_ARRAY = 6;
+       int DOUBLE_ARRAY = 7;
+
+       // Debug attributes
+       int ATTR_SOURCE = 0x1; // SourceFileAttribute
+       int ATTR_LINES = 0x2; // LineNumberAttribute
+       int ATTR_VARS = 0x4; // LocalVariableTableAttribute
+       int ATTR_STACK_MAP_TABLE = 0x8; // Stack map table attribute
+       int ATTR_STACK_MAP = 0x10; // Stack map attribute: cldc
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/AnnotationBinding.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/AnnotationBinding.java
new file mode 100644 (file)
index 0000000..ebb5f0e
--- /dev/null
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.Annotation;
+
+/**
+ * Represents JSR 175 Annotation instances in the type-system.
+ */ 
+public class AnnotationBinding {
+       // do not access directly - use getters instead (UnresolvedAnnotationBinding
+       // resolves types for type and pair contents just in time)
+       ReferenceBinding type;
+       ElementValuePair[] pairs;
+
+/**
+ * Add the standard annotations encoded in the tag bits to the recorded annotations.
+ * 
+ * @param recordedAnnotations existing annotations already created
+ * @param annotationTagBits
+ * @param env
+ * @return the combined list of annotations
+ */
+public static AnnotationBinding[] addStandardAnnotations(AnnotationBinding[] recordedAnnotations, long annotationTagBits, LookupEnvironment env) {
+       // NOTE: expect annotations to be requested just once so there is no need to store the standard annotations
+       // and all of the standard annotations created by this method are fully resolved since the sender is expected to use them immediately
+       int count = 0;
+       if ((annotationTagBits & TagBits.AnnotationTargetMASK) != 0)
+               count++;
+       if ((annotationTagBits & TagBits.AnnotationRetentionMASK) != 0)
+               count++;
+       if ((annotationTagBits & TagBits.AnnotationDeprecated) != 0)
+               count++;
+       if ((annotationTagBits & TagBits.AnnotationDocumented) != 0)
+               count++;
+       if ((annotationTagBits & TagBits.AnnotationInherited) != 0)
+               count++;
+       if ((annotationTagBits & TagBits.AnnotationOverride) != 0)
+               count++;
+       if ((annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0)
+               count++;
+       if (count == 0)
+               return recordedAnnotations;
+
+       int index = recordedAnnotations.length;
+       AnnotationBinding[] result = new AnnotationBinding[index + count];
+       System.arraycopy(recordedAnnotations, 0, result, 0, index);
+       if ((annotationTagBits & TagBits.AnnotationTargetMASK) != 0)
+               result[index++] = buildTargetAnnotation(annotationTagBits, env);
+       if ((annotationTagBits & TagBits.AnnotationRetentionMASK) != 0)
+               result[index++] = buildRetentionAnnotation(annotationTagBits, env);
+       if ((annotationTagBits & TagBits.AnnotationDeprecated) != 0)
+               result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_DEPRECATED, env);
+       if ((annotationTagBits & TagBits.AnnotationDocumented) != 0)
+               result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED, env);
+       if ((annotationTagBits & TagBits.AnnotationInherited) != 0)
+               result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_ANNOTATION_INHERITED, env);
+       if ((annotationTagBits & TagBits.AnnotationOverride) != 0)
+               result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, env);
+       if ((annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0)
+               result[index++] = buildMarkerAnnotation(TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, env);
+       return result;
+}
+
+private static AnnotationBinding buildMarkerAnnotation(char[][] compoundName, LookupEnvironment env) {
+       ReferenceBinding type = env.getResolvedType(compoundName, null);
+       return env.createAnnotation(type, Binding.NO_ELEMENT_VALUE_PAIRS);
+}
+
+private static AnnotationBinding buildRetentionAnnotation(long bits, LookupEnvironment env) {
+       ReferenceBinding retentionPolicy = 
+               env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY, 
+                       null);
+       Object value = null;
+       if ((bits & TagBits.AnnotationRuntimeRetention) != 0)
+               value = retentionPolicy.getField(TypeConstants.UPPER_RUNTIME, true);
+       else if ((bits & TagBits.AnnotationClassRetention) != 0)
+               value = retentionPolicy.getField(TypeConstants.UPPER_CLASS, true);
+       else if ((bits & TagBits.AnnotationSourceRetention) != 0)
+               value = retentionPolicy.getField(TypeConstants.UPPER_SOURCE, true);
+       return env.createAnnotation(
+               env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_RETENTION, null),
+               new ElementValuePair[] { 
+                       new ElementValuePair(TypeConstants.VALUE, value, null)
+               });
+}
+
+private static AnnotationBinding buildTargetAnnotation(long bits, LookupEnvironment env) {
+       ReferenceBinding target = env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_TARGET, null);
+       if ((bits & TagBits.AnnotationTarget) != 0)
+               return new AnnotationBinding(target, Binding.NO_ELEMENT_VALUE_PAIRS);
+
+       int arraysize = 0;
+       if ((bits & TagBits.AnnotationForAnnotationType) != 0)
+               arraysize++;
+       if ((bits & TagBits.AnnotationForConstructor) != 0)
+               arraysize++;
+       if ((bits & TagBits.AnnotationForField) != 0)
+               arraysize++;
+       if ((bits & TagBits.AnnotationForLocalVariable) != 0)
+               arraysize++;
+       if ((bits & TagBits.AnnotationForMethod) != 0)
+               arraysize++;
+       if ((bits & TagBits.AnnotationForPackage) != 0)
+               arraysize++;
+       if ((bits & TagBits.AnnotationForParameter) != 0)
+               arraysize++;
+       if ((bits & TagBits.AnnotationForType) != 0)
+               arraysize++;
+       Object[] value = new Object[arraysize];
+       if (arraysize > 0) {
+               ReferenceBinding elementType = env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE, null);
+               int index = 0;
+               if ((bits & TagBits.AnnotationForAnnotationType) != 0)
+                       value[index++] = elementType.getField(TypeConstants.UPPER_ANNOTATION_TYPE, true);
+               if ((bits & TagBits.AnnotationForConstructor) != 0)
+                       value[index++] = elementType.getField(TypeConstants.UPPER_CONSTRUCTOR, true);
+               if ((bits & TagBits.AnnotationForField) != 0)
+                       value[index++] = elementType.getField(TypeConstants.UPPER_FIELD, true);
+               if ((bits & TagBits.AnnotationForLocalVariable) != 0)
+                       value[index++] = elementType.getField(TypeConstants.UPPER_LOCAL_VARIABLE, true);
+               if ((bits & TagBits.AnnotationForMethod) != 0)
+                       value[index++] = elementType.getField(TypeConstants.UPPER_METHOD, true);
+               if ((bits & TagBits.AnnotationForPackage) != 0)
+                       value[index++] = elementType.getField(TypeConstants.UPPER_PACKAGE, true);
+               if ((bits & TagBits.AnnotationForParameter) != 0)
+                       value[index++] = elementType.getField(TypeConstants.UPPER_PARAMETER, true);
+               if ((bits & TagBits.AnnotationForType) != 0)
+                       value[index++] = elementType.getField(TypeConstants.TYPE, true);
+       }
+       return env.createAnnotation(
+                       target,
+                       new ElementValuePair[] {
+                               new ElementValuePair(TypeConstants.VALUE, value, null)
+                       });
+}
+
+AnnotationBinding(ReferenceBinding type, ElementValuePair[] pairs) {
+       this.type = type;
+       this.pairs = pairs;
+}
+
+AnnotationBinding(Annotation astAnnotation) {
+       this((ReferenceBinding) astAnnotation.resolvedType, astAnnotation.computeElementValuePairs());
+}
+
+/*
+ * Computes a key that uniquely identifies this binding, using the given recipient's unique key.
+ * recipientKey @ typeKey
+ * @MyAnnot void bar() --> Lp/X;.bar()V@Lp/MyAnnot;
+ */
+public char[] computeUniqueKey(char[] recipientKey) {
+       char[] typeKey = this.type.computeUniqueKey(false);
+       int recipientKeyLength = recipientKey.length;
+       char[] uniqueKey = new char[recipientKeyLength+1+typeKey.length];
+       System.arraycopy(recipientKey, 0, uniqueKey, 0, recipientKeyLength);
+       uniqueKey[recipientKeyLength] = '@';
+       System.arraycopy(typeKey, 0, uniqueKey, recipientKeyLength+1, typeKey.length);
+       return uniqueKey;
+}
+
+public ReferenceBinding getAnnotationType() {
+       return this.type;
+}
+
+public ElementValuePair[] getElementValuePairs() {
+       return this.pairs;
+}
+
+public static void setMethodBindings(ReferenceBinding type, ElementValuePair[] pairs) {
+       // set the method bindings of each element value pair
+       for (int i = pairs.length; --i >= 0;) {
+               ElementValuePair pair = pairs[i];
+               MethodBinding[] methods = type.getMethods(pair.getName());
+               // there should be exactly one since the type is an annotation type.
+               if (methods != null && methods.length == 1)
+                       pair.setMethodBinding(methods[0]);
+       }
+}
+
+public String toString() {
+       StringBuffer buffer = new StringBuffer(5);
+       buffer.append('@').append(this.type.sourceName);
+       if (this.pairs != null && this.pairs.length > 0) {
+               buffer.append("{ "); //$NON-NLS-1$
+               for (int i = 0, max = this.pairs.length; i < max; i++) {
+                       if (i > 0) buffer.append(", "); //$NON-NLS-1$
+                       buffer.append(this.pairs[i]);
+               }
+               buffer.append('}');
+       }
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/ElementValuePair.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/lookup/ElementValuePair.java
new file mode 100644 (file)
index 0000000..a418905
--- /dev/null
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+
+public class ElementValuePair {
+       char[] name;
+       public Object value;
+       public MethodBinding binding;
+
+public static Object getValue(Expression expression) {
+       if (expression == null)
+               return null;
+       Constant constant = expression.constant;
+       // literals would hit this case.
+       if (constant != null && constant != Constant.NotAConstant)
+               return constant;
+
+       if (expression instanceof Annotation)
+               return ((Annotation) expression).getCompilerAnnotation();
+       if (expression instanceof ArrayInitializer) {
+               Expression[] exprs = ((ArrayInitializer) expression).expressions;
+               int length = exprs == null ? 0 : exprs.length;
+               Object[] values = new Object[length];
+               for (int i = 0; i < length; i++)
+                       values[i] = getValue(exprs[i]);
+               return values;
+       }
+       if (expression instanceof ClassLiteralAccess)
+               return ((ClassLiteralAccess) expression).targetType;
+       if (expression instanceof Reference) {
+               FieldBinding fieldBinding = null;
+               if (expression instanceof FieldReference) {
+                       fieldBinding = ((FieldReference) expression).fieldBinding();
+               } else if (expression instanceof NameReference) {
+                       Binding binding = ((NameReference) expression).binding;
+                       if (binding != null && binding.kind() == Binding.FIELD)
+                               fieldBinding = (FieldBinding) binding;
+               }
+               if (fieldBinding != null && (fieldBinding.modifiers & ClassFileConstants.AccEnum) > 0)
+                       return fieldBinding;
+       }
+       // something that isn't a compile time constant.
+       return null;
+}
+
+public ElementValuePair(char[] name, Expression expression, MethodBinding binding) {
+       this(name, ElementValuePair.getValue(expression), binding);
+}
+
+public ElementValuePair(char[] name, Object value, MethodBinding binding) {
+       this.name = name;
+       this.value = value;
+       this.binding = binding;
+}
+
+/**
+ * @return the name of the element value pair.
+ */
+public char[] getName() {
+       return this.name;
+}
+
+/**
+ * @return the method binding that defined this member value pair or null if no such binding exists.
+ */
+public MethodBinding getMethodBinding() {
+       return this.binding;
+}
+
+/**
+ * Return {@link TypeBinding} for member value of type {@link java.lang.Class}
+ * Return {@link org.eclipse.jdt.internal.compiler.impl.Constant} for member of primitive type or String
+ * Return {@link FieldBinding} for enum constant
+ * Return {@link AnnotationBinding} for annotation instance
+ * Return <code>Object[]</code> for member value of array type.
+ * @return the value of this member value pair or null if the value is missing or is not a compile-time constant
+ */
+public Object getValue() {
+       return this.value;
+}
+
+void setMethodBinding(MethodBinding binding) {
+       // lazily set after annotation type was resolved
+       this.binding = binding;
+}
+
+void setValue(Object value) {
+       // can be modified after the initialization if holding an unresolved ref
+       this.value = value;
+}
+
+public String toString() {
+       StringBuffer buffer = new StringBuffer(5);
+       buffer.append(this.name).append(" = "); //$NON-NLS-1$
+       buffer.append(this.value);
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/TerminalTokens.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/TerminalTokens.java
new file mode 100644 (file)
index 0000000..40fa11d
--- /dev/null
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.internal.compiler.parser;
+
+/**
+ * IMPORTANT NOTE: These constants are dedicated to the internal Scanner implementation. 
+ * It is mirrored in org.eclipse.jdt.core.compiler public package where it is API. 
+ * The mirror implementation is using the backward compatible ITerminalSymbols constant 
+ * definitions (stable with 2.0), whereas the internal implementation uses TerminalTokens 
+ * which constant values reflect the latest parser generation state.
+ */
+/**
+ * Maps each terminal symbol in the java-grammar into a unique integer. 
+ * This integer is used to represent the terminal when computing a parsing action. 
+ * 
+ * Disclaimer : These constant values are generated automatically using a Java 
+ * grammar, therefore their actual values are subject to change if new keywords 
+ * were added to the language (for instance, 'assert' is a keyword in 1.4).
+ */
+public interface TerminalTokens {
+
+       // special tokens not part of grammar - not autogenerated
+       int TokenNameWHITESPACE = 1000,
+               TokenNameCOMMENT_LINE = 1001,
+               TokenNameCOMMENT_BLOCK = 1002,
+               TokenNameCOMMENT_JAVADOC = 1003;
+
+       int TokenNameIdentifier = 26,
+               TokenNameabstract = 56,
+               TokenNameassert = 74,
+               TokenNameboolean = 32,
+               TokenNamebreak = 75,
+               TokenNamebyte = 33,
+               TokenNamecase = 101,
+               TokenNamecatch = 102,
+               TokenNamechar = 34,
+               TokenNameclass = 72,
+               TokenNamecontinue = 76,
+               TokenNameconst = 108,
+               TokenNamedefault = 97,
+               TokenNamedo = 77,
+               TokenNamedouble = 35,
+               TokenNameelse = 103,
+               TokenNameenum = 98,
+               TokenNameextends = 99,
+               TokenNamefalse = 44,
+               TokenNamefinal = 57,
+               TokenNamefinally = 104,
+               TokenNamefloat = 36,
+               TokenNamefor = 78,
+               TokenNamegoto = 109,
+               TokenNameif = 79,
+               TokenNameimplements = 106,
+               TokenNameimport = 100,
+               TokenNameinstanceof = 12,
+               TokenNameint = 37,
+               TokenNameinterface = 95,
+               TokenNamelong = 38,
+               TokenNamenative = 58,
+               TokenNamenew = 43,
+               TokenNamenull = 45,
+               TokenNamepackage = 96,
+               TokenNameprivate = 59,
+               TokenNameprotected = 60,
+               TokenNamepublic = 61,
+               TokenNamereturn = 80,
+               TokenNameshort = 39,
+               TokenNamestatic = 54,
+               TokenNamestrictfp = 62,
+               TokenNamesuper = 41,
+               TokenNameswitch = 81,
+               TokenNamesynchronized = 55,
+               TokenNamethis = 42,
+               TokenNamethrow = 82,
+               TokenNamethrows = 105,
+               TokenNametransient = 63,
+               TokenNametrue = 46,
+               TokenNametry = 83,
+               TokenNamevoid = 40,
+               TokenNamevolatile = 64,
+               TokenNamewhile = 73,
+               TokenNameIntegerLiteral = 47,
+               TokenNameLongLiteral = 48,
+               TokenNameFloatingPointLiteral = 49,
+               TokenNameDoubleLiteral = 50,
+               TokenNameCharacterLiteral = 51,
+               TokenNameStringLiteral = 52,
+               TokenNamePLUS_PLUS = 8,
+               TokenNameMINUS_MINUS = 9,
+               TokenNameEQUAL_EQUAL = 18,
+               TokenNameLESS_EQUAL = 15,
+               TokenNameGREATER_EQUAL = 16,
+               TokenNameNOT_EQUAL = 19,
+               TokenNameLEFT_SHIFT = 17,
+               TokenNameRIGHT_SHIFT = 10,
+               TokenNameUNSIGNED_RIGHT_SHIFT = 11,
+               TokenNamePLUS_EQUAL = 84,
+               TokenNameMINUS_EQUAL = 85,
+               TokenNameMULTIPLY_EQUAL = 86,
+               TokenNameDIVIDE_EQUAL = 87,
+               TokenNameAND_EQUAL = 88,
+               TokenNameOR_EQUAL = 89,
+               TokenNameXOR_EQUAL = 90,
+               TokenNameREMAINDER_EQUAL = 91,
+               TokenNameLEFT_SHIFT_EQUAL = 92,
+               TokenNameRIGHT_SHIFT_EQUAL = 93,
+               TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 94,
+               TokenNameOR_OR = 25,
+               TokenNameAND_AND = 24,
+               TokenNamePLUS = 1,
+               TokenNameMINUS = 2,
+               TokenNameNOT = 66,
+               TokenNameREMAINDER = 5,
+               TokenNameXOR = 21,
+               TokenNameAND = 20,
+               TokenNameMULTIPLY = 4,
+               TokenNameOR = 22,
+               TokenNameTWIDDLE = 67,
+               TokenNameDIVIDE = 6,
+               TokenNameGREATER = 13,
+               TokenNameLESS = 7,
+               TokenNameLPAREN = 28,
+               TokenNameRPAREN = 29,
+               TokenNameLBRACE = 69,
+               TokenNameRBRACE = 31,
+               TokenNameLBRACKET = 14,
+               TokenNameRBRACKET = 70,
+               TokenNameSEMICOLON = 27,
+               TokenNameQUESTION = 23,
+               TokenNameCOLON = 65,
+               TokenNameCOMMA = 30,
+               TokenNameDOT = 3,
+               TokenNameEQUAL = 71,
+               TokenNameAT = 53,
+               TokenNameELLIPSIS = 107,
+               TokenNameEOF = 68,
+               TokenNameERROR = 110;
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/dom/NaiveASTFlattener.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/dom/NaiveASTFlattener.java
new file mode 100644 (file)
index 0000000..142cebb
--- /dev/null
@@ -0,0 +1,1752 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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 net.sourceforge.phpdt.internal.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.dom.AST;
+import net.sourceforge.phpdt.core.dom.ASTNode;
+import net.sourceforge.phpdt.core.dom.ASTVisitor;
+import net.sourceforge.phpdt.core.dom.AbstractTypeDeclaration;
+import net.sourceforge.phpdt.core.dom.Annotation;
+import net.sourceforge.phpdt.core.dom.AnnotationTypeDeclaration;
+import net.sourceforge.phpdt.core.dom.AnnotationTypeMemberDeclaration;
+import net.sourceforge.phpdt.core.dom.AnonymousClassDeclaration;
+import net.sourceforge.phpdt.core.dom.ArrayAccess;
+import net.sourceforge.phpdt.core.dom.ArrayCreation;
+import net.sourceforge.phpdt.core.dom.ArrayInitializer;
+import net.sourceforge.phpdt.core.dom.ArrayType;
+import net.sourceforge.phpdt.core.dom.AssertStatement;
+import net.sourceforge.phpdt.core.dom.Assignment;
+import net.sourceforge.phpdt.core.dom.Block;
+import net.sourceforge.phpdt.core.dom.BlockComment;
+import net.sourceforge.phpdt.core.dom.BodyDeclaration;
+import net.sourceforge.phpdt.core.dom.BooleanLiteral;
+import net.sourceforge.phpdt.core.dom.BreakStatement;
+import net.sourceforge.phpdt.core.dom.CastExpression;
+import net.sourceforge.phpdt.core.dom.CatchClause;
+import net.sourceforge.phpdt.core.dom.CharacterLiteral;
+import net.sourceforge.phpdt.core.dom.ClassInstanceCreation;
+import net.sourceforge.phpdt.core.dom.CompilationUnit;
+import net.sourceforge.phpdt.core.dom.ConditionalExpression;
+import net.sourceforge.phpdt.core.dom.ConstructorInvocation;
+import net.sourceforge.phpdt.core.dom.ContinueStatement;
+import net.sourceforge.phpdt.core.dom.DoStatement;
+import net.sourceforge.phpdt.core.dom.EmptyStatement;
+import net.sourceforge.phpdt.core.dom.EnhancedForStatement;
+import net.sourceforge.phpdt.core.dom.EnumConstantDeclaration;
+import net.sourceforge.phpdt.core.dom.EnumDeclaration;
+import net.sourceforge.phpdt.core.dom.Expression;
+import net.sourceforge.phpdt.core.dom.ExpressionStatement;
+import net.sourceforge.phpdt.core.dom.FieldAccess;
+import net.sourceforge.phpdt.core.dom.FieldDeclaration;
+import net.sourceforge.phpdt.core.dom.ForStatement;
+import net.sourceforge.phpdt.core.dom.IfStatement;
+import net.sourceforge.phpdt.core.dom.ImportDeclaration;
+import net.sourceforge.phpdt.core.dom.InfixExpression;
+import net.sourceforge.phpdt.core.dom.Initializer;
+import net.sourceforge.phpdt.core.dom.InstanceofExpression;
+import net.sourceforge.phpdt.core.dom.Javadoc;
+import net.sourceforge.phpdt.core.dom.LabeledStatement;
+import net.sourceforge.phpdt.core.dom.LineComment;
+import net.sourceforge.phpdt.core.dom.MarkerAnnotation;
+import net.sourceforge.phpdt.core.dom.MemberRef;
+import net.sourceforge.phpdt.core.dom.MemberValuePair;
+import net.sourceforge.phpdt.core.dom.MethodDeclaration;
+import net.sourceforge.phpdt.core.dom.MethodInvocation;
+import net.sourceforge.phpdt.core.dom.MethodRef;
+import net.sourceforge.phpdt.core.dom.MethodRefParameter;
+import net.sourceforge.phpdt.core.dom.Modifier;
+import net.sourceforge.phpdt.core.dom.Name;
+import net.sourceforge.phpdt.core.dom.NormalAnnotation;
+import net.sourceforge.phpdt.core.dom.NullLiteral;
+import net.sourceforge.phpdt.core.dom.NumberLiteral;
+import net.sourceforge.phpdt.core.dom.PackageDeclaration;
+import net.sourceforge.phpdt.core.dom.ParameterizedType;
+import net.sourceforge.phpdt.core.dom.ParenthesizedExpression;
+import net.sourceforge.phpdt.core.dom.PostfixExpression;
+import net.sourceforge.phpdt.core.dom.PrefixExpression;
+import net.sourceforge.phpdt.core.dom.PrimitiveType;
+import net.sourceforge.phpdt.core.dom.QualifiedName;
+import net.sourceforge.phpdt.core.dom.QualifiedType;
+import net.sourceforge.phpdt.core.dom.ReturnStatement;
+import net.sourceforge.phpdt.core.dom.SimpleName;
+import net.sourceforge.phpdt.core.dom.SimpleType;
+import net.sourceforge.phpdt.core.dom.SingleMemberAnnotation;
+import net.sourceforge.phpdt.core.dom.SingleVariableDeclaration;
+import net.sourceforge.phpdt.core.dom.Statement;
+import net.sourceforge.phpdt.core.dom.StringLiteral;
+import net.sourceforge.phpdt.core.dom.SuperConstructorInvocation;
+import net.sourceforge.phpdt.core.dom.SuperFieldAccess;
+import net.sourceforge.phpdt.core.dom.SuperMethodInvocation;
+import net.sourceforge.phpdt.core.dom.SwitchCase;
+import net.sourceforge.phpdt.core.dom.SwitchStatement;
+import net.sourceforge.phpdt.core.dom.SynchronizedStatement;
+import net.sourceforge.phpdt.core.dom.TagElement;
+import net.sourceforge.phpdt.core.dom.TextElement;
+import net.sourceforge.phpdt.core.dom.ThisExpression;
+import net.sourceforge.phpdt.core.dom.ThrowStatement;
+import net.sourceforge.phpdt.core.dom.TryStatement;
+import net.sourceforge.phpdt.core.dom.Type;
+import net.sourceforge.phpdt.core.dom.TypeDeclaration;
+import net.sourceforge.phpdt.core.dom.TypeDeclarationStatement;
+import net.sourceforge.phpdt.core.dom.TypeLiteral;
+import net.sourceforge.phpdt.core.dom.TypeParameter;
+import net.sourceforge.phpdt.core.dom.VariableDeclarationExpression;
+import net.sourceforge.phpdt.core.dom.VariableDeclarationFragment;
+import net.sourceforge.phpdt.core.dom.VariableDeclarationStatement;
+import net.sourceforge.phpdt.core.dom.WhileStatement;
+import net.sourceforge.phpdt.core.dom.WildcardType;
+
+/**
+ * Internal AST visitor for serializing an AST in a quick and dirty fashion.
+ * For various reasons the resulting string is not necessarily legal
+ * Java code; and even if it is legal Java code, it is not necessarily the string
+ * that corresponds to the given AST. Although useless for most purposes, it's
+ * fine for generating debug print strings.
+ * <p>
+ * Example usage:
+ * <code>
+ * <pre>
+ *    NaiveASTFlattener p = new NaiveASTFlattener();
+ *    node.accept(p);
+ *    String result = p.getResult();
+ * </pre>
+ * </code>
+ * Call the <code>reset</code> method to clear the previous result before reusing an
+ * existing instance.
+ * </p>
+ * 
+ * @since 2.0
+ */
+public class NaiveASTFlattener extends ASTVisitor {
+       /**
+        * Internal synonym for {@link AST#JLS2}. Use to alleviate
+        * deprecation warnings.
+        * @deprecated
+        * @since 3.4
+        */
+       private static final int JLS2 = AST.JLS2;
+       
+       /**
+        * The string buffer into which the serialized representation of the AST is
+        * written.
+        */
+       protected StringBuffer buffer;
+       
+       private int indent = 0;
+       
+       /**
+        * Creates a new AST printer.
+        */
+       public NaiveASTFlattener() {
+               this.buffer = new StringBuffer();
+       }
+       
+       /**
+        * Internal synonym for {@link ClassInstanceCreation#getName()}. Use to alleviate
+        * deprecation warnings.
+        * @deprecated
+        * @since 3.4
+        */
+       private Name getName(ClassInstanceCreation node) {
+               return node.getName();
+       }
+       
+       /**
+        * Returns the string accumulated in the visit.
+        *
+        * @return the serialized 
+        */
+       public String getResult() {
+               return this.buffer.toString();
+       }
+       
+       /**
+        * Internal synonym for {@link MethodDeclaration#getReturnType()}. Use to alleviate
+        * deprecation warnings.
+        * @deprecated
+        * @since 3.4
+        */
+       private Type getReturnType(MethodDeclaration node) {
+               return node.getReturnType();
+       }
+       
+       /**
+        * Internal synonym for {@link TypeDeclaration#getSuperclass()}. Use to alleviate
+        * deprecation warnings.
+        * @deprecated
+        * @since 3.4
+        */
+       private Name getSuperclass(TypeDeclaration node) {
+               return node.getSuperclass();
+       }               
+       
+       /**
+        * Internal synonym for {@link TypeDeclarationStatement#getTypeDeclaration()}. Use to alleviate
+        * deprecation warnings.
+        * @deprecated
+        * @since 3.4
+        */
+       private TypeDeclaration getTypeDeclaration(TypeDeclarationStatement node) {
+               return node.getTypeDeclaration();
+       }               
+       
+       void printIndent() {
+               for (int i = 0; i < this.indent; i++) 
+                       this.buffer.append("  "); //$NON-NLS-1$
+       }
+       
+       /**
+        * Appends the text representation of the given modifier flags, followed by a single space.
+        * Used for JLS2 modifiers.
+        * 
+        * @param modifiers the modifier flags
+        */
+       void printModifiers(int modifiers) {
+               if (Modifier.isPublic(modifiers)) {
+                       this.buffer.append("public ");//$NON-NLS-1$
+               }
+               if (Modifier.isProtected(modifiers)) {
+                       this.buffer.append("protected ");//$NON-NLS-1$
+               }
+               if (Modifier.isPrivate(modifiers)) {
+                       this.buffer.append("private ");//$NON-NLS-1$
+               }
+               if (Modifier.isStatic(modifiers)) {
+                       this.buffer.append("static ");//$NON-NLS-1$
+               }
+               if (Modifier.isAbstract(modifiers)) {
+                       this.buffer.append("abstract ");//$NON-NLS-1$
+               }
+               if (Modifier.isFinal(modifiers)) {
+                       this.buffer.append("final ");//$NON-NLS-1$
+               }
+               if (Modifier.isSynchronized(modifiers)) {
+                       this.buffer.append("synchronized ");//$NON-NLS-1$
+               }
+               if (Modifier.isVolatile(modifiers)) {
+                       this.buffer.append("volatile ");//$NON-NLS-1$
+               }
+               if (Modifier.isNative(modifiers)) {
+                       this.buffer.append("native ");//$NON-NLS-1$
+               }
+               if (Modifier.isStrictfp(modifiers)) {
+                       this.buffer.append("strictfp ");//$NON-NLS-1$
+               }
+               if (Modifier.isTransient(modifiers)) {
+                       this.buffer.append("transient ");//$NON-NLS-1$
+               }
+       }
+       
+       /**
+        * Appends the text representation of the given modifier flags, followed by a single space.
+        * Used for 3.0 modifiers and annotations.
+        * 
+        * @param ext the list of modifier and annotation nodes
+        * (element type: <code>IExtendedModifiers</code>)
+        */
+       void printModifiers(List ext) {
+               for (Iterator it = ext.iterator(); it.hasNext(); ) {
+                       ASTNode p = (ASTNode) it.next();
+                       p.accept(this);
+                       this.buffer.append(" ");//$NON-NLS-1$
+               }
+       }
+
+       /**
+        * Resets this printer so that it can be used again.
+        */
+       public void reset() {
+               this.buffer.setLength(0);
+       }
+
+       /**
+        * Internal synonym for {@link TypeDeclaration#superInterfaces()}. Use to alleviate
+        * deprecation warnings.
+        * @deprecated
+        * @since 3.4
+        */
+       private List superInterfaces(TypeDeclaration node) {
+               return node.superInterfaces();
+       }
+
+       /*
+        * @see ASTVisitor#visit(AnnotationTypeDeclaration)
+        * @since 3.1
+        */
+       public boolean visit(AnnotationTypeDeclaration node) {
+               if (node.getJavadoc() != null) {
+                       node.getJavadoc().accept(this);
+               }
+               printIndent();
+               printModifiers(node.modifiers());
+               this.buffer.append("@interface ");//$NON-NLS-1$
+               node.getName().accept(this);
+               this.buffer.append(" {");//$NON-NLS-1$
+               for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+                       BodyDeclaration d = (BodyDeclaration) it.next();
+                       d.accept(this);
+               }
+               this.buffer.append("}\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(AnnotationTypeMemberDeclaration)
+        * @since 3.1
+        */
+       public boolean visit(AnnotationTypeMemberDeclaration node) {
+               if (node.getJavadoc() != null) {
+                       node.getJavadoc().accept(this);
+               }
+               printIndent();
+               printModifiers(node.modifiers());
+               node.getType().accept(this);
+               this.buffer.append(" ");//$NON-NLS-1$
+               node.getName().accept(this);
+               this.buffer.append("()");//$NON-NLS-1$
+               if (node.getDefault() != null) {
+                       this.buffer.append(" default ");//$NON-NLS-1$
+                       node.getDefault().accept(this);
+               }
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(AnonymousClassDeclaration)
+        */
+       public boolean visit(AnonymousClassDeclaration node) {
+               this.buffer.append("{\n");//$NON-NLS-1$
+               this.indent++;
+               for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+                       BodyDeclaration b = (BodyDeclaration) it.next();
+                       b.accept(this);
+               }
+               this.indent--;
+               printIndent();
+               this.buffer.append("}\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ArrayAccess)
+        */
+       public boolean visit(ArrayAccess node) {
+               node.getArray().accept(this);
+               this.buffer.append("[");//$NON-NLS-1$
+               node.getIndex().accept(this);
+               this.buffer.append("]");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ArrayCreation)
+        */
+       public boolean visit(ArrayCreation node) {
+               this.buffer.append("new ");//$NON-NLS-1$
+               ArrayType at = node.getType();
+               int dims = at.getDimensions();
+               Type elementType = at.getElementType();
+               elementType.accept(this);
+               for (Iterator it = node.dimensions().iterator(); it.hasNext(); ) {
+                       this.buffer.append("[");//$NON-NLS-1$
+                       Expression e = (Expression) it.next();
+                       e.accept(this);
+                       this.buffer.append("]");//$NON-NLS-1$
+                       dims--;
+               }
+               // add empty "[]" for each extra array dimension
+               for (int i= 0; i < dims; i++) {
+                       this.buffer.append("[]");//$NON-NLS-1$
+               }
+               if (node.getInitializer() != null) {
+                       node.getInitializer().accept(this);
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ArrayInitializer)
+        */
+       public boolean visit(ArrayInitializer node) {
+               this.buffer.append("{");//$NON-NLS-1$
+               for (Iterator it = node.expressions().iterator(); it.hasNext(); ) {
+                       Expression e = (Expression) it.next();
+                       e.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(",");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append("}");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ArrayType)
+        */
+       public boolean visit(ArrayType node) {
+               node.getComponentType().accept(this);
+               this.buffer.append("[]");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(AssertStatement)
+        */
+       public boolean visit(AssertStatement node) {
+               printIndent();
+               this.buffer.append("assert ");//$NON-NLS-1$
+               node.getExpression().accept(this);
+               if (node.getMessage() != null) {
+                       this.buffer.append(" : ");//$NON-NLS-1$
+                       node.getMessage().accept(this);
+               }
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(Assignment)
+        */
+       public boolean visit(Assignment node) {
+               node.getLeftHandSide().accept(this);
+               this.buffer.append(node.getOperator().toString());
+               node.getRightHandSide().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(Block)
+        */
+       public boolean visit(Block node) {
+               this.buffer.append("{\n");//$NON-NLS-1$
+               this.indent++;
+               for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
+                       Statement s = (Statement) it.next();
+                       s.accept(this);
+               }
+               this.indent--;
+               printIndent();
+               this.buffer.append("}\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(BlockComment)
+        * @since 3.0
+        */
+       public boolean visit(BlockComment node) {
+               printIndent();
+               this.buffer.append("/* */");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(BooleanLiteral)
+        */
+       public boolean visit(BooleanLiteral node) {
+               if (node.booleanValue() == true) {
+                       this.buffer.append("true");//$NON-NLS-1$
+               } else {
+                       this.buffer.append("false");//$NON-NLS-1$
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(BreakStatement)
+        */
+       public boolean visit(BreakStatement node) {
+               printIndent();
+               this.buffer.append("break");//$NON-NLS-1$
+               if (node.getLabel() != null) {
+                       this.buffer.append(" ");//$NON-NLS-1$
+                       node.getLabel().accept(this);
+               }
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(CastExpression)
+        */
+       public boolean visit(CastExpression node) {
+               this.buffer.append("(");//$NON-NLS-1$
+               node.getType().accept(this);
+               this.buffer.append(")");//$NON-NLS-1$
+               node.getExpression().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(CatchClause)
+        */
+       public boolean visit(CatchClause node) {
+               this.buffer.append("catch (");//$NON-NLS-1$
+               node.getException().accept(this);
+               this.buffer.append(") ");//$NON-NLS-1$
+               node.getBody().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(CharacterLiteral)
+        */
+       public boolean visit(CharacterLiteral node) {
+               this.buffer.append(node.getEscapedValue());
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ClassInstanceCreation)
+        */
+       public boolean visit(ClassInstanceCreation node) {
+               if (node.getExpression() != null) {
+                       node.getExpression().accept(this);
+                       this.buffer.append(".");//$NON-NLS-1$
+               }
+               this.buffer.append("new ");//$NON-NLS-1$
+               if (node.getAST().apiLevel() == JLS2) {
+                       this.getName(node).accept(this);
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       if (!node.typeArguments().isEmpty()) {
+                               this.buffer.append("<");//$NON-NLS-1$
+                               for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+                                       Type t = (Type) it.next();
+                                       t.accept(this);
+                                       if (it.hasNext()) {
+                                               this.buffer.append(",");//$NON-NLS-1$
+                                       }
+                               }
+                               this.buffer.append(">");//$NON-NLS-1$
+                       }
+                       node.getType().accept(this);
+               }
+               this.buffer.append("(");//$NON-NLS-1$
+               for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+                       Expression e = (Expression) it.next();
+                       e.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(",");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(")");//$NON-NLS-1$
+               if (node.getAnonymousClassDeclaration() != null) {
+                       node.getAnonymousClassDeclaration().accept(this);
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(CompilationUnit)
+        */
+       public boolean visit(CompilationUnit node) {
+               if (node.getPackage() != null) {
+                       node.getPackage().accept(this);
+               }
+               for (Iterator it = node.imports().iterator(); it.hasNext(); ) {
+                       ImportDeclaration d = (ImportDeclaration) it.next();
+                       d.accept(this);
+               }
+               for (Iterator it = node.types().iterator(); it.hasNext(); ) {
+                       AbstractTypeDeclaration d = (AbstractTypeDeclaration) it.next();
+                       d.accept(this);
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ConditionalExpression)
+        */
+       public boolean visit(ConditionalExpression node) {
+               node.getExpression().accept(this);
+               this.buffer.append(" ? ");//$NON-NLS-1$
+               node.getThenExpression().accept(this);
+               this.buffer.append(" : ");//$NON-NLS-1$
+               node.getElseExpression().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ConstructorInvocation)
+        */
+       public boolean visit(ConstructorInvocation node) {
+               printIndent();
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       if (!node.typeArguments().isEmpty()) {
+                               this.buffer.append("<");//$NON-NLS-1$
+                               for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+                                       Type t = (Type) it.next();
+                                       t.accept(this);
+                                       if (it.hasNext()) {
+                                               this.buffer.append(",");//$NON-NLS-1$
+                                       }
+                               }
+                               this.buffer.append(">");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append("this(");//$NON-NLS-1$
+               for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+                       Expression e = (Expression) it.next();
+                       e.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(",");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(");\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ContinueStatement)
+        */
+       public boolean visit(ContinueStatement node) {
+               printIndent();
+               this.buffer.append("continue");//$NON-NLS-1$
+               if (node.getLabel() != null) {
+                       this.buffer.append(" ");//$NON-NLS-1$
+                       node.getLabel().accept(this);
+               }
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(DoStatement)
+        */
+       public boolean visit(DoStatement node) {
+               printIndent();
+               this.buffer.append("do ");//$NON-NLS-1$
+               node.getBody().accept(this);
+               this.buffer.append(" while (");//$NON-NLS-1$
+               node.getExpression().accept(this);
+               this.buffer.append(");\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(EmptyStatement)
+        */
+       public boolean visit(EmptyStatement node) {
+               printIndent();
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(EnhancedForStatement)
+        * @since 3.1
+        */
+       public boolean visit(EnhancedForStatement node) {
+               printIndent();
+               this.buffer.append("for (");//$NON-NLS-1$
+               node.getParameter().accept(this);
+               this.buffer.append(" : ");//$NON-NLS-1$
+               node.getExpression().accept(this);
+               this.buffer.append(") ");//$NON-NLS-1$
+               node.getBody().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(EnumConstantDeclaration)
+        * @since 3.1
+        */
+       public boolean visit(EnumConstantDeclaration node) {
+               if (node.getJavadoc() != null) {
+                       node.getJavadoc().accept(this);
+               }
+               printIndent();
+               printModifiers(node.modifiers());
+               node.getName().accept(this);
+               if (!node.arguments().isEmpty()) {
+                       this.buffer.append("(");//$NON-NLS-1$
+                       for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+                               Expression e = (Expression) it.next();
+                               e.accept(this);
+                               if (it.hasNext()) {
+                                       this.buffer.append(",");//$NON-NLS-1$
+                               }
+                       }
+                       this.buffer.append(")");//$NON-NLS-1$
+               }
+               if (node.getAnonymousClassDeclaration() != null) {
+                       node.getAnonymousClassDeclaration().accept(this);
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(EnumDeclaration)
+        * @since 3.1
+        */
+       public boolean visit(EnumDeclaration node) {
+               if (node.getJavadoc() != null) {
+                       node.getJavadoc().accept(this);
+               }
+               printIndent();
+               printModifiers(node.modifiers());
+               this.buffer.append("enum ");//$NON-NLS-1$
+               node.getName().accept(this);
+               this.buffer.append(" ");//$NON-NLS-1$
+               if (!node.superInterfaceTypes().isEmpty()) {
+                       this.buffer.append("implements ");//$NON-NLS-1$
+                       for (Iterator it = node.superInterfaceTypes().iterator(); it.hasNext(); ) {
+                               Type t = (Type) it.next();
+                               t.accept(this);
+                               if (it.hasNext()) {
+                                       this.buffer.append(", ");//$NON-NLS-1$
+                               }
+                       }
+                       this.buffer.append(" ");//$NON-NLS-1$
+               }
+               this.buffer.append("{");//$NON-NLS-1$
+               for (Iterator it = node.enumConstants().iterator(); it.hasNext(); ) {
+                       EnumConstantDeclaration d = (EnumConstantDeclaration) it.next();
+                       d.accept(this);
+                       // enum constant declarations do not include punctuation
+                       if (it.hasNext()) {
+                               // enum constant declarations are separated by commas
+                               this.buffer.append(", ");//$NON-NLS-1$
+                       }
+               }
+               if (!node.bodyDeclarations().isEmpty()) {
+                       this.buffer.append("; ");//$NON-NLS-1$
+                       for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+                               BodyDeclaration d = (BodyDeclaration) it.next();
+                               d.accept(this);
+                               // other body declarations include trailing punctuation
+                       }
+               }
+               this.buffer.append("}\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ExpressionStatement)
+        */
+       public boolean visit(ExpressionStatement node) {
+               printIndent();
+               node.getExpression().accept(this);
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(FieldAccess)
+        */
+       public boolean visit(FieldAccess node) {
+               node.getExpression().accept(this);
+               this.buffer.append(".");//$NON-NLS-1$
+               node.getName().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(FieldDeclaration)
+        */
+       public boolean visit(FieldDeclaration node) {
+               if (node.getJavadoc() != null) {
+                       node.getJavadoc().accept(this);
+               }
+               printIndent();
+               if (node.getAST().apiLevel() == JLS2) {
+                       printModifiers(node.getModifiers());
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       printModifiers(node.modifiers());
+               }
+               node.getType().accept(this);
+               this.buffer.append(" ");//$NON-NLS-1$
+               for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+                       VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
+                       f.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(", ");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ForStatement)
+        */
+       public boolean visit(ForStatement node) {
+               printIndent();
+               this.buffer.append("for (");//$NON-NLS-1$
+               for (Iterator it = node.initializers().iterator(); it.hasNext(); ) {
+                       Expression e = (Expression) it.next();
+                       e.accept(this);
+                       if (it.hasNext()) buffer.append(", ");//$NON-NLS-1$
+               }
+               this.buffer.append("; ");//$NON-NLS-1$
+               if (node.getExpression() != null) {
+                       node.getExpression().accept(this);
+               }
+               this.buffer.append("; ");//$NON-NLS-1$
+               for (Iterator it = node.updaters().iterator(); it.hasNext(); ) {
+                       Expression e = (Expression) it.next();
+                       e.accept(this);
+                       if (it.hasNext()) buffer.append(", ");//$NON-NLS-1$
+               }
+               this.buffer.append(") ");//$NON-NLS-1$
+               node.getBody().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(IfStatement)
+        */
+       public boolean visit(IfStatement node) {
+               printIndent();
+               this.buffer.append("if (");//$NON-NLS-1$
+               node.getExpression().accept(this);
+               this.buffer.append(") ");//$NON-NLS-1$
+               node.getThenStatement().accept(this);
+               if (node.getElseStatement() != null) {
+                       this.buffer.append(" else ");//$NON-NLS-1$
+                       node.getElseStatement().accept(this);
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ImportDeclaration)
+        */
+       public boolean visit(ImportDeclaration node) {
+               printIndent();
+               this.buffer.append("import ");//$NON-NLS-1$
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       if (node.isStatic()) {
+                               this.buffer.append("static ");//$NON-NLS-1$
+                       }
+               }
+               node.getName().accept(this);
+               if (node.isOnDemand()) {
+                       this.buffer.append(".*");//$NON-NLS-1$
+               }
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(InfixExpression)
+        */
+       public boolean visit(InfixExpression node) {
+               node.getLeftOperand().accept(this);
+               this.buffer.append(' ');  // for cases like x= i - -1; or x= i++ + ++i;
+               this.buffer.append(node.getOperator().toString());
+               this.buffer.append(' ');
+               node.getRightOperand().accept(this);
+               final List extendedOperands = node.extendedOperands();
+               if (extendedOperands.size() != 0) {
+                       this.buffer.append(' ');
+                       for (Iterator it = extendedOperands.iterator(); it.hasNext(); ) {
+                               this.buffer.append(node.getOperator().toString()).append(' ');
+                               Expression e = (Expression) it.next();
+                               e.accept(this);
+                       }
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(Initializer)
+        */
+       public boolean visit(Initializer node) {
+               if (node.getJavadoc() != null) {
+                       node.getJavadoc().accept(this);
+               }
+               if (node.getAST().apiLevel() == JLS2) {
+                       printModifiers(node.getModifiers());
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       printModifiers(node.modifiers());
+               }
+               node.getBody().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(InstanceofExpression)
+        */
+       public boolean visit(InstanceofExpression node) {
+               node.getLeftOperand().accept(this);
+               this.buffer.append(" instanceof ");//$NON-NLS-1$
+               node.getRightOperand().accept(this);
+               return false;
+       }
+       
+       /*
+        * @see ASTVisitor#visit(Javadoc)
+        */
+       public boolean visit(Javadoc node) {
+               printIndent();
+               this.buffer.append("/** ");//$NON-NLS-1$
+               for (Iterator it = node.tags().iterator(); it.hasNext(); ) {
+                       ASTNode e = (ASTNode) it.next();
+                       e.accept(this);
+               }
+               this.buffer.append("\n */\n");//$NON-NLS-1$
+               return false;
+       }
+       
+       /*
+        * @see ASTVisitor#visit(LabeledStatement)
+        */
+       public boolean visit(LabeledStatement node) {
+               printIndent();
+               node.getLabel().accept(this);
+               this.buffer.append(": ");//$NON-NLS-1$
+               node.getBody().accept(this);
+               return false;
+       }
+       
+       /*
+        * @see ASTVisitor#visit(LineComment)
+        * @since 3.0
+        */
+       public boolean visit(LineComment node) {
+               this.buffer.append("//\n");//$NON-NLS-1$
+               return false;
+       }
+       
+       /*
+        * @see ASTVisitor#visit(MarkerAnnotation)
+        * @since 3.1
+        */
+       public boolean visit(MarkerAnnotation node) {
+               this.buffer.append("@");//$NON-NLS-1$
+               node.getTypeName().accept(this);
+               return false;
+       }
+       
+       /*
+        * @see ASTVisitor#visit(MemberRef)
+        * @since 3.0
+        */
+       public boolean visit(MemberRef node) {
+               if (node.getQualifier() != null) {
+                       node.getQualifier().accept(this);
+               }
+               this.buffer.append("#");//$NON-NLS-1$
+               node.getName().accept(this);
+               return false;
+       }
+       
+       /*
+        * @see ASTVisitor#visit(MemberValuePair)
+        * @since 3.1
+        */
+       public boolean visit(MemberValuePair node) {
+               node.getName().accept(this);
+               this.buffer.append("=");//$NON-NLS-1$
+               node.getValue().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(MethodDeclaration)
+        */
+       public boolean visit(MethodDeclaration node) {
+               if (node.getJavadoc() != null) {
+                       node.getJavadoc().accept(this);
+               }
+               printIndent();
+               if (node.getAST().apiLevel() == JLS2) {
+                       printModifiers(node.getModifiers());
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       printModifiers(node.modifiers());
+                       if (!node.typeParameters().isEmpty()) {
+                               this.buffer.append("<");//$NON-NLS-1$
+                               for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) {
+                                       TypeParameter t = (TypeParameter) it.next();
+                                       t.accept(this);
+                                       if (it.hasNext()) {
+                                               this.buffer.append(",");//$NON-NLS-1$
+                                       }
+                               }
+                               this.buffer.append(">");//$NON-NLS-1$
+                       }
+               }
+               if (!node.isConstructor()) {
+                       if (node.getAST().apiLevel() == JLS2) {
+                               this.getReturnType(node).accept(this);
+                       } else {
+                               if (node.getReturnType2() != null) {
+                                       node.getReturnType2().accept(this);
+                               } else {
+                                       // methods really ought to have a return type
+                                       this.buffer.append("void");//$NON-NLS-1$
+                               }
+                       }
+                       this.buffer.append(" ");//$NON-NLS-1$
+               }
+               node.getName().accept(this);
+               this.buffer.append("(");//$NON-NLS-1$
+               for (Iterator it = node.parameters().iterator(); it.hasNext(); ) {
+                       SingleVariableDeclaration v = (SingleVariableDeclaration) it.next();
+                       v.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(",");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(")");//$NON-NLS-1$
+               for (int i = 0; i < node.getExtraDimensions(); i++) {
+                       this.buffer.append("[]"); //$NON-NLS-1$
+               }               
+               if (!node.thrownExceptions().isEmpty()) {
+                       this.buffer.append(" throws ");//$NON-NLS-1$
+                       for (Iterator it = node.thrownExceptions().iterator(); it.hasNext(); ) {
+                               Name n = (Name) it.next();
+                               n.accept(this);
+                               if (it.hasNext()) {
+                                       this.buffer.append(", ");//$NON-NLS-1$
+                               }
+                       }
+                       this.buffer.append(" ");//$NON-NLS-1$
+               }
+               if (node.getBody() == null) {
+                       this.buffer.append(";\n");//$NON-NLS-1$
+               } else {
+                       node.getBody().accept(this);
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(MethodInvocation)
+        */
+       public boolean visit(MethodInvocation node) {
+               if (node.getExpression() != null) {
+                       node.getExpression().accept(this);
+                       this.buffer.append(".");//$NON-NLS-1$
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       if (!node.typeArguments().isEmpty()) {
+                               this.buffer.append("<");//$NON-NLS-1$
+                               for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+                                       Type t = (Type) it.next();
+                                       t.accept(this);
+                                       if (it.hasNext()) {
+                                               this.buffer.append(",");//$NON-NLS-1$
+                                       }
+                               }
+                               this.buffer.append(">");//$NON-NLS-1$
+                       }
+               }
+               node.getName().accept(this);
+               this.buffer.append("(");//$NON-NLS-1$
+               for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+                       Expression e = (Expression) it.next();
+                       e.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(",");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(")");//$NON-NLS-1$
+               return false;
+       }
+       
+       /*
+        * @see ASTVisitor#visit(MethodRef)
+        * @since 3.0
+        */
+       public boolean visit(MethodRef node) {
+               if (node.getQualifier() != null) {
+                       node.getQualifier().accept(this);
+               }
+               this.buffer.append("#");//$NON-NLS-1$
+               node.getName().accept(this);
+               this.buffer.append("(");//$NON-NLS-1$
+               for (Iterator it = node.parameters().iterator(); it.hasNext(); ) {
+                       MethodRefParameter e = (MethodRefParameter) it.next();
+                       e.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(",");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(")");//$NON-NLS-1$
+               return false;
+       }
+       
+       /*
+        * @see ASTVisitor#visit(MethodRefParameter)
+        * @since 3.0
+        */
+       public boolean visit(MethodRefParameter node) {
+               node.getType().accept(this);
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       if (node.isVarargs()) {
+                               this.buffer.append("...");//$NON-NLS-1$
+                       }
+               }
+               if (node.getName() != null) {
+                       this.buffer.append(" ");//$NON-NLS-1$
+                       node.getName().accept(this);
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(Modifier)
+        * @since 3.1
+        */
+       public boolean visit(Modifier node) {
+               this.buffer.append(node.getKeyword().toString());
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(NormalAnnotation)
+        * @since 3.1
+        */
+       public boolean visit(NormalAnnotation node) {
+               this.buffer.append("@");//$NON-NLS-1$
+               node.getTypeName().accept(this);
+               this.buffer.append("(");//$NON-NLS-1$
+               for (Iterator it = node.values().iterator(); it.hasNext(); ) {
+                       MemberValuePair p = (MemberValuePair) it.next();
+                       p.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(",");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(")");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(NullLiteral)
+        */
+       public boolean visit(NullLiteral node) {
+               this.buffer.append("null");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(NumberLiteral)
+        */
+       public boolean visit(NumberLiteral node) {
+               this.buffer.append(node.getToken());
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(PackageDeclaration)
+        */
+       public boolean visit(PackageDeclaration node) {
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       if (node.getJavadoc() != null) {
+                               node.getJavadoc().accept(this);
+                       }
+                       for (Iterator it = node.annotations().iterator(); it.hasNext(); ) {
+                               Annotation p = (Annotation) it.next();
+                               p.accept(this);
+                               this.buffer.append(" ");//$NON-NLS-1$
+                       }
+               }
+               printIndent();
+               this.buffer.append("package ");//$NON-NLS-1$
+               node.getName().accept(this);
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ParameterizedType)
+        * @since 3.1
+        */
+       public boolean visit(ParameterizedType node) {
+               node.getType().accept(this);
+               this.buffer.append("<");//$NON-NLS-1$
+               for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+                       Type t = (Type) it.next();
+                       t.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(",");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(">");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ParenthesizedExpression)
+        */
+       public boolean visit(ParenthesizedExpression node) {
+               this.buffer.append("(");//$NON-NLS-1$
+               node.getExpression().accept(this);
+               this.buffer.append(")");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(PostfixExpression)
+        */
+       public boolean visit(PostfixExpression node) {
+               node.getOperand().accept(this);
+               this.buffer.append(node.getOperator().toString());
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(PrefixExpression)
+        */
+       public boolean visit(PrefixExpression node) {
+               this.buffer.append(node.getOperator().toString());
+               node.getOperand().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(PrimitiveType)
+        */
+       public boolean visit(PrimitiveType node) {
+               this.buffer.append(node.getPrimitiveTypeCode().toString());
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(QualifiedName)
+        */
+       public boolean visit(QualifiedName node) {
+               node.getQualifier().accept(this);
+               this.buffer.append(".");//$NON-NLS-1$
+               node.getName().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(QualifiedType)
+        * @since 3.1
+        */
+       public boolean visit(QualifiedType node) {
+               node.getQualifier().accept(this);
+               this.buffer.append(".");//$NON-NLS-1$
+               node.getName().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ReturnStatement)
+        */
+       public boolean visit(ReturnStatement node) {
+               printIndent();
+               this.buffer.append("return");//$NON-NLS-1$
+               if (node.getExpression() != null) {
+                       this.buffer.append(" ");//$NON-NLS-1$
+                       node.getExpression().accept(this);
+               }
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+       
+       /*
+        * @see ASTVisitor#visit(SimpleName)
+        */
+       public boolean visit(SimpleName node) {
+               this.buffer.append(node.getIdentifier());
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(SimpleType)
+        */
+       public boolean visit(SimpleType node) {
+               return true;
+       }
+
+       /*
+        * @see ASTVisitor#visit(SingleMemberAnnotation)
+        * @since 3.1
+        */
+       public boolean visit(SingleMemberAnnotation node) {
+               this.buffer.append("@");//$NON-NLS-1$
+               node.getTypeName().accept(this);
+               this.buffer.append("(");//$NON-NLS-1$
+               node.getValue().accept(this);
+               this.buffer.append(")");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(SingleVariableDeclaration)
+        */
+       public boolean visit(SingleVariableDeclaration node) {
+               printIndent();
+               if (node.getAST().apiLevel() == JLS2) {
+                       printModifiers(node.getModifiers());
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       printModifiers(node.modifiers());
+               }
+               node.getType().accept(this);
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       if (node.isVarargs()) {
+                               this.buffer.append("...");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(" ");//$NON-NLS-1$
+               node.getName().accept(this);
+               for (int i = 0; i < node.getExtraDimensions(); i++) {
+                       this.buffer.append("[]"); //$NON-NLS-1$
+               }                       
+               if (node.getInitializer() != null) {
+                       this.buffer.append("=");//$NON-NLS-1$
+                       node.getInitializer().accept(this);
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(StringLiteral)
+        */
+       public boolean visit(StringLiteral node) {
+               this.buffer.append(node.getEscapedValue());
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(SuperConstructorInvocation)
+        */
+       public boolean visit(SuperConstructorInvocation node) {
+               printIndent();
+               if (node.getExpression() != null) {
+                       node.getExpression().accept(this);
+                       this.buffer.append(".");//$NON-NLS-1$
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       if (!node.typeArguments().isEmpty()) {
+                               this.buffer.append("<");//$NON-NLS-1$
+                               for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+                                       Type t = (Type) it.next();
+                                       t.accept(this);
+                                       if (it.hasNext()) {
+                                               this.buffer.append(",");//$NON-NLS-1$
+                                       }
+                               }
+                               this.buffer.append(">");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append("super(");//$NON-NLS-1$
+               for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+                       Expression e = (Expression) it.next();
+                       e.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(",");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(");\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(SuperFieldAccess)
+        */
+       public boolean visit(SuperFieldAccess node) {
+               if (node.getQualifier() != null) {
+                       node.getQualifier().accept(this);
+                       this.buffer.append(".");//$NON-NLS-1$
+               }
+               this.buffer.append("super.");//$NON-NLS-1$
+               node.getName().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(SuperMethodInvocation)
+        */
+       public boolean visit(SuperMethodInvocation node) {
+               if (node.getQualifier() != null) {
+                       node.getQualifier().accept(this);
+                       this.buffer.append(".");//$NON-NLS-1$
+               }
+               this.buffer.append("super.");//$NON-NLS-1$
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       if (!node.typeArguments().isEmpty()) {
+                               this.buffer.append("<");//$NON-NLS-1$
+                               for (Iterator it = node.typeArguments().iterator(); it.hasNext(); ) {
+                                       Type t = (Type) it.next();
+                                       t.accept(this);
+                                       if (it.hasNext()) {
+                                               this.buffer.append(",");//$NON-NLS-1$
+                                       }
+                               }
+                               this.buffer.append(">");//$NON-NLS-1$
+                       }
+               }
+               node.getName().accept(this);
+               this.buffer.append("(");//$NON-NLS-1$
+               for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
+                       Expression e = (Expression) it.next();
+                       e.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(",");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(")");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(SwitchCase)
+        */
+       public boolean visit(SwitchCase node) {
+               if (node.isDefault()) {
+                       this.buffer.append("default :\n");//$NON-NLS-1$
+               } else {
+                       this.buffer.append("case ");//$NON-NLS-1$
+                       node.getExpression().accept(this);
+                       this.buffer.append(":\n");//$NON-NLS-1$
+               }
+               this.indent++; //decremented in visit(SwitchStatement)
+               return false;
+       }
+       
+       /*
+        * @see ASTVisitor#visit(SwitchStatement)
+        */
+       public boolean visit(SwitchStatement node) {
+               this.buffer.append("switch (");//$NON-NLS-1$
+               node.getExpression().accept(this);
+               this.buffer.append(") ");//$NON-NLS-1$
+               this.buffer.append("{\n");//$NON-NLS-1$
+               this.indent++;
+               for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
+                       Statement s = (Statement) it.next();
+                       s.accept(this);
+                       this.indent--; // incremented in visit(SwitchCase)
+               }
+               this.indent--;
+               printIndent();
+               this.buffer.append("}\n");//$NON-NLS-1$
+               return false;
+       }
+       
+       /*
+        * @see ASTVisitor#visit(SynchronizedStatement)
+        */
+       public boolean visit(SynchronizedStatement node) {
+               this.buffer.append("synchronized (");//$NON-NLS-1$
+               node.getExpression().accept(this);
+               this.buffer.append(") ");//$NON-NLS-1$
+               node.getBody().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(TagElement)
+        * @since 3.0
+        */
+       public boolean visit(TagElement node) {
+               if (node.isNested()) {
+                       // nested tags are always enclosed in braces
+                       this.buffer.append("{");//$NON-NLS-1$
+               } else {
+                       // top-level tags always begin on a new line
+                       this.buffer.append("\n * ");//$NON-NLS-1$
+               }
+               boolean previousRequiresWhiteSpace = false;
+               if (node.getTagName() != null) {
+                       this.buffer.append(node.getTagName());
+                       previousRequiresWhiteSpace = true;
+               }
+               boolean previousRequiresNewLine = false;
+               for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+                       ASTNode e = (ASTNode) it.next();
+                       // assume text elements include necessary leading and trailing whitespace
+                       // but Name, MemberRef, MethodRef, and nested TagElement do not include white space
+                       boolean currentIncludesWhiteSpace = (e instanceof TextElement);
+                       if (previousRequiresNewLine && currentIncludesWhiteSpace) {
+                               this.buffer.append("\n * ");//$NON-NLS-1$
+                       }
+                       previousRequiresNewLine = currentIncludesWhiteSpace;
+                       // add space if required to separate
+                       if (previousRequiresWhiteSpace && !currentIncludesWhiteSpace) {
+                               this.buffer.append(" "); //$NON-NLS-1$
+                       }
+                       e.accept(this);
+                       previousRequiresWhiteSpace = !currentIncludesWhiteSpace && !(e instanceof TagElement);
+               }
+               if (node.isNested()) {
+                       this.buffer.append("}");//$NON-NLS-1$
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(TextElement)
+        * @since 3.0
+        */
+       public boolean visit(TextElement node) {
+               this.buffer.append(node.getText());
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ThisExpression)
+        */
+       public boolean visit(ThisExpression node) {
+               if (node.getQualifier() != null) {
+                       node.getQualifier().accept(this);
+                       this.buffer.append(".");//$NON-NLS-1$
+               }
+               this.buffer.append("this");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(ThrowStatement)
+        */
+       public boolean visit(ThrowStatement node) {
+               printIndent();
+               this.buffer.append("throw ");//$NON-NLS-1$
+               node.getExpression().accept(this);
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(TryStatement)
+        */
+       public boolean visit(TryStatement node) {
+               printIndent();
+               this.buffer.append("try ");//$NON-NLS-1$
+               node.getBody().accept(this);
+               this.buffer.append(" ");//$NON-NLS-1$
+               for (Iterator it = node.catchClauses().iterator(); it.hasNext(); ) {
+                       CatchClause cc = (CatchClause) it.next();
+                       cc.accept(this);
+               }
+               if (node.getFinally() != null) {
+                       this.buffer.append(" finally ");//$NON-NLS-1$
+                       node.getFinally().accept(this);
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(TypeDeclaration)
+        */
+       public boolean visit(TypeDeclaration node) {
+               if (node.getJavadoc() != null) {
+                       node.getJavadoc().accept(this);
+               }
+               if (node.getAST().apiLevel() == JLS2) {
+                       printModifiers(node.getModifiers());
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       printModifiers(node.modifiers());
+               }
+               this.buffer.append(node.isInterface() ? "interface " : "class ");//$NON-NLS-2$//$NON-NLS-1$
+               node.getName().accept(this);
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       if (!node.typeParameters().isEmpty()) {
+                               this.buffer.append("<");//$NON-NLS-1$
+                               for (Iterator it = node.typeParameters().iterator(); it.hasNext(); ) {
+                                       TypeParameter t = (TypeParameter) it.next();
+                                       t.accept(this);
+                                       if (it.hasNext()) {
+                                               this.buffer.append(",");//$NON-NLS-1$
+                                       }
+                               }
+                               this.buffer.append(">");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(" ");//$NON-NLS-1$
+               if (node.getAST().apiLevel() == JLS2) {
+                       if (this.getSuperclass(node) != null) {
+                               this.buffer.append("extends ");//$NON-NLS-1$
+                               this.getSuperclass(node).accept(this);
+                               this.buffer.append(" ");//$NON-NLS-1$
+                       }
+                       if (!this.superInterfaces(node).isEmpty()) {
+                               this.buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$
+                               for (Iterator it = this.superInterfaces(node).iterator(); it.hasNext(); ) {
+                                       Name n = (Name) it.next();
+                                       n.accept(this);
+                                       if (it.hasNext()) {
+                                               this.buffer.append(", ");//$NON-NLS-1$
+                                       }
+                               }
+                               this.buffer.append(" ");//$NON-NLS-1$
+                       }
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       if (node.getSuperclassType() != null) {
+                               this.buffer.append("extends ");//$NON-NLS-1$
+                               node.getSuperclassType().accept(this);
+                               this.buffer.append(" ");//$NON-NLS-1$
+                       }
+                       if (!node.superInterfaceTypes().isEmpty()) {
+                               this.buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$
+                               for (Iterator it = node.superInterfaceTypes().iterator(); it.hasNext(); ) {
+                                       Type t = (Type) it.next();
+                                       t.accept(this);
+                                       if (it.hasNext()) {
+                                               this.buffer.append(", ");//$NON-NLS-1$
+                                       }
+                               }
+                               this.buffer.append(" ");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append("{\n");//$NON-NLS-1$
+               this.indent++;
+               for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
+                       BodyDeclaration d = (BodyDeclaration) it.next();
+                       d.accept(this);
+               }
+               this.indent--;
+               printIndent();
+               this.buffer.append("}\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(TypeDeclarationStatement)
+        */
+       public boolean visit(TypeDeclarationStatement node) {
+               if (node.getAST().apiLevel() == JLS2) {
+                       this.getTypeDeclaration(node).accept(this);
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       node.getDeclaration().accept(this);
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(TypeLiteral)
+        */
+       public boolean visit(TypeLiteral node) {
+               node.getType().accept(this);
+               this.buffer.append(".class");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(TypeParameter)
+        * @since 3.1
+        */
+       public boolean visit(TypeParameter node) {
+               node.getName().accept(this);
+               if (!node.typeBounds().isEmpty()) {
+                       this.buffer.append(" extends ");//$NON-NLS-1$
+                       for (Iterator it = node.typeBounds().iterator(); it.hasNext(); ) {
+                               Type t = (Type) it.next();
+                               t.accept(this);
+                               if (it.hasNext()) {
+                                       this.buffer.append(" & ");//$NON-NLS-1$
+                               }
+                       }
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(VariableDeclarationExpression)
+        */
+       public boolean visit(VariableDeclarationExpression node) {
+               if (node.getAST().apiLevel() == JLS2) {
+                       printModifiers(node.getModifiers());
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       printModifiers(node.modifiers());
+               }
+               node.getType().accept(this);
+               this.buffer.append(" ");//$NON-NLS-1$
+               for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+                       VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
+                       f.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(", ");//$NON-NLS-1$
+                       }
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(VariableDeclarationFragment)
+        */
+       public boolean visit(VariableDeclarationFragment node) {
+               node.getName().accept(this);
+               for (int i = 0; i < node.getExtraDimensions(); i++) {
+                       this.buffer.append("[]");//$NON-NLS-1$
+               }
+               if (node.getInitializer() != null) {
+                       this.buffer.append("=");//$NON-NLS-1$
+                       node.getInitializer().accept(this);
+               }
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(VariableDeclarationStatement)
+        */
+       public boolean visit(VariableDeclarationStatement node) {
+               printIndent();
+               if (node.getAST().apiLevel() == JLS2) {
+                       printModifiers(node.getModifiers());
+               }
+               if (node.getAST().apiLevel() >= AST.JLS3) {
+                       printModifiers(node.modifiers());
+               }
+               node.getType().accept(this);
+               this.buffer.append(" ");//$NON-NLS-1$
+               for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
+                       VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
+                       f.accept(this);
+                       if (it.hasNext()) {
+                               this.buffer.append(", ");//$NON-NLS-1$
+                       }
+               }
+               this.buffer.append(";\n");//$NON-NLS-1$
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(WhileStatement)
+        */
+       public boolean visit(WhileStatement node) {
+               printIndent();
+               this.buffer.append("while (");//$NON-NLS-1$
+               node.getExpression().accept(this);
+               this.buffer.append(") ");//$NON-NLS-1$
+               node.getBody().accept(this);
+               return false;
+       }
+
+       /*
+        * @see ASTVisitor#visit(WildcardType)
+        * @since 3.1
+        */
+       public boolean visit(WildcardType node) {
+               this.buffer.append("?");//$NON-NLS-1$
+               Type bound = node.getBound();
+               if (bound != null) {
+                       if (node.isUpperBound()) {
+                               this.buffer.append(" extends ");//$NON-NLS-1$
+                       } else {
+                               this.buffer.append(" super ");//$NON-NLS-1$
+                       }
+                       bound.accept(this);
+               }
+               return false;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/RecordedParsingInformation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/RecordedParsingInformation.java
new file mode 100644 (file)
index 0000000..cb4f23f
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2006 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 net.sourceforge.phpdt.internal.core.util;
+
+import net.sourceforge.phpdt.core.compiler.CategorizedProblem;
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+
+/**
+ * Use to keep track of recorded information during the parsing like comment positions,
+ * line ends or problems.
+ */
+public class RecordedParsingInformation {
+       public CategorizedProblem[] problems;
+       public int problemsCount;
+       public int[] lineEnds;
+       public int[][] commentPositions;
+       
+       public RecordedParsingInformation(CategorizedProblem[] problems, int[] lineEnds, int[][] commentPositions) {
+               this.problems = problems;
+               this.lineEnds = lineEnds;
+               this.commentPositions = commentPositions;
+               this.problemsCount = problems != null ? problems.length : 0;
+       }
+       
+       void updateRecordedParsingInformation(CompilationResult compilationResult) {
+               if (compilationResult.problems != null) {
+                       this.problems = compilationResult.problems;
+                       this.problemsCount = this.problems.length;
+               }
+       }
+}