new version with WorkingCopy Management
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / SourceElementParser.java
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/SourceElementParser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/SourceElementParser.java
new file mode 100644 (file)
index 0000000..b3c72a0
--- /dev/null
@@ -0,0 +1,1293 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
+import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
+import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
+import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
+import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.AnonymousLocalTypeDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.Argument;
+import net.sourceforge.phpeclipse.internal.compiler.ast.AstNode;
+import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.ExplicitConstructorCall;
+import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.LocalTypeDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.MemberTypeDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.NameReference;
+import net.sourceforge.phpeclipse.internal.compiler.ast.QualifiedAllocationExpression;
+import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
+
+
+
+/**
+ * A source element parser extracts structural and reference information
+ * from a piece of source.
+ *
+ * also see @ISourceElementRequestor
+ *
+ * The structural investigation includes:
+ * - the package statement
+ * - import statements
+ * - top-level types: package member, member types (member types of member types...)
+ * - fields
+ * - methods
+ *
+ * If reference information is requested, then all source constructs are
+ * investigated and type, field & method references are provided as well.
+ *
+ * Any (parsing) problem encountered is also provided.
+ */
+
+public class SourceElementParser extends UnitParser {
+       
+       ISourceElementRequestor requestor;
+       int fieldCount;
+       int localIntPtr;
+       int lastFieldEndPosition;
+       ISourceType sourceType;
+       boolean reportReferenceInfo;
+       char[][] typeNames;
+       char[][] superTypeNames;
+       int nestedTypeIndex;
+       static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
+       NameReference[] unknownRefs;
+       int unknownRefsCounter;
+       LocalDeclarationVisitor localDeclarationVisitor = null;
+//     CompilerOptions options;
+       
+/**
+ * An ast visitor that visits local type declarations.
+ */
+public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
+//     public boolean visit(
+//                     AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
+//                     BlockScope scope) {
+//             notifySourceElementRequestor(anonymousTypeDeclaration, sourceType == null);
+//             return false; // don't visit members as this was done during notifySourceElementRequestor(...)
+//     }
+       public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
+               notifySourceElementRequestor(typeDeclaration, sourceType == null);
+               return false; // don't visit members as this was done during notifySourceElementRequestor(...)
+       }
+       public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
+               notifySourceElementRequestor(typeDeclaration, sourceType == null);
+               return false; // don't visit members as this was done during notifySourceElementRequestor(...)
+       }
+       
+}
+
+public SourceElementParser(
+       final ISourceElementRequestor requestor, 
+       IProblemFactory problemFactory) {
+//     CompilerOptions options) {
+       // we want to notify all syntax error with the acceptProblem API
+       // To do so, we define the record method of the ProblemReporter
+       super(
+       new ProblemReporter(
+               DefaultErrorHandlingPolicies.exitAfterAllProblems(),
+//             options, 
+               problemFactory) {
+               public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
+                       unitResult.record(problem, referenceContext);
+                       requestor.acceptProblem(problem);
+               }
+       });
+//     true);
+//     options.sourceLevel >= CompilerOptions.JDK1_4);
+       this.requestor = requestor;
+       typeNames = new char[4][];
+       superTypeNames = new char[4][];
+       nestedTypeIndex = 0;
+//     this.options = options;
+}
+
+/** @deprecated use SourceElementParser(ISourceElementRequestor, IProblemFactory, CompilerOptions) */
+//public SourceElementParser(
+//     final ISourceElementRequestor requestor, 
+//     IProblemFactory problemFactory) {
+//             this(requestor, problemFactory, new CompilerOptions());
+//}
+
+//public SourceElementParser(
+//     final ISourceElementRequestor requestor, 
+//     IProblemFactory problemFactory,
+//     CompilerOptions options,
+//     boolean reportLocalDeclarations) {
+//             this(requestor, problemFactory, options);
+//             if (reportLocalDeclarations) {
+//                     this.localDeclarationVisitor = new LocalDeclarationVisitor();
+//             }
+//}
+
+//public void checkAnnotation() {
+//     int firstCommentIndex = scanner.commentPtr;
+//
+//     super.checkAnnotation();
+//
+//     // modify the modifier source start to point at the first comment
+//     if (firstCommentIndex >= 0) {
+//             modifiersSourceStart = scanner.commentStarts[0]; 
+//     }
+//}
+
+//protected void classInstanceCreation(boolean alwaysQualified) {
+//
+//     boolean previousFlag = reportReferenceInfo;
+//     reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
+//     super.classInstanceCreation(alwaysQualified);
+//     reportReferenceInfo = previousFlag;
+//     if (reportReferenceInfo){
+//             AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
+//             TypeReference typeRef = alloc.type;
+//             requestor.acceptConstructorReference(
+//                     typeRef instanceof SingleTypeReference 
+//                             ? ((SingleTypeReference) typeRef).token
+//                             : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
+//                     alloc.arguments == null ? 0 : alloc.arguments.length, 
+//                     alloc.sourceStart);
+//     }
+//}
+//protected void consumeConstructorHeaderName() {
+//     // ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('
+//
+//     /* recovering - might be an empty message send */
+//     if (currentElement != null){
+//             if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
+//                     lastCheckPoint = scanner.startPosition; // force to restart at this exact position                              
+//                     restartRecovery = true;
+//                     return;
+//             }
+//     }
+//     SourceConstructorDeclaration cd = new SourceConstructorDeclaration(this.compilationUnit.compilationResult);
+//
+//     //name -- this is not really revelant but we do .....
+//     cd.selector = identifierStack[identifierPtr];
+//     long selectorSourcePositions = identifierPositionStack[identifierPtr--];
+//     identifierLengthPtr--;
+//
+//     //modifiers
+//     cd.declarationSourceStart = intStack[intPtr--];
+//     cd.modifiers = intStack[intPtr--];
+//
+//     //highlight starts at the selector starts
+//     cd.sourceStart = (int) (selectorSourcePositions >>> 32);
+//     cd.selectorSourceEnd = (int) selectorSourcePositions;
+//     pushOnAstStack(cd);
+//
+//     cd.sourceEnd = lParenPos;
+//     cd.bodyStart = lParenPos+1;
+//     listLength = 0; // initialize listLength before reading parameters/throws
+//
+//     // recovery
+//     if (currentElement != null){
+//             lastCheckPoint = cd.bodyStart;
+//             if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
+//                     || cd.modifiers != 0){
+//                     currentElement = currentElement.add(cd, 0);
+//                     lastIgnoredToken = -1;
+//             }
+//     }       
+//}
+///**
+// *
+// * INTERNAL USE-ONLY
+// */
+//protected void consumeExitVariableWithInitialization() {
+//     // ExitVariableWithInitialization ::= $empty
+//     // the scanner is located after the comma or the semi-colon.
+//     // we want to include the comma or the semi-colon
+//     super.consumeExitVariableWithInitialization();
+//     if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
+//             return;
+//     ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
+//}
+//protected void consumeExitVariableWithoutInitialization() {
+//     // ExitVariableWithoutInitialization ::= $empty
+//     // do nothing by default
+//     super.consumeExitVariableWithoutInitialization();
+//     if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
+//             return;
+//     ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
+//}
+///**
+// *
+// * INTERNAL USE-ONLY
+// */
+//protected void consumeFieldAccess(boolean isSuperAccess) {
+//     // FieldAccess ::= Primary '.' 'Identifier'
+//     // FieldAccess ::= 'super' '.' 'Identifier'
+//     super.consumeFieldAccess(isSuperAccess);
+//     FieldReference fr = (FieldReference) expressionStack[expressionPtr];
+//     if (reportReferenceInfo) {
+//             requestor.acceptFieldReference(fr.token, fr.sourceStart);
+//     }
+//}
+//protected void consumeMethodHeaderName() {
+//     // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+//     SourceMethodDeclaration md = new SourceMethodDeclaration(this.compilationUnit.compilationResult);
+//
+//     //name
+//     md.selector = identifierStack[identifierPtr];
+//     long selectorSourcePositions = identifierPositionStack[identifierPtr--];
+//     identifierLengthPtr--;
+//     //type
+//     md.returnType = getTypeReference(intStack[intPtr--]);
+//     //modifiers
+//     md.declarationSourceStart = intStack[intPtr--];
+//     md.modifiers = intStack[intPtr--];
+//
+//     //highlight starts at selector start
+//     md.sourceStart = (int) (selectorSourcePositions >>> 32);
+//     md.selectorSourceEnd = (int) selectorSourcePositions;
+//     pushOnAstStack(md);
+//     md.sourceEnd = lParenPos;
+//     md.bodyStart = lParenPos+1;
+//     listLength = 0; // initialize listLength before reading parameters/throws
+//     
+//     // recovery
+//     if (currentElement != null){
+//             if (currentElement instanceof RecoveredType 
+//                     //|| md.modifiers != 0
+//                     || (scanner.getLineNumber(md.returnType.sourceStart)
+//                                     == scanner.getLineNumber(md.sourceStart))){
+//                     lastCheckPoint = md.bodyStart;
+//                     currentElement = currentElement.add(md, 0);
+//                     lastIgnoredToken = -1;                  
+//             } else {
+//                     lastCheckPoint = md.sourceStart;
+//                     restartRecovery = true;
+//             }
+//     }               
+//}
+///**
+// *
+// * INTERNAL USE-ONLY
+// */
+//protected void consumeMethodInvocationName() {
+//     // MethodInvocation ::= Name '(' ArgumentListopt ')'
+//
+//     // when the name is only an identifier...we have a message send to "this" (implicit)
+//     super.consumeMethodInvocationName();
+//     MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+//     Expression[] args = messageSend.arguments;
+//     if (reportReferenceInfo) {
+//             requestor.acceptMethodReference(
+//                     messageSend.selector, 
+//                     args == null ? 0 : args.length, 
+//                     (int)(messageSend.nameSourcePosition >>> 32));
+//     }
+//}
+///**
+// *
+// * INTERNAL USE-ONLY
+// */
+//protected void consumeMethodInvocationPrimary() {
+//     super.consumeMethodInvocationPrimary();
+//     MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+//     Expression[] args = messageSend.arguments;
+//     if (reportReferenceInfo) {
+//             requestor.acceptMethodReference(
+//                     messageSend.selector, 
+//                     args == null ? 0 : args.length, 
+//                     (int)(messageSend.nameSourcePosition >>> 32));
+//     }
+//}
+///**
+// *
+// * INTERNAL USE-ONLY
+// */
+//protected void consumeMethodInvocationSuper() {
+//     // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
+//     super.consumeMethodInvocationSuper();
+//     MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+//     Expression[] args = messageSend.arguments;
+//     if (reportReferenceInfo) {
+//             requestor.acceptMethodReference(
+//                     messageSend.selector, 
+//                     args == null ? 0 : args.length, 
+//                     (int)(messageSend.nameSourcePosition >>> 32));
+//     }
+//}
+//protected void consumeSingleTypeImportDeclarationName() {
+//     // SingleTypeImportDeclarationName ::= 'import' Name
+//     /* push an ImportRef build from the last name 
+//     stored in the identifier stack. */
+//
+//     super.consumeSingleTypeImportDeclarationName();
+//     ImportReference impt = (ImportReference)astStack[astPtr];
+//     if (reportReferenceInfo) {
+//             requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
+//     }
+//}
+//protected void consumeTypeImportOnDemandDeclarationName() {
+//     // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+//     /* push an ImportRef build from the last name 
+//     stored in the identifier stack. */
+//
+//     super.consumeTypeImportOnDemandDeclarationName();
+//     ImportReference impt = (ImportReference)astStack[astPtr];
+//     if (reportReferenceInfo) {
+//             requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
+//     }
+//}
+//protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
+//     return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
+//}
+//protected CompilationUnitDeclaration endParse(int act) {
+//     if (sourceType != null) {
+//             if (sourceType.isInterface()) {
+//                     consumeInterfaceDeclaration();
+//             } else {
+//                     consumeClassDeclaration();
+//             }
+//     }
+//     if (compilationUnit != null) {
+//             CompilationUnitDeclaration result = super.endParse(act);
+//             return result;
+//     } else {
+//             return null;
+//     }               
+//}
+/*
+ * Flush annotations defined prior to a given positions.
+ *
+ * Note: annotations are stacked in syntactical order
+ *
+ * Either answer given <position>, or the end position of a comment line 
+ * immediately following the <position> (same line)
+ *
+ * e.g.
+ * void foo(){
+ * } // end of method foo
+ */
+// 
+//public int flushAnnotationsDefinedPriorTo(int position) {
+//
+//     return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
+//}
+//public TypeReference getTypeReference(int dim) {
+//     /* build a Reference on a variable that may be qualified or not
+//      * This variable is a type reference and dim will be its dimensions
+//      */
+//     int length;
+//     if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+//             // single variable reference
+//             if (dim == 0) {
+//                     SingleTypeReference ref = 
+//                             new SingleTypeReference(
+//                                     identifierStack[identifierPtr], 
+//                                     identifierPositionStack[identifierPtr--]);
+//                     if (reportReferenceInfo) {
+//                             requestor.acceptTypeReference(ref.token, ref.sourceStart);
+//                     }
+//                     return ref;
+//             } else {
+//                     ArrayTypeReference ref = 
+//                             new ArrayTypeReference(
+//                                     identifierStack[identifierPtr], 
+//                                     dim, 
+//                                     identifierPositionStack[identifierPtr--]); 
+//                     ref.sourceEnd = endPosition;
+//                     if (reportReferenceInfo) {
+//                             requestor.acceptTypeReference(ref.token, ref.sourceStart);
+//                     }
+//                     return ref;
+//             }
+//     } else {
+//             if (length < 0) { //flag for precompiled type reference on base types
+//                     TypeReference ref = TypeReference.baseTypeReference(-length, dim);
+//                     ref.sourceStart = intStack[intPtr--];
+//                     if (dim == 0) {
+//                             ref.sourceEnd = intStack[intPtr--];
+//                     } else {
+//                             intPtr--; // no need to use this position as it is an array
+//                             ref.sourceEnd = endPosition;
+//                     }
+//                     if (reportReferenceInfo){
+//                                     requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
+//                     }
+//                     return ref;
+//             } else { //Qualified variable reference
+//                     char[][] tokens = new char[length][];
+//                     identifierPtr -= length;
+//                     long[] positions = new long[length];
+//                     System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+//                     System.arraycopy(
+//                             identifierPositionStack, 
+//                             identifierPtr + 1, 
+//                             positions, 
+//                             0, 
+//                             length); 
+//                     if (dim == 0) {
+//                             QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
+//                             if (reportReferenceInfo) {
+//                                     requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
+//                             }
+//                             return ref;
+//                     } else {
+//                             ArrayQualifiedTypeReference ref = 
+//                                     new ArrayQualifiedTypeReference(tokens, dim, positions); 
+//                             ref.sourceEnd = endPosition;                                    
+//                             if (reportReferenceInfo) {
+//                                     requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
+//                             }
+//                             return ref;
+//                     }
+//             }
+//     }
+//}
+//public NameReference getUnspecifiedReference() {
+//     /* build a (unspecified) NameReference which may be qualified*/
+//
+//     int length;
+//     if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+//             // single variable reference
+//             SingleNameReference ref = 
+//                     new SingleNameReference(
+//                             identifierStack[identifierPtr], 
+//                             identifierPositionStack[identifierPtr--]); 
+//             if (reportReferenceInfo) {
+//                     this.addUnknownRef(ref);
+//             }
+//             return ref;
+//     } else {
+//             //Qualified variable reference
+//             char[][] tokens = new char[length][];
+//             identifierPtr -= length;
+//             System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+//             QualifiedNameReference ref = 
+//                     new QualifiedNameReference(
+//                             tokens, 
+//                             (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
+//                             (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
+//             if (reportReferenceInfo) {
+//                     this.addUnknownRef(ref);
+//             }
+//             return ref;
+//     }
+//}
+//public NameReference getUnspecifiedReferenceOptimized() {
+//     /* build a (unspecified) NameReference which may be qualified
+//     The optimization occurs for qualified reference while we are
+//     certain in this case the last item of the qualified name is
+//     a field access. This optimization is IMPORTANT while it results
+//     that when a NameReference is build, the type checker should always
+//     look for that it is not a type reference */
+//
+//     int length;
+//     if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+//             // single variable reference
+//             SingleNameReference ref = 
+//                     new SingleNameReference(
+//                             identifierStack[identifierPtr], 
+//                             identifierPositionStack[identifierPtr--]); 
+//             ref.bits &= ~AstNode.RestrictiveFlagMASK;
+//             ref.bits |= LOCAL | FIELD;
+//             if (reportReferenceInfo) {
+//                     this.addUnknownRef(ref);
+//             }
+//             return ref;
+//     }
+//
+//     //Qualified-variable-reference
+//     //In fact it is variable-reference DOT field-ref , but it would result in a type
+//     //conflict tha can be only reduce by making a superclass (or inetrface ) between
+//     //nameReference and FiledReference or putting FieldReference under NameReference
+//     //or else..........This optimisation is not really relevant so just leave as it is
+//
+//     char[][] tokens = new char[length][];
+//     identifierPtr -= length;
+//     System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+//     QualifiedNameReference ref = 
+//             new QualifiedNameReference(
+//                     tokens, 
+//                     (int) (identifierPositionStack[identifierPtr + 1] >> 32), 
+//     // sourceStart
+//      (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
+//     ref.bits &= ~AstNode.RestrictiveFlagMASK;
+//     ref.bits |= LOCAL | FIELD;
+//     if (reportReferenceInfo) {
+//             this.addUnknownRef(ref);
+//     }
+//     return ref;
+//}
+///**
+// *
+// * INTERNAL USE-ONLY
+// */
+//private boolean isLocalDeclaration() {
+//     int nestedDepth = nestedType;
+//     while (nestedDepth >= 0) {
+//             if (nestedMethod[nestedDepth] != 0) {
+//                     return true;
+//             }
+//             nestedDepth--;
+//     }
+//     return false;
+//}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
+       if (parsedUnit == null) {
+               // when we parse a single type member declaration the compilation unit is null, but we still
+               // want to be able to notify the requestor on the created ast node
+               if (astStack[0] instanceof AbstractMethodDeclaration) {
+                       notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
+                       return;
+               }
+               return;
+       }
+       // range check
+       boolean isInRange = 
+                               scanner.initialPosition <= parsedUnit.sourceStart
+                               && scanner.eofPosition >= parsedUnit.sourceEnd;
+       
+//     if (reportReferenceInfo) {
+//             notifyAllUnknownReferences();
+//     }
+       // collect the top level ast nodes
+       int length = 0;
+       AstNode[] nodes = null;
+       if (sourceType == null){
+               if (isInRange) {
+                       requestor.enterCompilationUnit();
+               }
+//             ImportReference currentPackage = parsedUnit.currentPackage;
+//             ImportReference[] imports = parsedUnit.imports;
+//             TypeDeclaration[] types = parsedUnit.types;
+               ArrayList types = parsedUnit.types;
+               if (types != null) {
+//             length = 
+//                     (currentPackage == null ? 0 : 1) 
+//                     + (imports == null ? 0 : imports.length)
+//                     + (types == null ? 0 : types.length);
+//             nodes = new AstNode[length];
+                       length = types.size();
+               nodes = new AstNode[length];
+               int index = 0;
+//             if (currentPackage != null) {
+//                     nodes[index++] = currentPackage;
+//             }
+//             if (imports != null) {
+//                     for (int i = 0, max = imports.length; i < max; i++) {
+//                             nodes[index++] = imports[i];
+//                     }
+//             }
+
+                       for (int i = 0, max = types.size(); i < max; i++) {
+                               nodes[index++] = (AstNode)types.get(i);
+                       }
+               }
+       } else {
+//             TypeDeclaration[] types = parsedUnit.types;
+    ArrayList types = parsedUnit.types;
+               if (types != null) {
+                       length = types.size();
+                       nodes = new AstNode[length];
+                       for (int i = 0, max = types.size(); i < max; i++) {
+                               nodes[i] = (AstNode)types.get(i);
+                       }
+               }
+       }
+       
+       // notify the nodes in the syntactical order
+       if (nodes != null && length > 0) {
+               quickSort(nodes, 0, length-1);
+               for (int i=0;i<length;i++) {
+                       AstNode node = nodes[i];
+//                     if (node instanceof ImportReference) {
+//                             ImportReference importRef = (ImportReference)node;
+//                             if (node == parsedUnit.currentPackage) {
+//                                     notifySourceElementRequestor(importRef, true);
+//                             } else {
+//                                     notifySourceElementRequestor(importRef, false);
+//                             }
+//                     } else { // instanceof TypeDeclaration
+      if (node instanceof TypeDeclaration) {
+                         notifySourceElementRequestor((TypeDeclaration)node, sourceType == null);
+//                             notifySourceElementRequestor((CompilationUnitDeclaration)node, sourceType == null);
+                       }
+                       // jsurfer - INSERT start
+                       if (node instanceof AbstractMethodDeclaration) {
+                               notifySourceElementRequestor((AbstractMethodDeclaration)node);
+                       }
+//             jsurfer - INSERT end
+               }
+       }
+       
+       if (sourceType == null){
+               if (isInRange) {
+                       requestor.exitCompilationUnit(parsedUnit.sourceEnd);
+               }
+       }
+}
+
+//private void notifyAllUnknownReferences() {
+//     for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
+//             NameReference nameRef = this.unknownRefs[i];
+//             if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
+//                     if ((nameRef.bits & BindingIds.TYPE) == 0) { 
+//                             // variable but not type
+//                             if (nameRef instanceof SingleNameReference) { 
+//                                     // local var or field
+//                                     requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
+//                             } else {
+//                                     // QualifiedNameReference
+//                                     // The last token is a field reference and the previous tokens are a type/variable references
+//                                     char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
+//                                     int tokensLength = tokens.length;
+//                                     requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd - tokens[tokensLength - 1].length + 1);
+//                                     char[][] typeRef = new char[tokensLength - 1][];
+//                                     System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
+//                                     requestor.acceptUnknownReference(typeRef, nameRef.sourceStart, nameRef.sourceEnd - tokens[tokensLength - 1].length);
+//                             }
+//                     } else {
+//                             // variable or type
+//                             if (nameRef instanceof SingleNameReference) {
+//                                     requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
+//                             } else {
+//                                     //QualifiedNameReference
+//                                     requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
+//                             }
+//                     }
+//             } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
+//                     if (nameRef instanceof SingleNameReference) {
+//                             requestor.acceptTypeReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
+//                     } else {
+//                             // it is a QualifiedNameReference
+//                             requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
+//                     }
+//             }
+//     }
+//}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
+
+       // range check
+       boolean isInRange = 
+                               scanner.initialPosition <= methodDeclaration.declarationSourceStart
+                               && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
+
+       if (methodDeclaration.isClinit()) {
+               this.visitIfNeeded(methodDeclaration);
+               return;
+       }
+
+       if (methodDeclaration.isDefaultConstructor()) {
+               if (reportReferenceInfo) {
+                       ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+                       ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
+                       if (constructorCall != null) {
+                               switch(constructorCall.accessMode) {
+                                       case ExplicitConstructorCall.This :
+                                               requestor.acceptConstructorReference(
+                                                       typeNames[nestedTypeIndex-1],
+                                                       constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
+                                                       constructorCall.sourceStart);
+                                               break;
+                                       case ExplicitConstructorCall.Super :
+                                       case ExplicitConstructorCall.ImplicitSuper :                                    
+                                               requestor.acceptConstructorReference(
+                                                       superTypeNames[nestedTypeIndex-1],
+                                                       constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
+                                                       constructorCall.sourceStart);
+                                               break;
+                               }
+                       }
+               }       
+               return; 
+       }       
+       char[][] argumentTypes = null;
+       char[][] argumentNames = null;
+       Argument[] arguments = methodDeclaration.arguments;
+       if (arguments != null) {
+               int argumentLength = arguments.length;
+               argumentTypes = new char[argumentLength][];
+               argumentNames = new char[argumentLength][];
+               for (int i = 0; i < argumentLength; i++) {
+                       argumentTypes[i] = returnTypeName(arguments[i].type);
+                       argumentNames[i] = arguments[i].name;
+               }
+       }
+       char[][] thrownExceptionTypes = null;
+       TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
+       if (thrownExceptions != null) {
+               int thrownExceptionLength = thrownExceptions.length;
+               thrownExceptionTypes = new char[thrownExceptionLength][];
+               for (int i = 0; i < thrownExceptionLength; i++) {
+                       thrownExceptionTypes[i] = 
+                               CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.'); 
+               }
+       }
+       // by default no selector end position
+       int selectorSourceEnd = -1;
+       if (methodDeclaration.isConstructor()) {
+//             if (methodDeclaration instanceof SourceConstructorDeclaration) {
+//                     selectorSourceEnd = 
+//                             ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd; 
+//             }
+               if (isInRange){
+                       requestor.enterConstructor(
+                               methodDeclaration.declarationSourceStart, 
+                               methodDeclaration.modifiers, 
+                               methodDeclaration.selector, 
+                               methodDeclaration.sourceStart, 
+                               selectorSourceEnd, 
+                               argumentTypes, 
+                               argumentNames, 
+                               thrownExceptionTypes);
+               }
+               if (reportReferenceInfo) {
+                       ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+                       ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
+                       if (constructorCall != null) {
+                               switch(constructorCall.accessMode) {
+                                       case ExplicitConstructorCall.This :
+                                               requestor.acceptConstructorReference(
+                                                       typeNames[nestedTypeIndex-1],
+                                                       constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
+                                                       constructorCall.sourceStart);
+                                               break;
+                                       case ExplicitConstructorCall.Super :
+                                       case ExplicitConstructorCall.ImplicitSuper :
+                                               requestor.acceptConstructorReference(
+                                                       superTypeNames[nestedTypeIndex-1],
+                                                       constructorCall.arguments == null ? 0 : constructorCall.arguments.length, 
+                                                       constructorCall.sourceStart);
+                                               break;
+                               }
+                       }
+               }
+               this.visitIfNeeded(methodDeclaration);
+               if (isInRange){
+                       requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
+               }
+               return;
+       }
+//     if (methodDeclaration instanceof SourceMethodDeclaration) {
+//             selectorSourceEnd = 
+//                     ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd; 
+//     }
+       if (isInRange) {
+               int modifiers = methodDeclaration.modifiers;
+//             boolean deprecated = (modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+               requestor.enterMethod(
+                       methodDeclaration.declarationSourceStart, 
+               modifiers, // deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag, 
+                       returnTypeName(((MethodDeclaration) methodDeclaration).returnType), 
+                       methodDeclaration.selector, 
+                       methodDeclaration.sourceStart, 
+                       selectorSourceEnd, 
+                       argumentTypes, 
+                       argumentNames, 
+                       thrownExceptionTypes); 
+       }               
+       this.visitIfNeeded(methodDeclaration);
+
+       if (isInRange){ 
+               requestor.exitMethod(methodDeclaration.declarationSourceEnd);
+       }
+}
+///*
+//* Update the bodyStart of the corresponding parse node
+//*/
+//public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
+//     
+//     // range check
+//     boolean isInRange = 
+//                             scanner.initialPosition <= fieldDeclaration.declarationSourceStart
+//                             && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
+//
+//     if (fieldDeclaration.isField()) {
+//             int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
+//             if (fieldDeclaration instanceof SourceFieldDeclaration) {
+//                     fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
+//                     if (fieldEndPosition == 0) {
+//                             // use the declaration source end by default
+//                             fieldEndPosition = fieldDeclaration.declarationSourceEnd;
+//                     }
+//             }
+//             if (isInRange) {
+//                     int modifiers = fieldDeclaration.modifiers;
+//                     boolean deprecated = (modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+//                     requestor.enterField(
+//                             fieldDeclaration.declarationSourceStart, 
+//                             deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag, 
+//                             returnTypeName(fieldDeclaration.type), 
+//                             fieldDeclaration.name, 
+//                             fieldDeclaration.sourceStart, 
+//                             fieldDeclaration.sourceEnd); 
+//             }
+//             this.visitIfNeeded(fieldDeclaration);
+//             if (isInRange){
+//                     requestor.exitField(
+//                             // filter out initializations that are not a constant (simple check)
+//                             (fieldDeclaration.initialization == null 
+//                                             || fieldDeclaration.initialization instanceof ArrayInitializer
+//                                             || fieldDeclaration.initialization instanceof AllocationExpression
+//                                             || fieldDeclaration.initialization instanceof ArrayAllocationExpression
+//                                             || fieldDeclaration.initialization instanceof Assignment
+//                                             || fieldDeclaration.initialization instanceof ClassLiteralAccess
+//                                             || fieldDeclaration.initialization instanceof MessageSend
+//                                             || fieldDeclaration.initialization instanceof ArrayReference
+//                                             || fieldDeclaration.initialization instanceof ThisReference) ? 
+//                                     -1 :  
+//                                     fieldDeclaration.initialization.sourceStart, 
+//                             fieldEndPosition,
+//                             fieldDeclaration.declarationSourceEnd);
+//             }
+//
+//     } else {
+//             if (isInRange){
+//                     requestor.enterInitializer(
+//                             fieldDeclaration.declarationSourceStart,
+//                             fieldDeclaration.modifiers); 
+//             }
+//             this.visitIfNeeded((Initializer)fieldDeclaration);
+//             if (isInRange){
+//                     requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
+//             }
+//     }
+//}
+//public void notifySourceElementRequestor(
+//     ImportReference importReference, 
+//     boolean isPackage) {
+//     if (isPackage) {
+//             requestor.acceptPackage(
+//                     importReference.declarationSourceStart, 
+//                     importReference.declarationSourceEnd, 
+//                     CharOperation.concatWith(importReference.getImportName(), '.')); 
+//     } else {
+//             requestor.acceptImport(
+//                     importReference.declarationSourceStart, 
+//                     importReference.declarationSourceEnd, 
+//                     CharOperation.concatWith(importReference.getImportName(), '.'), 
+//                     importReference.onDemand); 
+//     }
+//}
+public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
+////   public void notifySourceElementRequestor(AstNode typeDeclaration, boolean notifyTypePresence) {
+       
+       // range check
+       boolean isInRange = 
+                               scanner.initialPosition <= typeDeclaration.declarationSourceStart
+                               && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
+       
+       FieldDeclaration[] fields = typeDeclaration.fields;
+       AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+       MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
+       int fieldCount = fields == null ? 0 : fields.length;
+       int methodCount = methods == null ? 0 : methods.length;
+       int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
+       int fieldIndex = 0;
+       int methodIndex = 0;
+       int memberTypeIndex = 0;
+       boolean isInterface = typeDeclaration.isInterface();
+
+       if (notifyTypePresence){
+               char[][] interfaceNames = null;
+               int superInterfacesLength = 0;
+               TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+               if (superInterfaces != null) {
+                       superInterfacesLength = superInterfaces.length;
+                       interfaceNames = new char[superInterfacesLength][];
+               } else {
+                       if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
+                               // see PR 3442
+                               QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation;
+                               if (alloc != null && alloc.type != null) {
+                                       superInterfaces = new TypeReference[] { ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation.type};
+                                       superInterfacesLength = 1;
+                                       interfaceNames = new char[1][];
+                               }
+                       }
+               }
+               if (superInterfaces != null) {
+                       for (int i = 0; i < superInterfacesLength; i++) {
+                               interfaceNames[i] = 
+                                       CharOperation.concatWith(superInterfaces[i].getTypeName(), '.'); 
+                       }
+               }
+               if (isInterface) {
+                       if (isInRange){
+                               int modifiers = typeDeclaration.modifiers;
+                               boolean deprecated = false; //(modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+                               requestor.enterInterface(
+                                       typeDeclaration.declarationSourceStart, 
+                                       modifiers, //deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag, 
+                                       typeDeclaration.name, 
+                                       typeDeclaration.sourceStart, 
+                                       typeDeclaration.sourceEnd, 
+                                       interfaceNames);
+                       }
+                       if (nestedTypeIndex == typeNames.length) {
+                               // need a resize
+                               System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+                               System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+                       }
+                       typeNames[nestedTypeIndex] = typeDeclaration.name;
+                       superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
+               } else {
+                       TypeReference superclass = typeDeclaration.superclass;
+                       if (superclass == null) {
+                               if (isInRange){
+                                       requestor.enterClass(
+                                               typeDeclaration.declarationSourceStart, 
+                                               typeDeclaration.modifiers, 
+                                               typeDeclaration.name, 
+                                               typeDeclaration.sourceStart, 
+                                               typeDeclaration.sourceEnd, 
+                                               null, 
+                                               interfaceNames); 
+                               }
+                       } else {
+                               if (isInRange){
+                                       requestor.enterClass(
+                                               typeDeclaration.declarationSourceStart, 
+                                               typeDeclaration.modifiers, 
+                                               typeDeclaration.name, 
+                                               typeDeclaration.sourceStart, 
+                                               typeDeclaration.sourceEnd, 
+                                               CharOperation.concatWith(superclass.getTypeName(), '.'), 
+                                               interfaceNames); 
+                               }
+                       }
+                       if (nestedTypeIndex == typeNames.length) {
+                               // need a resize
+                               System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+                               System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+                       }
+                       typeNames[nestedTypeIndex] = typeDeclaration.name;
+                       superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
+               }
+       }
+       while ((fieldIndex < fieldCount)
+               || (memberTypeIndex < memberTypeCount)
+               || (methodIndex < methodCount)) {
+               FieldDeclaration nextFieldDeclaration = null;
+               AbstractMethodDeclaration nextMethodDeclaration = null;
+               TypeDeclaration nextMemberDeclaration = null;
+
+               int position = Integer.MAX_VALUE;
+               int nextDeclarationType = -1;
+               if (fieldIndex < fieldCount) {
+                       nextFieldDeclaration = fields[fieldIndex];
+                       if (nextFieldDeclaration.declarationSourceStart < position) {
+                               position = nextFieldDeclaration.declarationSourceStart;
+                               nextDeclarationType = 0; // FIELD
+                       }
+               }
+               if (methodIndex < methodCount) {
+                       nextMethodDeclaration = methods[methodIndex];
+                       if (nextMethodDeclaration.declarationSourceStart < position) {
+                               position = nextMethodDeclaration.declarationSourceStart;
+                               nextDeclarationType = 1; // METHOD
+                       }
+               }
+               if (memberTypeIndex < memberTypeCount) {
+                       nextMemberDeclaration = memberTypes[memberTypeIndex];
+                       if (nextMemberDeclaration.declarationSourceStart < position) {
+                               position = nextMemberDeclaration.declarationSourceStart;
+                               nextDeclarationType = 2; // MEMBER
+                       }
+               }
+               switch (nextDeclarationType) {
+                       case 0 :
+                               fieldIndex++;
+//                             notifySourceElementRequestor(nextFieldDeclaration);
+                               break;
+                       case 1 :
+                               methodIndex++;
+                               notifySourceElementRequestor(nextMethodDeclaration);
+                               break;
+                       case 2 :
+                               memberTypeIndex++;
+                               notifySourceElementRequestor(nextMemberDeclaration, true);
+               }
+       }
+       if (notifyTypePresence){
+               if (isInRange){
+                       if (isInterface) {
+                               requestor.exitInterface(typeDeclaration.declarationSourceEnd);
+                       } else {
+                               requestor.exitClass(typeDeclaration.declarationSourceEnd);
+                       }
+               }
+               nestedTypeIndex--;
+       }
+}
+public void parseCompilationUnit (
+       ICompilationUnit unit, 
+       int start, 
+       int end ) { 
+//     boolean needReferenceInfo) {
+
+//     reportReferenceInfo = needReferenceInfo;
+//     boolean old = diet;
+//     if (needReferenceInfo) {
+//             unknownRefs = new NameReference[10];
+//             unknownRefsCounter = 0;
+//     }
+       
+       try {
+//             diet = true;
+               CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
+               CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
+//             if (scanner.recordLineSeparator) {
+//                     requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
+//             }
+//             if (this.localDeclarationVisitor != null || needReferenceInfo){
+//                     diet = false;
+//                     this.getMethodBodies(parsedUnit);
+//             }               
+//             this.scanner.resetTo(start, end);
+//             notifySourceElementRequestor(parsedUnit);
+       } catch (AbortCompilation e) {
+       } finally {
+//             diet = old;
+       }
+}
+public void parseCompilationUnit(
+       ICompilationUnit unit, 
+       boolean needReferenceInfo) {
+//     boolean old = diet;
+//     if (needReferenceInfo) {
+//             unknownRefs = new NameReference[10];
+//             unknownRefsCounter = 0;
+//     }
+
+       try {
+//             diet = true;
+               reportReferenceInfo = needReferenceInfo;
+               CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, 10); //this.options.maxProblemsPerUnit);
+               CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult);
+               if (scanner.recordLineSeparator) {
+                       requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
+               }
+               int initialStart = this.scanner.initialPosition;
+               int initialEnd = this.scanner.eofPosition;
+//             if (this.localDeclarationVisitor != null || needReferenceInfo){
+//                     diet = false;
+//                     this.getMethodBodies(parsedUnit);
+//             }
+               this.scanner.resetTo(initialStart, initialEnd);
+               notifySourceElementRequestor(parsedUnit);
+       } catch (AbortCompilation e) {
+       } finally {
+//             diet = old;
+       }
+}
+//public void parseTypeMemberDeclarations(
+//     ISourceType sourceType, 
+//     ICompilationUnit sourceUnit, 
+//     int start, 
+//     int end, 
+//     boolean needReferenceInfo) {
+//     boolean old = diet;
+//     if (needReferenceInfo) {
+//             unknownRefs = new NameReference[10];
+//             unknownRefsCounter = 0;
+//     }
+//     
+//     try {
+//             diet = !needReferenceInfo;
+//             reportReferenceInfo = needReferenceInfo;
+//             CompilationResult compilationUnitResult = 
+//                     new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit); 
+//             CompilationUnitDeclaration unit = 
+//                     SourceTypeConverter.buildCompilationUnit(
+//                             new ISourceType[]{sourceType}, 
+//                             false, // no need for field and methods
+//                             false, // no need for member types
+//                             false, // no need for field initialization
+//                             problemReporter(), 
+//                             compilationUnitResult); 
+//             if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
+//                     return;
+//             this.sourceType = sourceType;
+//             try {
+//                     /* automaton initialization */
+//                     initialize();
+//                     goForClassBodyDeclarations();
+//                     /* scanner initialization */
+//                     scanner.setSource(sourceUnit.getContents());
+//                     scanner.resetTo(start, end);
+//                     /* unit creation */
+//                     referenceContext = compilationUnit = unit;
+//                     /* initialize the astStacl */
+//                     // the compilationUnitDeclaration should contain exactly one type
+//                     pushOnAstStack(unit.types[0]);
+//                     /* run automaton */
+//                     parse();
+//                     notifySourceElementRequestor(unit);
+//             } finally {
+//                     unit = compilationUnit;
+//                     compilationUnit = null; // reset parser
+//             }
+//     } catch (AbortCompilation e) {
+//     } finally {
+//             if (scanner.recordLineSeparator) {
+//                     requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
+//             }
+//             diet = old;
+//     }
+//}
+//
+//public void parseTypeMemberDeclarations(
+//     char[] contents, 
+//     int start, 
+//     int end) {
+//
+//     boolean old = diet;
+//     
+//     try {
+//             diet = true;
+//
+//             /* automaton initialization */
+//             initialize();
+//             goForClassBodyDeclarations();
+//             /* scanner initialization */
+//             scanner.setSource(contents);
+//             scanner.recordLineSeparator = false;
+//             scanner.taskTags = null;
+//             scanner.taskPriorities = null;
+//             scanner.resetTo(start, end);
+//
+//             /* unit creation */
+//             referenceContext = null;
+//
+//             /* initialize the astStacl */
+//             // the compilationUnitDeclaration should contain exactly one type
+//             /* run automaton */
+//             parse();
+//             notifySourceElementRequestor((CompilationUnitDeclaration)null);
+//     } catch (AbortCompilation e) {
+//     } finally {
+//             diet = old;
+//     }
+//}
+/**
+ * Sort the given ast nodes by their positions.
+ */
+private static void quickSort(AstNode[] sortedCollection, int left, int right) {
+       int original_left = left;
+       int original_right = right;
+       AstNode mid = sortedCollection[ (left + right) / 2];
+       do {
+               while (sortedCollection[left].sourceStart < mid.sourceStart) {
+                       left++;
+               }
+               while (mid.sourceStart < sortedCollection[right].sourceStart) {
+                       right--;
+               }
+               if (left <= right) {
+                       AstNode tmp = sortedCollection[left];
+                       sortedCollection[left] = sortedCollection[right];
+                       sortedCollection[right] = tmp;
+                       left++;
+                       right--;
+               }
+       } while (left <= right);
+       if (original_left < right) {
+               quickSort(sortedCollection, original_left, right);
+       }
+       if (left < original_right) {
+               quickSort(sortedCollection, left, original_right);
+       }
+}
+/*
+ * Answer a char array representation of the type name formatted like:
+ * - type name + dimensions
+ * Example:
+ * "A[][]".toCharArray()
+ * "java.lang.String".toCharArray()
+ */
+private char[] returnTypeName(TypeReference type) {
+       if (type == null)
+               return null;
+       int dimension = type.dimensions();
+       if (dimension != 0) {
+               char[] dimensionsArray = new char[dimension * 2];
+               for (int i = 0; i < dimension; i++) {
+                       dimensionsArray[i * 2] = '[';
+                       dimensionsArray[(i * 2) + 1] = ']';
+               }
+               return CharOperation.concat(
+                       CharOperation.concatWith(type.getTypeName(), '.'), 
+                       dimensionsArray); 
+       }
+       return CharOperation.concatWith(type.getTypeName(), '.');
+}
+
+public void addUnknownRef(NameReference nameRef) {
+       if (this.unknownRefs.length == this.unknownRefsCounter) {
+               // resize
+               System.arraycopy(
+                       this.unknownRefs,
+                       0,
+                       (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]),
+                       0,
+                       this.unknownRefsCounter);
+       }
+       this.unknownRefs[this.unknownRefsCounter++] = nameRef;
+}
+
+private void visitIfNeeded(AbstractMethodDeclaration method) {
+       if (this.localDeclarationVisitor != null 
+               && (method.bits & AstNode.HasLocalTypeMASK) != 0) {
+                       if (method.statements != null) {
+                               int statementsLength = method.statements.length;
+                               for (int i = 0; i < statementsLength; i++)
+                                       method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
+                       }
+       }
+}
+
+//private void visitIfNeeded(FieldDeclaration field) {
+//     if (this.localDeclarationVisitor != null 
+//             && (field.bits & AstNode.HasLocalTypeMASK) != 0) {
+//                     if (field.initialization != null) {
+//                             field.initialization.traverse(this.localDeclarationVisitor, null);
+//                     }
+//     }
+//}
+//
+//private void visitIfNeeded(Initializer initializer) {
+//     if (this.localDeclarationVisitor != null 
+//             && (initializer.bits & AstNode.HasLocalTypeMASK) != 0) {
+//                     if (initializer.block != null) {
+//                             initializer.block.traverse(this.localDeclarationVisitor, null);
+//                     }
+//     }
+//}
+//
+//protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
+//     if (compilationUnit == null) return;
+//     super.reportSyntaxError(act, currentKind,stateStackTop);
+//}
+
+}