Initial upgrade to Platform/JDT 3.4.1
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / ASTConverter.java
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--;
+                       }               
+               }
+       }
+}