improved PHP parser
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / internal / compiler / ast / TypeDeclaration.java
index 308f852..6bf3530 100644 (file)
@@ -1,18 +1,17 @@
-/*******************************************************************************
- * 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
+/***********************************************************************************************************************************
+ * 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
- *******************************************************************************/
+ * Contributors: IBM Corporation - initial API and implementation
+ **********************************************************************************************************************************/
 package net.sourceforge.phpeclipse.internal.compiler.ast;
 
+import net.sourceforge.phpeclipse.internal.compiler.ast.FieldDeclaration;
+
 import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
-import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
 import net.sourceforge.phpdt.internal.compiler.flow.InitializationFlowContext;
@@ -38,943 +37,1055 @@ import net.sourceforge.phpdt.internal.compiler.problem.AbortMethod;
 import net.sourceforge.phpdt.internal.compiler.problem.AbortType;
 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
 
-public class TypeDeclaration
-       extends Statement
-       implements ProblemSeverities, ReferenceContext {
-
-       public int modifiers;
-       public int modifiersSourceStart;
-       public char[] name;
-       public TypeReference superclass;
-       public TypeReference[] superInterfaces;
-       public FieldDeclaration[] fields;
-       public AbstractMethodDeclaration[] methods;
-       public MemberTypeDeclaration[] memberTypes;
-       public SourceTypeBinding binding;
-       public ClassScope scope;
-       public MethodScope initializerScope;
-       public MethodScope staticInitializerScope;
-       public boolean ignoreFurtherInvestigation = false;
-       public int maxFieldCount;
-       public int declarationSourceStart;
-       public int declarationSourceEnd;
-       public int bodyStart;
-       public int bodyEnd; // doesn't include the trailing comment if any.
-       protected boolean hasBeenGenerated = false;
-       public CompilationResult compilationResult;
-       private MethodDeclaration[] missingAbstractMethods;
-
-       public TypeDeclaration(CompilationResult compilationResult){
-               this.compilationResult = compilationResult;
-       }
-               
-       /*
-        *      We cause the compilation task to abort to a given extent.
-        */
-       public void abort(int abortLevel) {
-
-               if (scope == null) {
-                       throw new AbortCompilation(); // cannot do better
-               }
-
-               CompilationResult compilationResult =
-                       scope.referenceCompilationUnit().compilationResult;
-
-               switch (abortLevel) {
-                       case AbortCompilation :
-                               throw new AbortCompilation(compilationResult);
-                       case AbortCompilationUnit :
-                               throw new AbortCompilationUnit(compilationResult);
-                       case AbortMethod :
-                               throw new AbortMethod(compilationResult);
-                       default :
-                               throw new AbortType(compilationResult);
-               }
-       }
-       /**
-        * This method is responsible for adding a <clinit> method declaration to the type method collections.
-        * Note that this implementation is inserting it in first place (as VAJ or javac), and that this
-        * impacts the behavior of the method ConstantPool.resetForClinit(int. int), in so far as 
-        * the latter will have to reset the constant pool state accordingly (if it was added first, it does 
-        * not need to preserve some of the method specific cached entries since this will be the first method).
-        * inserts the clinit method declaration in the first position.
-        * 
-        * @see org.eclipse.jdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int)
-        */
-       public final void addClinit() {
-
-               //see comment on needClassInitMethod
-               if (needClassInitMethod()) {
-                       int length;
-                       AbstractMethodDeclaration[] methods;
-                       if ((methods = this.methods) == null) {
-                               length = 0;
-                               methods = new AbstractMethodDeclaration[1];
-                       } else {
-                               length = methods.length;
-                               System.arraycopy(
-                                       methods,
-                                       0,
-                                       (methods = new AbstractMethodDeclaration[length + 1]),
-                                       1,
-                                       length);
-                       }
-                       Clinit clinit = new Clinit(this.compilationResult);
-                       methods[0] = clinit;
-                       // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
-                       clinit.declarationSourceStart = clinit.sourceStart = sourceStart;
-                       clinit.declarationSourceEnd = clinit.sourceEnd = sourceEnd;
-                       clinit.bodyEnd = sourceEnd;
-                       this.methods = methods;
-               }
-       }
-
-       /**
-        *      Flow analysis for a local innertype
-        *
-        */
-       public FlowInfo analyseCode(
-               BlockScope currentScope,
-               FlowContext flowContext,
-               FlowInfo flowInfo) {
-
-               if (ignoreFurtherInvestigation)
-                       return flowInfo;
-               try {
-                       bits |= IsReachableMASK;
-                       LocalTypeBinding localType = (LocalTypeBinding) binding;
-                       
-                       localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
-                       manageEnclosingInstanceAccessIfNecessary(currentScope);
-                       
-                       updateMaxFieldCount(); // propagate down the max field count
-                       internalAnalyseCode(flowContext, flowInfo); 
-               } catch (AbortType e) {
-                       this.ignoreFurtherInvestigation = true;
-               }
-               return flowInfo;
-       }
-
-       /**
-        *      Flow analysis for a member innertype
-        *
-        */
-       public void analyseCode(ClassScope enclosingClassScope) {
-
-               if (ignoreFurtherInvestigation)
-                       return;
-               try {
-                       // propagate down the max field count
-                       updateMaxFieldCount();
-                       internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
-               } catch (AbortType e) {
-                       this.ignoreFurtherInvestigation = true;
-               }
-       }
-
-       /**
-        *      Flow analysis for a local member innertype
-        *
-        */
-       public void analyseCode(
-               ClassScope currentScope,
-               FlowContext flowContext,
-               FlowInfo flowInfo) {
-
-               if (ignoreFurtherInvestigation)
-                       return;
-               try {
-                       bits |= IsReachableMASK;
-                       LocalTypeBinding localType = (LocalTypeBinding) binding;
-
-                       localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
-                       manageEnclosingInstanceAccessIfNecessary(currentScope);
-                       
-                       updateMaxFieldCount(); // propagate down the max field count
-                       internalAnalyseCode(flowContext, flowInfo);
-               } catch (AbortType e) {
-                       this.ignoreFurtherInvestigation = true;
-               }
-       }
-
-       /**
-        *      Flow analysis for a package member type
-        *
-        */
-       public void analyseCode(CompilationUnitScope unitScope) {
-
-               if (ignoreFurtherInvestigation)
-                       return;
-               try {
-                       internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
-               } catch (AbortType e) {
-                       this.ignoreFurtherInvestigation = true;
-               }
-       }
-
-       /*
-        * Check for constructor vs. method with no return type.
-        * Answers true if at least one constructor is defined
-        */
-       public boolean checkConstructors(Parser parser) {
-
-               //if a constructor has not the name of the type,
-               //convert it into a method with 'null' as its return type
-               boolean hasConstructor = false;
-               if (methods != null) {
-                       for (int i = methods.length; --i >= 0;) {
-                               AbstractMethodDeclaration am;
-                               if ((am = methods[i]).isConstructor()) {
-                                       if (!CharOperation.equals(am.selector, name)) {
-                                               // the constructor was in fact a method with no return type
-                                               // unless an explicit constructor call was supplied
-                                               ConstructorDeclaration c = (ConstructorDeclaration) am;
-                                               if ((c.constructorCall == null)
-                                                       || (c.constructorCall.isImplicitSuper())) { //changed to a method
-                                                       MethodDeclaration m = new MethodDeclaration(this.compilationResult);
-                                                       m.sourceStart = c.sourceStart;
-                                                       m.sourceEnd = c.sourceEnd;
-                                                       m.bodyStart = c.bodyStart;
-                                                       m.bodyEnd = c.bodyEnd;
-                                                       m.declarationSourceEnd = c.declarationSourceEnd;
-                                                       m.declarationSourceStart = c.declarationSourceStart;
-                                                       m.selector = c.selector;
-                                                       m.statements = c.statements;
-                                                       m.modifiers = c.modifiers;
-                                                       m.arguments = c.arguments;
-                                                       m.thrownExceptions = c.thrownExceptions;
-                                                       m.explicitDeclarations = c.explicitDeclarations;
-                                                       m.returnType = null;
-                                                       methods[i] = m;
-                                               }
-                                       } else {
-                                               if (this.isInterface()) {
-                                                       // report the problem and continue the parsing
-                                                       parser.problemReporter().interfaceCannotHaveConstructors(
-                                                               (ConstructorDeclaration) am);
-                                               }
-                                               hasConstructor = true;
-                                       }
-                               }
-                       }
-               }
-               return hasConstructor;
-       }
-
-       public CompilationResult compilationResult() {
-
-               return this.compilationResult;
-       }
-
-       public ConstructorDeclaration createsInternalConstructor(
-               boolean needExplicitConstructorCall,
-               boolean needToInsert) {
-
-               //Add to method'set, the default constuctor that just recall the
-               //super constructor with no arguments
-               //The arguments' type will be positionned by the TC so just use
-               //the default int instead of just null (consistency purpose)
-
-               //the constructor
-               ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
-               constructor.isDefaultConstructor = true;
-               constructor.selector = name;
-               if (modifiers != AccDefault) {
-                       constructor.modifiers =
-                               ((this instanceof MemberTypeDeclaration) && (modifiers & AccPrivate) != 0)
-                                       ? AccDefault
-                                       : modifiers & AccVisibilityMASK;
-               }
-
-               //if you change this setting, please update the 
-               //SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
-               constructor.declarationSourceStart = constructor.sourceStart = sourceStart;
-               constructor.declarationSourceEnd =
-                       constructor.sourceEnd = constructor.bodyEnd = sourceEnd;
-
-               //the super call inside the constructor
-               if (needExplicitConstructorCall) {
-                       constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
-                       constructor.constructorCall.sourceStart = sourceStart;
-                       constructor.constructorCall.sourceEnd = sourceEnd;
-               }
-
-               //adding the constructor in the methods list
-               if (needToInsert) {
-                       if (methods == null) {
-                               methods = new AbstractMethodDeclaration[] { constructor };
-                       } else {
-                               AbstractMethodDeclaration[] newMethods;
-                               System.arraycopy(
-                                       methods,
-                                       0,
-                                       newMethods = new AbstractMethodDeclaration[methods.length + 1],
-                                       1,
-                                       methods.length);
-                               newMethods[0] = constructor;
-                               methods = newMethods;
-                       }
-               }
-               return constructor;
-       }
-
-       /**
-        * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding.
-        * It is used to report errors for missing abstract methods.
-        */
-       public MethodDeclaration addMissingAbstractMethodFor(MethodBinding methodBinding) {
-               TypeBinding[] argumentTypes = methodBinding.parameters;
-               int argumentsLength = argumentTypes.length;
-               //the constructor
-               MethodDeclaration methodDeclaration = new MethodDeclaration(this.compilationResult);
-               methodDeclaration.selector = methodBinding.selector;
-               methodDeclaration.sourceStart = sourceStart;
-               methodDeclaration.sourceEnd = sourceEnd;
-               methodDeclaration.modifiers = methodBinding.getAccessFlags() & ~AccAbstract;
-
-               if (argumentsLength > 0) {
-                       String baseName = "arg";//$NON-NLS-1$
-                       Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]);
-                       for (int i = argumentsLength; --i >= 0;) {
-                               arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, AccDefault);
-                       }
-               }
-
-               //adding the constructor in the methods list
-               if (this.missingAbstractMethods == null) {
-                       this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
-               } else {
-                       MethodDeclaration[] newMethods;
-                       System.arraycopy(
-                               this.missingAbstractMethods,
-                               0,
-                               newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1],
-                               1,
-                               this.missingAbstractMethods.length);
-                       newMethods[0] = methodDeclaration;
-                       this.missingAbstractMethods = newMethods;
-               }
-
-               //============BINDING UPDATE==========================
-               methodDeclaration.binding = new MethodBinding(
-                               methodDeclaration.modifiers, //methodDeclaration
-                               methodBinding.selector,
-                               methodBinding.returnType,
-                               argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
-                               methodBinding.thrownExceptions, //exceptions
-                               binding); //declaringClass
-                               
-               methodDeclaration.scope = new MethodScope(scope, methodDeclaration, true);
-               methodDeclaration.bindArguments();
-
-/*             if (binding.methods == null) {
-                       binding.methods = new MethodBinding[] { methodDeclaration.binding };
-               } else {
-                       MethodBinding[] newMethods;
-                       System.arraycopy(
-                               binding.methods,
-                               0,
-                               newMethods = new MethodBinding[binding.methods.length + 1],
-                               1,
-                               binding.methods.length);
-                       newMethods[0] = methodDeclaration.binding;
-                       binding.methods = newMethods;
-               }*/
-               //===================================================
-
-               return methodDeclaration;
-       }
-       
-       /*
-        * Find the matching parse node, answers null if nothing found
-        */
-       public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
-
-               if (fieldBinding != null) {
-                       for (int i = 0, max = this.fields.length; i < max; i++) {
-                               FieldDeclaration fieldDecl;
-                               if ((fieldDecl = this.fields[i]).binding == fieldBinding)
-                                       return fieldDecl;
-                       }
-               }
-               return null;
-       }
-
-       /*
-        * Find the matching parse node, answers null if nothing found
-        */
-       public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) {
-
-               if (memberTypeBinding != null) {
-                       for (int i = 0, max = this.memberTypes.length; i < max; i++) {
-                               TypeDeclaration memberTypeDecl;
-                               if ((memberTypeDecl = this.memberTypes[i]).binding == memberTypeBinding)
-                                       return memberTypeDecl;
-                       }
-               }
-               return null;
-       }
-
-       /*
-        * Find the matching parse node, answers null if nothing found
-        */
-       public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
-
-               if (methodBinding != null) {
-                       for (int i = 0, max = this.methods.length; i < max; i++) {
-                               AbstractMethodDeclaration methodDecl;
-
-                               if ((methodDecl = this.methods[i]).binding == methodBinding)
-                                       return methodDecl;
-                       }
-               }
-               return null;
-       }
-
-       /*
-        * Finds the matching type amoung this type's member types.
-        * Returns null if no type with this name is found.
-        * The type name is a compound name relative to this type
-        * eg. if this type is X and we're looking for Y.X.A.B
-        *     then a type name would be {X, A, B}
-        */
-       public TypeDeclaration declarationOfType(char[][] typeName) {
-
-               int typeNameLength = typeName.length;
-               if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) {
-                       return null;
-               }
-               if (typeNameLength == 1) {
-                       return this;
-               }
-               char[][] subTypeName = new char[typeNameLength - 1][];
-               System.arraycopy(typeName, 1, subTypeName, 0, typeNameLength - 1);
-               for (int i = 0; i < this.memberTypes.length; i++) {
-                       TypeDeclaration typeDecl = this.memberTypes[i].declarationOfType(subTypeName);
-                       if (typeDecl != null) {
-                               return typeDecl;
-                       }
-               }
-               return null;
-       }
-
-       /**
-        * Generic bytecode generation for type
-        */
-//     public void generateCode(ClassFile enclosingClassFile) {
-//
-//             if (hasBeenGenerated)
-//                     return;
-//             hasBeenGenerated = true;
-//             if (ignoreFurtherInvestigation) {
-//                     if (binding == null)
-//                             return;
-//                     ClassFile.createProblemType(
-//                             this,
-//                             scope.referenceCompilationUnit().compilationResult);
-//                     return;
-//             }
-//             try {
-//                     // create the result for a compiled type
-//                     ClassFile classFile = new ClassFile(binding, enclosingClassFile, false);
-//                     // generate all fiels
-//                     classFile.addFieldInfos();
-//
-//                     // record the inner type inside its own .class file to be able
-//                     // to generate inner classes attributes
-//                     if (binding.isMemberType())
-//                             classFile.recordEnclosingTypeAttributes(binding);
-//                     if (binding.isLocalType()) {
-//                             enclosingClassFile.recordNestedLocalAttribute(binding);
-//                             classFile.recordNestedLocalAttribute(binding);
-//                     }
-//                     if (memberTypes != null) {
-//                             for (int i = 0, max = memberTypes.length; i < max; i++) {
-//                                     // record the inner type inside its own .class file to be able
-//                                     // to generate inner classes attributes
-//                                     classFile.recordNestedMemberAttribute(memberTypes[i].binding);
-//                                     memberTypes[i].generateCode(scope, classFile);
-//                             }
-//                     }
-//                     // generate all methods
-//                     classFile.setForMethodInfos();
-//                     if (methods != null) {
-//                             for (int i = 0, max = methods.length; i < max; i++) {
-//                                     methods[i].generateCode(scope, classFile);
-//                             }
-//                     }
-//                     
-//                     classFile.generateMissingAbstractMethods(this.missingAbstractMethods, scope.referenceCompilationUnit().compilationResult);
-//
-//                     // generate all methods
-//                     classFile.addSpecialMethods();
-//
-//                     if (ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
-//                             throw new AbortType(scope.referenceCompilationUnit().compilationResult);
-//                     }
-//
-//                     // finalize the compiled type result
-//                     classFile.addAttributes();
-//                     scope.referenceCompilationUnit().compilationResult.record(
-//                             binding.constantPoolName(),
-//                             classFile);
-//             } catch (AbortType e) {
-//                     if (binding == null)
-//                             return;
-//                     ClassFile.createProblemType(
-//                             this,
-//                             scope.referenceCompilationUnit().compilationResult);
-//             }
-//     }
-
-       /**
-        * Bytecode generation for a local inner type (API as a normal statement code gen)
-        */
-//     public void generateCode(BlockScope blockScope, CodeStream codeStream) {
-//
-//             if (hasBeenGenerated) return;
-//             int pc = codeStream.position;
-//             if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
-//             generateCode(codeStream.classFile);
-//             codeStream.recordPositionsFrom(pc, this.sourceStart);
-//     }
-
-       /**
-        * Bytecode generation for a member inner type
-        */
-//     public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) {
-//
-//             if (hasBeenGenerated) return;
-//             if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
-//             generateCode(enclosingClassFile);
-//     }
-
-       /**
-        * Bytecode generation for a package member
-        */
-//     public void generateCode(CompilationUnitScope unitScope) {
-//
-//             generateCode((ClassFile) null);
-//     }
-
-       public boolean hasErrors() {
-               return this.ignoreFurtherInvestigation;
-       }
-
-       /**
-        *      Common flow analysis for all types
-        *
-        */
-       public void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
-
-               if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
-                       if (!scope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
-                               scope.problemReporter().unusedPrivateType(this);
-                       }
-               }
-
-               ReferenceBinding[] defaultHandledExceptions = new ReferenceBinding[] { scope.getJavaLangThrowable()}; // tolerate any kind of exception
-               InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, initializerScope);
-               InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, staticInitializerScope);
-               FlowInfo nonStaticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
-               FlowInfo staticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
-               if (fields != null) {
-                       for (int i = 0, count = fields.length; i < count; i++) {
-                               FieldDeclaration field = fields[i];
-                               if (field.isStatic()) {
-                                       /*if (field.isField()){
-                                               staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
-                                       } else {*/
-                                       staticInitializerContext.handledExceptions = defaultHandledExceptions; // tolerate them all, and record them
-                                       /*}*/
-                                       staticFieldInfo =
-                                               field.analyseCode(
-                                                       staticInitializerScope,
-                                                       staticInitializerContext,
-                                                       staticFieldInfo);
-                                       // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
-                                       // branch, since the previous initializer already got the blame.
-                                       if (staticFieldInfo == FlowInfo.DEAD_END) {
-                                               staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
-                                               staticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
-                                       }
-                               } else {
-                                       /*if (field.isField()){
-                                               initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
-                                       } else {*/
-                                               initializerContext.handledExceptions = defaultHandledExceptions; // tolerate them all, and record them
-                                       /*}*/
-                                       nonStaticFieldInfo =
-                                               field.analyseCode(initializerScope, initializerContext, nonStaticFieldInfo);
-                                       // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
-                                       // branch, since the previous initializer already got the blame.
-                                       if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
-                                               initializerScope.problemReporter().initializerMustCompleteNormally(field);
-                                               nonStaticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
-                                       }
-                               }
-                       }
-               }
-               if (memberTypes != null) {
-                       for (int i = 0, count = memberTypes.length; i < count; i++) {
-                               if (flowContext != null){ // local type
-                                       memberTypes[i].analyseCode(scope, flowContext, nonStaticFieldInfo.copy());
-                               } else {
-                                       memberTypes[i].analyseCode(scope);
-                               }
-                       }
-               }
-               if (methods != null) {
-                       UnconditionalFlowInfo outerInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
-                       FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo);
-                       for (int i = 0, count = methods.length; i < count; i++) {
-                               AbstractMethodDeclaration method = methods[i];
-                               if (method.ignoreFurtherInvestigation)
-                                       continue;
-                               if (method.isInitializationMethod()) {
-                                       if (method.isStatic()) { // <clinit>
-                                               method.analyseCode(
-                                                       scope, 
-                                                       staticInitializerContext, 
-                                                       staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo));
-                                       } else { // constructor
-                                               method.analyseCode(scope, initializerContext, constructorInfo.copy());
-                                       }
-                               } else { // regular method
-                                       method.analyseCode(scope, null, flowInfo.copy());
-                               }
-                       }
-               }
-       }
-
-       public boolean isInterface() {
-
-               return (modifiers & AccInterface) != 0;
-       }
-
-       /* 
-        * Access emulation for a local type
-        * force to emulation of access to direct enclosing instance.
-        * By using the initializer scope, we actually only request an argument emulation, the
-        * field is not added until actually used. However we will force allocations to be qualified
-        * with an enclosing instance.
-        * 15.9.2
-        */
-       public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
-
-               NestedTypeBinding nestedType = (NestedTypeBinding) binding;
-               
-               MethodScope methodScope = currentScope.methodScope();
-               if (!methodScope.isStatic && !methodScope.isConstructorCall){
-
-                       nestedType.addSyntheticArgumentAndField(binding.enclosingType());       
-               }
-               // add superclass enclosing instance arg for anonymous types (if necessary)
-               if (binding.isAnonymousType()) { 
-                       ReferenceBinding superclass = binding.superclass;
-                       if (superclass.enclosingType() != null && !superclass.isStatic()) {
-                               if (!binding.superclass.isLocalType()
-                                               || ((NestedTypeBinding)binding.superclass).getSyntheticField(superclass.enclosingType(), true) != null){
-
-                                       nestedType.addSyntheticArgument(superclass.enclosingType());    
-                               }
-                       }
-               }
-       }
-       
-       /* 
-        * Access emulation for a local member type
-        * force to emulation of access to direct enclosing instance.
-        * By using the initializer scope, we actually only request an argument emulation, the
-        * field is not added until actually used. However we will force allocations to be qualified
-        * with an enclosing instance.
-        * 
-        * Local member cannot be static.
-        */
-       public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope) {
-
-               NestedTypeBinding nestedType = (NestedTypeBinding) binding;
-               nestedType.addSyntheticArgumentAndField(binding.enclosingType());
-       }       
-       
-       /**
-        * A <clinit> will be requested as soon as static fields or assertions are present. It will be eliminated during
-        * classfile creation if no bytecode was actually produced based on some optimizations/compiler settings.
-        */
-       public final boolean needClassInitMethod() {
-
-               // always need a <clinit> when assertions are present
-               if ((this.bits & AddAssertionMASK) != 0)
-                       return true;
-               if (fields == null)
-                       return false;
-               if (isInterface())
-                       return true; // fields are implicitly statics
-               for (int i = fields.length; --i >= 0;) {
-                       FieldDeclaration field = fields[i];
-                       //need to test the modifier directly while there is no binding yet
-                       if ((field.modifiers & AccStatic) != 0)
-                               return true;
-               }
-               return false;
-       }
-
-       public void parseMethod(UnitParser parser, CompilationUnitDeclaration unit) {
-
-               //connect method bodies
-               if (unit.ignoreMethodBodies)
-                       return;
-
-               // no scope were created, so cannot report further errors
-//             if (binding == null)
-//                     return;
-
-               //members
-               if (memberTypes != null) {
-                       int length = memberTypes.length;
-                       for (int i = 0; i < length; i++)
-                               memberTypes[i].parseMethod(parser, unit);
-               }
-
-               //methods
-               if (methods != null) {
-                       int length = methods.length;
-                       for (int i = 0; i < length; i++)
-                               methods[i].parseStatements(parser, unit);
-               }
-
-               //initializers
-               if (fields != null) {
-                       int length = fields.length;
-                       for (int i = 0; i < length; i++) {
-                               if (fields[i] instanceof Initializer) {
-                                       ((Initializer) fields[i]).parseStatements(parser, this, unit);
-                               }
-                       }
-               }
-       }
-
-       public void resolve() {
-
-               if (binding == null) {
-                       ignoreFurtherInvestigation = true;
-                       return;
-               }
-
-               try {
-                       // check superclass & interfaces
-                       if (binding.superclass != null) // watch out for Object ! (and other roots)     
-                               if (isTypeUseDeprecated(binding.superclass, scope))
-                                       scope.problemReporter().deprecatedType(binding.superclass, superclass);
-                       if (superInterfaces != null)
-                               for (int i = superInterfaces.length; --i >= 0;)
-                                       if (superInterfaces[i].resolvedType != null)
-                                               if (isTypeUseDeprecated(superInterfaces[i].resolvedType, scope))
-                                                       scope.problemReporter().deprecatedType(
-                                                               superInterfaces[i].resolvedType,
-                                                               superInterfaces[i]);
-                       maxFieldCount = 0;
-                       int lastFieldID = -1;
-                       if (fields != null) {
-                               for (int i = 0, count = fields.length; i < count; i++) {
-                                       FieldDeclaration field = fields[i];
-                                       if (field.isField()) {
-                                               if (field.binding == null) {
-                                                       // still discover secondary errors
-                                                       if (field.initialization != null) field.initialization.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
-                                                       ignoreFurtherInvestigation = true;
-                                                       continue;
-                                               }
-                                               maxFieldCount++;
-                                               lastFieldID = field.binding.id;
-                                       } else { // initializer
-                                                ((Initializer) field).lastFieldID = lastFieldID + 1;
-                                       }
-                                       field.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
-                               }
-                       }
-                       if (memberTypes != null) {
-                               for (int i = 0, count = memberTypes.length; i < count; i++) {
-                                       memberTypes[i].resolve(scope);
-                               }
-                       }
-                       int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
-                       int methodsLength = this.methods == null ? 0 : methods.length;
-                       if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) {
-                               scope.problemReporter().tooManyMethods(this);
-                       }
-                       
-                       if (methods != null) {
-                               for (int i = 0, count = methods.length; i < count; i++) {
-                                       methods[i].resolve(scope);
-                               }
-                       }
-               } catch (AbortType e) {
-                       this.ignoreFurtherInvestigation = true;
-                       return;
-               };
-       }
-
-       public void resolve(BlockScope blockScope) {
-               // local type declaration
-
-               // need to build its scope first and proceed with binding's creation
-               blockScope.addLocalType(this);
-
-               // and TC....
-               if (binding != null) {
-                       // remember local types binding for innerclass emulation propagation
-                       blockScope.referenceCompilationUnit().record((LocalTypeBinding)binding);
-
-                       // binding is not set if the receiver could not be created
-                       resolve();
-                       updateMaxFieldCount();
-               }
-       }
-
-       public void resolve(ClassScope upperScope) {
-               // member scopes are already created
-               // request the construction of a binding if local member type
-
-               if (binding != null && binding instanceof LocalTypeBinding) {
-                       // remember local types binding for innerclass emulation propagation
-                       upperScope.referenceCompilationUnit().record((LocalTypeBinding)binding);
-               }
-               resolve();
-               updateMaxFieldCount();
-       }
-
-       public void resolve(CompilationUnitScope upperScope) {
-               // top level : scope are already created
-
-               resolve();
-               updateMaxFieldCount();
-       }
-
-       public void tagAsHavingErrors() {
-               ignoreFurtherInvestigation = true;
-       }
-
-       public String toString(int tab) {
-
-               return tabString(tab) + toStringHeader() + toStringBody(tab);
-       }
-
-       public String toStringBody(int tab) {
-
-               String s = " {"; //$NON-NLS-1$
-               if (memberTypes != null) {
-                       for (int i = 0; i < memberTypes.length; i++) {
-                               if (memberTypes[i] != null) {
-                                       s += "\n" + memberTypes[i].toString(tab + 1); //$NON-NLS-1$
-                               }
-                       }
-               }
-               if (fields != null) {
-                       for (int fieldI = 0; fieldI < fields.length; fieldI++) {
-                               if (fields[fieldI] != null) {
-                                       s += "\n" + fields[fieldI].toString(tab + 1); //$NON-NLS-1$
-                                       if (fields[fieldI].isField())
-                                               s += ";"; //$NON-NLS-1$
-                               }
-                       }
-               }
-               if (methods != null) {
-                       for (int i = 0; i < methods.length; i++) {
-                               if (methods[i] != null) {
-                                       s += "\n" + methods[i].toString(tab + 1); //$NON-NLS-1$
-                               }
-                       }
-               }
-               s += "\n" + tabString(tab) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
-               return s;
-       }
-
-       public String toStringHeader() {
-
-               String s = ""; //$NON-NLS-1$
-               if (modifiers != AccDefault) {
-                       s += modifiersString(modifiers);
-               }
-               s += (isInterface() ? "interface " : "class ") + new String(name);//$NON-NLS-1$ //$NON-NLS-2$
-               if (superclass != null)
-                       s += " extends " + superclass.toString(0); //$NON-NLS-1$
-               if (superInterfaces != null && superInterfaces.length > 0) {
-                       s += (isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
-                       for (int i = 0; i < superInterfaces.length; i++) {
-                               s += superInterfaces[i].toString(0);
-                               if (i != superInterfaces.length - 1)
-                                       s += ", "; //$NON-NLS-1$
-                       };
-               };
-               return s;
-       }
-
-       /**
-        *      Iteration for a package member type
-        *
-        */
-       public void traverse(
-               IAbstractSyntaxTreeVisitor visitor,
-               CompilationUnitScope unitScope) {
-
-               if (ignoreFurtherInvestigation)
-                       return;
-               try {
-                       if (visitor.visit(this, unitScope)) {
-                               if (superclass != null)
-                                       superclass.traverse(visitor, scope);
-                               if (superInterfaces != null) {
-                                       int superInterfaceLength = superInterfaces.length;
-                                       for (int i = 0; i < superInterfaceLength; i++)
-                                               superInterfaces[i].traverse(visitor, scope);
-                               }
-                               if (memberTypes != null) {
-                                       int memberTypesLength = memberTypes.length;
-                                       for (int i = 0; i < memberTypesLength; i++)
-                                               memberTypes[i].traverse(visitor, scope);
-                               }
-                               if (fields != null) {
-                                       int fieldsLength = fields.length;
-                                       for (int i = 0; i < fieldsLength; i++) {
-                                               FieldDeclaration field;
-                                               if ((field = fields[i]).isStatic()) {
-                                                       field.traverse(visitor, staticInitializerScope);
-                                               } else {
-                                                       field.traverse(visitor, initializerScope);
-                                               }
-                                       }
-                               }
-                               if (methods != null) {
-                                       int methodsLength = methods.length;
-                                       for (int i = 0; i < methodsLength; i++)
-                                               methods[i].traverse(visitor, scope);
-                               }
-                       }
-                       visitor.endVisit(this, unitScope);
-               } catch (AbortType e) {
-               }
-       }
-
-       /**
-        * MaxFieldCount's computation is necessary so as to reserve space for
-        * the flow info field portions. It corresponds to the maximum amount of
-        * fields this class or one of its innertypes have.
-        *
-        * During name resolution, types are traversed, and the max field count is recorded
-        * on the outermost type. It is then propagated down during the flow analysis.
-        *
-        * This method is doing either up/down propagation.
-        */
-       void updateMaxFieldCount() {
-
-               if (binding == null)
-                       return; // error scenario
-               TypeDeclaration outerMostType = scope.outerMostClassScope().referenceType();
-               if (maxFieldCount > outerMostType.maxFieldCount) {
-                       outerMostType.maxFieldCount = maxFieldCount; // up
-               } else {
-                       maxFieldCount = outerMostType.maxFieldCount; // down
-               }
-       }
-}
+public class TypeDeclaration extends Statement implements ProblemSeverities, ReferenceContext {
+
+  public int modifiers;
+
+  public int modifiersSourceStart;
+
+  public char[] name;
+
+  public TypeReference superclass;
+
+  public TypeReference[] superInterfaces;
+
+  public FieldDeclaration[] fields;
+
+  public AbstractMethodDeclaration[] methods;
+
+  public TypeDeclaration[] memberTypes;
+
+  public SourceTypeBinding binding;
+
+  public ClassScope scope;
+
+  public MethodScope initializerScope;
+
+  public MethodScope staticInitializerScope;
+
+  public boolean ignoreFurtherInvestigation = false;
+
+  public int maxFieldCount;
+
+  public int declarationSourceStart;
+
+  public int declarationSourceEnd;
+
+  public int bodyStart;
+
+  public int bodyEnd; // doesn't include the trailing comment if any.
+
+  protected boolean hasBeenGenerated = false;
+
+  public CompilationResult compilationResult;
+
+  private MethodDeclaration[] missingAbstractMethods;
+
+  public TypeDeclaration(CompilationResult compilationResult) {
+    this.compilationResult = compilationResult;
+  }
+
+  /*
+   * We cause the compilation task to abort to a given extent.
+   */
+  public void abort(int abortLevel) {
+
+    if (scope == null) {
+      throw new AbortCompilation(); // cannot do better
+    }
+
+    CompilationResult compilationResult = scope.referenceCompilationUnit().compilationResult;
+
+    switch (abortLevel) {
+    case AbortCompilation:
+      throw new AbortCompilation(compilationResult);
+    case AbortCompilationUnit:
+      throw new AbortCompilationUnit(compilationResult);
+    case AbortMethod:
+      throw new AbortMethod(compilationResult);
+    default:
+      throw new AbortType(compilationResult);
+    }
+  }
+
+  /**
+   * This method is responsible for adding a <clinit>method declaration to the type method collections. Note that this
+   * implementation is inserting it in first place (as VAJ or javac), and that this impacts the behavior of the method
+   * ConstantPool.resetForClinit(int. int), in so far as the latter will have to reset the constant pool state accordingly (if it
+   * was added first, it does not need to preserve some of the method specific cached entries since this will be the first method).
+   * inserts the clinit method declaration in the first position.
+   * 
+   * @see net.sourceforge.phpdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int)
+   */
+  public final void addClinit() {
+
+    //see comment on needClassInitMethod
+    if (needClassInitMethod()) {
+      int length;
+      AbstractMethodDeclaration[] methods;
+      if ((methods = this.methods) == null) {
+        length = 0;
+        methods = new AbstractMethodDeclaration[1];
+      } else {
+        length = methods.length;
+        System.arraycopy(methods, 0, (methods = new AbstractMethodDeclaration[length + 1]), 1, length);
+      }
+      Clinit clinit = new Clinit(this.compilationResult);
+      methods[0] = clinit;
+      // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
+      clinit.declarationSourceStart = clinit.sourceStart = sourceStart;
+      clinit.declarationSourceEnd = clinit.sourceEnd = sourceEnd;
+      clinit.bodyEnd = sourceEnd;
+      this.methods = methods;
+    }
+  }
+
+  /**
+   * Flow analysis for a local innertype
+   *  
+   */
+  public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+    if (ignoreFurtherInvestigation)
+      return flowInfo;
+    try {
+      bits |= IsReachableMASK;
+      LocalTypeBinding localType = (LocalTypeBinding) binding;
+
+      localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
+      manageEnclosingInstanceAccessIfNecessary(currentScope);
+
+      updateMaxFieldCount(); // propagate down the max field count
+      internalAnalyseCode(flowContext, flowInfo);
+    } catch (AbortType e) {
+      this.ignoreFurtherInvestigation = true;
+    }
+    return flowInfo;
+  }
+
+  /**
+   * Flow analysis for a member innertype
+   *  
+   */
+  public void analyseCode(ClassScope enclosingClassScope) {
+
+    if (ignoreFurtherInvestigation)
+      return;
+    try {
+      // propagate down the max field count
+      updateMaxFieldCount();
+      internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
+    } catch (AbortType e) {
+      this.ignoreFurtherInvestigation = true;
+    }
+  }
+
+  /**
+   * Flow analysis for a local member innertype
+   *  
+   */
+  public void analyseCode(ClassScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+    if (ignoreFurtherInvestigation)
+      return;
+    try {
+      bits |= IsReachableMASK;
+      LocalTypeBinding localType = (LocalTypeBinding) binding;
+
+      localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
+      manageEnclosingInstanceAccessIfNecessary(currentScope);
+
+      updateMaxFieldCount(); // propagate down the max field count
+      internalAnalyseCode(flowContext, flowInfo);
+    } catch (AbortType e) {
+      this.ignoreFurtherInvestigation = true;
+    }
+  }
+
+  /**
+   * Flow analysis for a package member type
+   *  
+   */
+  public void analyseCode(CompilationUnitScope unitScope) {
+
+    if (ignoreFurtherInvestigation)
+      return;
+    try {
+      internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
+    } catch (AbortType e) {
+      this.ignoreFurtherInvestigation = true;
+    }
+  }
+
+  /*
+   * Check for constructor vs. method with no return type. Answers true if at least one constructor is defined
+   */
+  public boolean checkConstructors(Parser parser) {
+
+    //if a constructor has not the name of the type,
+    //convert it into a method with 'null' as its return type
+    boolean hasConstructor = false;
+    if (methods != null) {
+      for (int i = methods.length; --i >= 0;) {
+        AbstractMethodDeclaration am;
+        if ((am = methods[i]).isConstructor()) {
+          if (!CharOperation.equals(am.selector, name)) {
+            // the constructor was in fact a method with no return type
+            // unless an explicit constructor call was supplied
+            ConstructorDeclaration c = (ConstructorDeclaration) am;
+            if ((c.constructorCall == null) || (c.constructorCall.isImplicitSuper())) { //changed to a method
+              MethodDeclaration m = new MethodDeclaration(this.compilationResult);
+              m.sourceStart = c.sourceStart;
+              m.sourceEnd = c.sourceEnd;
+              m.bodyStart = c.bodyStart;
+              m.bodyEnd = c.bodyEnd;
+              m.declarationSourceEnd = c.declarationSourceEnd;
+              m.declarationSourceStart = c.declarationSourceStart;
+              m.selector = c.selector;
+              m.statements = c.statements;
+              m.modifiers = c.modifiers;
+              m.arguments = c.arguments;
+              m.thrownExceptions = c.thrownExceptions;
+              m.explicitDeclarations = c.explicitDeclarations;
+              m.returnType = null;
+              methods[i] = m;
+            }
+          } else {
+            if (this.isInterface()) {
+              // report the problem and continue the parsing
+              parser.problemReporter().interfaceCannotHaveConstructors((ConstructorDeclaration) am);
+            }
+            hasConstructor = true;
+          }
+        }
+      }
+    }
+    return hasConstructor;
+  }
+
+  public CompilationResult compilationResult() {
+
+    return this.compilationResult;
+  }
+
+  public ConstructorDeclaration createsInternalConstructor(boolean needExplicitConstructorCall, boolean needToInsert) {
+
+    //Add to method'set, the default constuctor that just recall the
+    //super constructor with no arguments
+    //The arguments' type will be positionned by the TC so just use
+    //the default int instead of just null (consistency purpose)
+
+    //the constructor
+    ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
+    constructor.isDefaultConstructor = true;
+    constructor.selector = name;
+    if (modifiers != AccDefault) {
+      constructor.modifiers = ((this instanceof MemberTypeDeclaration) && (modifiers & AccPrivate) != 0) ? AccDefault : modifiers
+          & AccVisibilityMASK;
+    }
+
+    //if you change this setting, please update the
+    //SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
+    constructor.declarationSourceStart = constructor.sourceStart = sourceStart;
+    constructor.declarationSourceEnd = constructor.sourceEnd = constructor.bodyEnd = sourceEnd;
+
+    //the super call inside the constructor
+    if (needExplicitConstructorCall) {
+      constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
+      constructor.constructorCall.sourceStart = sourceStart;
+      constructor.constructorCall.sourceEnd = sourceEnd;
+    }
+
+    //adding the constructor in the methods list
+    if (needToInsert) {
+      if (methods == null) {
+        methods = new AbstractMethodDeclaration[] { constructor };
+      } else {
+        AbstractMethodDeclaration[] newMethods;
+        System.arraycopy(methods, 0, newMethods = new AbstractMethodDeclaration[methods.length + 1], 1, methods.length);
+        newMethods[0] = constructor;
+        methods = newMethods;
+      }
+    }
+    return constructor;
+  }
+
+  /**
+   * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding. It is used to report errors for missing
+   * abstract methods.
+   */
+  public MethodDeclaration addMissingAbstractMethodFor(MethodBinding methodBinding) {
+    TypeBinding[] argumentTypes = methodBinding.parameters;
+    int argumentsLength = argumentTypes.length;
+    //the constructor
+    MethodDeclaration methodDeclaration = new MethodDeclaration(this.compilationResult);
+    methodDeclaration.selector = methodBinding.selector;
+    methodDeclaration.sourceStart = sourceStart;
+    methodDeclaration.sourceEnd = sourceEnd;
+    methodDeclaration.modifiers = methodBinding.getAccessFlags() & ~AccAbstract;
+
+    if (argumentsLength > 0) {
+      String baseName = "arg";//$NON-NLS-1$
+      Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]);
+      for (int i = argumentsLength; --i >= 0;) {
+        arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /* type ref */, AccDefault);
+      }
+    }
+
+    //adding the constructor in the methods list
+    if (this.missingAbstractMethods == null) {
+      this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
+    } else {
+      MethodDeclaration[] newMethods;
+      System.arraycopy(this.missingAbstractMethods, 0, newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1],
+          1, this.missingAbstractMethods.length);
+      newMethods[0] = methodDeclaration;
+      this.missingAbstractMethods = newMethods;
+    }
+
+    //============BINDING UPDATE==========================
+    methodDeclaration.binding = new MethodBinding(methodDeclaration.modifiers, //methodDeclaration
+        methodBinding.selector, methodBinding.returnType, argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
+        methodBinding.thrownExceptions, //exceptions
+        binding); //declaringClass
+
+    methodDeclaration.scope = new MethodScope(scope, methodDeclaration, true);
+    methodDeclaration.bindArguments();
+
+    /*
+     * if (binding.methods == null) { binding.methods = new MethodBinding[] { methodDeclaration.binding }; } else { MethodBinding[]
+     * newMethods; System.arraycopy( binding.methods, 0, newMethods = new MethodBinding[binding.methods.length + 1], 1,
+     * binding.methods.length); newMethods[0] = methodDeclaration.binding; binding.methods = newMethods; }
+     */
+    //===================================================
+    return methodDeclaration;
+  }
+
+  /*
+   * Find the matching parse node, answers null if nothing found
+   */
+  public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
+
+    if (fieldBinding != null) {
+      for (int i = 0, max = this.fields.length; i < max; i++) {
+        FieldDeclaration fieldDecl;
+        if ((fieldDecl = this.fields[i]).binding == fieldBinding)
+          return fieldDecl;
+      }
+    }
+    return null;
+  }
+
+  /*
+   * Find the matching parse node, answers null if nothing found
+   */
+  public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) {
+
+    if (memberTypeBinding != null) {
+      for (int i = 0, max = this.memberTypes.length; i < max; i++) {
+        TypeDeclaration memberTypeDecl;
+        if ((memberTypeDecl = this.memberTypes[i]).binding == memberTypeBinding)
+          return memberTypeDecl;
+      }
+    }
+    return null;
+  }
+
+  /*
+   * Find the matching parse node, answers null if nothing found
+   */
+  public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
+
+    if (methodBinding != null) {
+      for (int i = 0, max = this.methods.length; i < max; i++) {
+        AbstractMethodDeclaration methodDecl;
+
+        if ((methodDecl = this.methods[i]).binding == methodBinding)
+          return methodDecl;
+      }
+    }
+    return null;
+  }
+
+  /*
+   * Finds the matching type amoung this type's member types. Returns null if no type with this name is found. The type name is a
+   * compound name relative to this type eg. if this type is X and we're looking for Y.X.A.B then a type name would be {X, A, B}
+   */
+  public TypeDeclaration declarationOfType(char[][] typeName) {
+
+    int typeNameLength = typeName.length;
+    if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) {
+      return null;
+    }
+    if (typeNameLength == 1) {
+      return this;
+    }
+    char[][] subTypeName = new char[typeNameLength - 1][];
+    System.arraycopy(typeName, 1, subTypeName, 0, typeNameLength - 1);
+    for (int i = 0; i < this.memberTypes.length; i++) {
+      TypeDeclaration typeDecl = this.memberTypes[i].declarationOfType(subTypeName);
+      if (typeDecl != null) {
+        return typeDecl;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Generic bytecode generation for type
+   */
+  //   public void generateCode(ClassFile enclosingClassFile) {
+  //
+  //           if (hasBeenGenerated)
+  //                   return;
+  //           hasBeenGenerated = true;
+  //           if (ignoreFurtherInvestigation) {
+  //                   if (binding == null)
+  //                           return;
+  //                   ClassFile.createProblemType(
+  //                           this,
+  //                           scope.referenceCompilationUnit().compilationResult);
+  //                   return;
+  //           }
+  //           try {
+  //                   // create the result for a compiled type
+  //                   ClassFile classFile = new ClassFile(binding, enclosingClassFile, false);
+  //                   // generate all fiels
+  //                   classFile.addFieldInfos();
+  //
+  //                   // record the inner type inside its own .class file to be able
+  //                   // to generate inner classes attributes
+  //                   if (binding.isMemberType())
+  //                           classFile.recordEnclosingTypeAttributes(binding);
+  //                   if (binding.isLocalType()) {
+  //                           enclosingClassFile.recordNestedLocalAttribute(binding);
+  //                           classFile.recordNestedLocalAttribute(binding);
+  //                   }
+  //                   if (memberTypes != null) {
+  //                           for (int i = 0, max = memberTypes.length; i < max; i++) {
+  //                                   // record the inner type inside its own .class file to be able
+  //                                   // to generate inner classes attributes
+  //                                   classFile.recordNestedMemberAttribute(memberTypes[i].binding);
+  //                                   memberTypes[i].generateCode(scope, classFile);
+  //                           }
+  //                   }
+  //                   // generate all methods
+  //                   classFile.setForMethodInfos();
+  //                   if (methods != null) {
+  //                           for (int i = 0, max = methods.length; i < max; i++) {
+  //                                   methods[i].generateCode(scope, classFile);
+  //                           }
+  //                   }
+  //                   
+  //                   classFile.generateMissingAbstractMethods(this.missingAbstractMethods, scope.referenceCompilationUnit().compilationResult);
+  //
+  //                   // generate all methods
+  //                   classFile.addSpecialMethods();
+  //
+  //                   if (ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
+  //                           throw new AbortType(scope.referenceCompilationUnit().compilationResult);
+  //                   }
+  //
+  //                   // finalize the compiled type result
+  //                   classFile.addAttributes();
+  //                   scope.referenceCompilationUnit().compilationResult.record(
+  //                           binding.constantPoolName(),
+  //                           classFile);
+  //           } catch (AbortType e) {
+  //                   if (binding == null)
+  //                           return;
+  //                   ClassFile.createProblemType(
+  //                           this,
+  //                           scope.referenceCompilationUnit().compilationResult);
+  //           }
+  //   }
+  /**
+   * Bytecode generation for a local inner type (API as a normal statement code gen)
+   */
+  //   public void generateCode(BlockScope blockScope, CodeStream codeStream) {
+  //
+  //           if (hasBeenGenerated) return;
+  //           int pc = codeStream.position;
+  //           if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
+  //           generateCode(codeStream.classFile);
+  //           codeStream.recordPositionsFrom(pc, this.sourceStart);
+  //   }
+  /**
+   * Bytecode generation for a member inner type
+   */
+  //   public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) {
+  //
+  //           if (hasBeenGenerated) return;
+  //           if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
+  //           generateCode(enclosingClassFile);
+  //   }
+  /**
+   * Bytecode generation for a package member
+   */
+  //   public void generateCode(CompilationUnitScope unitScope) {
+  //
+  //           generateCode((ClassFile) null);
+  //   }
+  public boolean hasErrors() {
+    return this.ignoreFurtherInvestigation;
+  }
+
+  /**
+   * Common flow analysis for all types
+   *  
+   */
+  public void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
+
+    if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
+      if (!scope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
+        scope.problemReporter().unusedPrivateType(this);
+      }
+    }
+
+    ReferenceBinding[] defaultHandledExceptions = new ReferenceBinding[] { scope.getJavaLangThrowable() }; // tolerate any kind of
+    // exception
+    InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, initializerScope);
+    InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, staticInitializerScope);
+    FlowInfo nonStaticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
+    FlowInfo staticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
+    if (fields != null) {
+      for (int i = 0, count = fields.length; i < count; i++) {
+        FieldDeclaration field = fields[i];
+        if (field.isStatic()) {
+          /*
+           * if (field.isField()){ staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2 }
+           * else {
+           */
+          staticInitializerContext.handledExceptions = defaultHandledExceptions; // tolerate them all, and record them
+          /* } */
+          staticFieldInfo = field.analyseCode(staticInitializerScope, staticInitializerContext, staticFieldInfo);
+          // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
+          // branch, since the previous initializer already got the blame.
+          if (staticFieldInfo == FlowInfo.DEAD_END) {
+            staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
+            staticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
+          }
+        } else {
+          /*
+           * if (field.isField()){ initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2 } else {
+           */
+          initializerContext.handledExceptions = defaultHandledExceptions; // tolerate them all, and record them
+          /* } */
+          nonStaticFieldInfo = field.analyseCode(initializerScope, initializerContext, nonStaticFieldInfo);
+          // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
+          // branch, since the previous initializer already got the blame.
+          if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
+            initializerScope.problemReporter().initializerMustCompleteNormally(field);
+            nonStaticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
+          }
+        }
+      }
+    }
+    if (memberTypes != null) {
+      for (int i = 0, count = memberTypes.length; i < count; i++) {
+        if (flowContext != null) { // local type
+          memberTypes[i].analyseCode(scope, flowContext, nonStaticFieldInfo.copy());
+        } else {
+          memberTypes[i].analyseCode(scope);
+        }
+      }
+    }
+    if (methods != null) {
+      UnconditionalFlowInfo outerInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
+      FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(
+          outerInfo);
+      for (int i = 0, count = methods.length; i < count; i++) {
+        AbstractMethodDeclaration method = methods[i];
+        if (method.ignoreFurtherInvestigation)
+          continue;
+        if (method.isInitializationMethod()) {
+          if (method.isStatic()) { // <clinit>
+            method.analyseCode(scope, staticInitializerContext, staticFieldInfo.unconditionalInits()
+                .discardNonFieldInitializations().addInitializationsFrom(outerInfo));
+          } else { // constructor
+            method.analyseCode(scope, initializerContext, constructorInfo.copy());
+          }
+        } else { // regular method
+          method.analyseCode(scope, null, flowInfo.copy());
+        }
+      }
+    }
+  }
+
+  public boolean isInterface() {
+
+    return (modifiers & AccInterface) != 0;
+  }
+
+  /*
+   * Access emulation for a local type force to emulation of access to direct enclosing instance. By using the initializer scope, we
+   * actually only request an argument emulation, the field is not added until actually used. However we will force allocations to
+   * be qualified with an enclosing instance. 15.9.2
+   */
+  public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
+
+    NestedTypeBinding nestedType = (NestedTypeBinding) binding;
+
+    MethodScope methodScope = currentScope.methodScope();
+    if (!methodScope.isStatic && !methodScope.isConstructorCall) {
+
+      nestedType.addSyntheticArgumentAndField(binding.enclosingType());
+    }
+    // add superclass enclosing instance arg for anonymous types (if necessary)
+    if (binding.isAnonymousType()) {
+      ReferenceBinding superclass = binding.superclass;
+      if (superclass.enclosingType() != null && !superclass.isStatic()) {
+        if (!binding.superclass.isLocalType()
+            || ((NestedTypeBinding) binding.superclass).getSyntheticField(superclass.enclosingType(), true) != null) {
+
+          nestedType.addSyntheticArgument(superclass.enclosingType());
+        }
+      }
+    }
+  }
+
+  /*
+   * Access emulation for a local member type force to emulation of access to direct enclosing instance. By using the initializer
+   * scope, we actually only request an argument emulation, the field is not added until actually used. However we will force
+   * allocations to be qualified with an enclosing instance.
+   * 
+   * Local member cannot be static.
+   */
+  public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope) {
+
+    NestedTypeBinding nestedType = (NestedTypeBinding) binding;
+    nestedType.addSyntheticArgumentAndField(binding.enclosingType());
+  }
+
+  /**
+   * A <clinit>will be requested as soon as static fields or assertions are present. It will be eliminated during classfile creation
+   * if no bytecode was actually produced based on some optimizations/compiler settings.
+   */
+  public final boolean needClassInitMethod() {
+
+    // always need a <clinit> when assertions are present
+    if ((this.bits & AddAssertionMASK) != 0)
+      return true;
+    if (fields == null)
+      return false;
+    if (isInterface())
+      return true; // fields are implicitly statics
+    for (int i = fields.length; --i >= 0;) {
+      FieldDeclaration field = fields[i];
+      //need to test the modifier directly while there is no binding yet
+      if ((field.modifiers & AccStatic) != 0)
+        return true;
+    }
+    return false;
+  }
+
+  public void parseMethod(UnitParser parser, CompilationUnitDeclaration unit) {
+
+    //connect method bodies
+    if (unit.ignoreMethodBodies)
+      return;
+
+    // no scope were created, so cannot report further errors
+    //         if (binding == null)
+    //                 return;
+
+    //members
+    if (memberTypes != null) {
+      int length = memberTypes.length;
+      for (int i = 0; i < length; i++)
+        memberTypes[i].parseMethod(parser, unit);
+    }
+
+    //methods
+    if (methods != null) {
+      int length = methods.length;
+      for (int i = 0; i < length; i++)
+        methods[i].parseStatements(parser, unit);
+    }
+
+    //initializers
+    if (fields != null) {
+      int length = fields.length;
+      for (int i = 0; i < length; i++) {
+        if (fields[i] instanceof Initializer) {
+          ((Initializer) fields[i]).parseStatements(parser, this, unit);
+        }
+      }
+    }
+  }
+
+  public void resolve() {
+
+    if (binding == null) {
+      ignoreFurtherInvestigation = true;
+      return;
+    }
+
+    try {
+      // check superclass & interfaces
+      if (binding.superclass != null) // watch out for Object ! (and other roots)
+        if (isTypeUseDeprecated(binding.superclass, scope))
+          scope.problemReporter().deprecatedType(binding.superclass, superclass);
+      if (superInterfaces != null)
+        for (int i = superInterfaces.length; --i >= 0;)
+          if (superInterfaces[i].resolvedType != null)
+            if (isTypeUseDeprecated(superInterfaces[i].resolvedType, scope))
+              scope.problemReporter().deprecatedType(superInterfaces[i].resolvedType, superInterfaces[i]);
+      maxFieldCount = 0;
+      int lastFieldID = -1;
+      if (fields != null) {
+        for (int i = 0, count = fields.length; i < count; i++) {
+          FieldDeclaration field = fields[i];
+          if (field.isField()) {
+            if (field.binding == null) {
+              // still discover secondary errors
+              if (field.initialization != null)
+                field.initialization.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
+              ignoreFurtherInvestigation = true;
+              continue;
+            }
+            maxFieldCount++;
+            lastFieldID = field.binding.id;
+          } else { // initializer
+            ((Initializer) field).lastFieldID = lastFieldID + 1;
+          }
+          field.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
+        }
+      }
+      if (memberTypes != null) {
+        for (int i = 0, count = memberTypes.length; i < count; i++) {
+          memberTypes[i].resolve(scope);
+        }
+      }
+      int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
+      int methodsLength = this.methods == null ? 0 : methods.length;
+      if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) {
+        scope.problemReporter().tooManyMethods(this);
+      }
+
+      if (methods != null) {
+        for (int i = 0, count = methods.length; i < count; i++) {
+          methods[i].resolve(scope);
+        }
+      }
+    } catch (AbortType e) {
+      this.ignoreFurtherInvestigation = true;
+      return;
+    }
+    ;
+  }
+
+  public void resolve(BlockScope blockScope) {
+    // local type declaration
+
+    // need to build its scope first and proceed with binding's creation
+    blockScope.addLocalType(this);
+
+    // and TC....
+    if (binding != null) {
+      // remember local types binding for innerclass emulation propagation
+      blockScope.referenceCompilationUnit().record((LocalTypeBinding) binding);
+
+      // binding is not set if the receiver could not be created
+      resolve();
+      updateMaxFieldCount();
+    }
+  }
+
+  public void resolve(ClassScope upperScope) {
+    // member scopes are already created
+    // request the construction of a binding if local member type
+
+    if (binding != null && binding instanceof LocalTypeBinding) {
+      // remember local types binding for innerclass emulation propagation
+      upperScope.referenceCompilationUnit().record((LocalTypeBinding) binding);
+    }
+    resolve();
+    updateMaxFieldCount();
+  }
+
+  public void resolve(CompilationUnitScope upperScope) {
+    // top level : scope are already created
+
+    resolve();
+    updateMaxFieldCount();
+  }
+
+  public void tagAsHavingErrors() {
+    ignoreFurtherInvestigation = true;
+  }
+
+  public StringBuffer print(int indent, StringBuffer output) {
+
+    //    if ((this.bits & IsAnonymousTypeMASK) == 0) {
+    printIndent(indent, output);
+    printHeader(0, output);
+    //    }
+    return printBody(indent, output);
+  }
+
+  public StringBuffer printBody(int indent, StringBuffer output) {
+
+    output.append(" {"); //$NON-NLS-1$
+    if (memberTypes != null) {
+      for (int i = 0; i < memberTypes.length; i++) {
+        if (memberTypes[i] != null) {
+          output.append('\n');
+          memberTypes[i].print(indent + 1, output);
+        }
+      }
+    }
+    if (fields != null) {
+      for (int fieldI = 0; fieldI < fields.length; fieldI++) {
+        if (fields[fieldI] != null) {
+          output.append('\n');
+          fields[fieldI].print(indent + 1, output);
+        }
+      }
+    }
+    if (methods != null) {
+      for (int i = 0; i < methods.length; i++) {
+        if (methods[i] != null) {
+          output.append('\n');
+          methods[i].print(indent + 1, output);
+        }
+      }
+    }
+    output.append('\n');
+    return printIndent(indent, output).append('}');
+  }
+
+  public StringBuffer printHeader(int indent, StringBuffer output) {
+
+    printModifiers(this.modifiers, output);
+    output.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
+    output.append(name);
+    if (superclass != null) {
+      output.append(" extends "); //$NON-NLS-1$
+      superclass.print(0, output);
+    }
+    if (superInterfaces != null && superInterfaces.length > 0) {
+      output.append(isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
+      for (int i = 0; i < superInterfaces.length; i++) {
+        if (i > 0)
+          output.append(", "); //$NON-NLS-1$
+        superInterfaces[i].print(0, output);
+      }
+    }
+    return output;
+  }
+
+  public StringBuffer printStatement(int tab, StringBuffer output) {
+    return print(tab, output);
+  }
+
+  public String toString(int tab) {
+
+    return tabString(tab) + toStringHeader() + toStringBody(tab);
+  }
+
+  public String toStringBody(int tab) {
+
+    String s = " {"; //$NON-NLS-1$
+    if (memberTypes != null) {
+      for (int i = 0; i < memberTypes.length; i++) {
+        if (memberTypes[i] != null) {
+          s += "\n" + memberTypes[i].toString(tab + 1); //$NON-NLS-1$
+        }
+      }
+    }
+    if (fields != null) {
+      for (int fieldI = 0; fieldI < fields.length; fieldI++) {
+        if (fields[fieldI] != null) {
+          s += "\n" + fields[fieldI].toString(tab + 1); //$NON-NLS-1$
+          if (fields[fieldI].isField())
+            s += ";"; //$NON-NLS-1$
+        }
+      }
+    }
+    if (methods != null) {
+      for (int i = 0; i < methods.length; i++) {
+        if (methods[i] != null) {
+          s += "\n" + methods[i].toString(tab + 1); //$NON-NLS-1$
+        }
+      }
+    }
+    s += "\n" + tabString(tab) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
+    return s;
+  }
+
+  public String toStringHeader() {
+
+    String s = ""; //$NON-NLS-1$
+    if (modifiers != AccDefault) {
+      s += modifiersString(modifiers);
+    }
+    s += (isInterface() ? "interface " : "class ") + new String(name);//$NON-NLS-1$ //$NON-NLS-2$
+    if (superclass != null)
+      s += " extends " + superclass.toString(0); //$NON-NLS-1$
+    if (superInterfaces != null && superInterfaces.length > 0) {
+      s += (isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
+      for (int i = 0; i < superInterfaces.length; i++) {
+        s += superInterfaces[i].toString(0);
+        if (i != superInterfaces.length - 1)
+          s += ", "; //$NON-NLS-1$
+      }
+      ;
+    }
+    ;
+    return s;
+  }
+
+  /**
+   * Iteration for a local innertype
+   *  
+   */
+  public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+    if (ignoreFurtherInvestigation)
+      return;
+    try {
+      if (visitor.visit(this, blockScope)) {
+        if (superclass != null)
+          superclass.traverse(visitor, scope);
+        if (superInterfaces != null) {
+          int superInterfaceLength = superInterfaces.length;
+          for (int i = 0; i < superInterfaceLength; i++)
+            superInterfaces[i].traverse(visitor, scope);
+        }
+        if (memberTypes != null) {
+          int memberTypesLength = memberTypes.length;
+          for (int i = 0; i < memberTypesLength; i++)
+            memberTypes[i].traverse(visitor, scope);
+        }
+        if (fields != null) {
+          int fieldsLength = fields.length;
+          for (int i = 0; i < fieldsLength; i++) {
+            FieldDeclaration field;
+            if ((field = fields[i]).isStatic()) {
+              // local type cannot have static fields
+            } else {
+              field.traverse(visitor, initializerScope);
+            }
+          }
+        }
+        if (methods != null) {
+          int methodsLength = methods.length;
+          for (int i = 0; i < methodsLength; i++)
+            methods[i].traverse(visitor, scope);
+        }
+      }
+      visitor.endVisit(this, blockScope);
+    } catch (AbortType e) {
+      // silent abort
+    }
+  }
+
+  /**
+   * Iteration for a member innertype
+   *  
+   */
+  public void traverse(ASTVisitor visitor, ClassScope classScope) {
+    if (ignoreFurtherInvestigation)
+      return;
+    try {
+      if (visitor.visit(this, classScope)) {
+        if (superclass != null)
+          superclass.traverse(visitor, scope);
+        if (superInterfaces != null) {
+          int superInterfaceLength = superInterfaces.length;
+          for (int i = 0; i < superInterfaceLength; i++)
+            superInterfaces[i].traverse(visitor, scope);
+        }
+        if (memberTypes != null) {
+          int memberTypesLength = memberTypes.length;
+          for (int i = 0; i < memberTypesLength; i++)
+            memberTypes[i].traverse(visitor, scope);
+        }
+        if (fields != null) {
+          int fieldsLength = fields.length;
+          for (int i = 0; i < fieldsLength; i++) {
+            FieldDeclaration field;
+            if ((field = fields[i]).isStatic()) {
+              field.traverse(visitor, staticInitializerScope);
+            } else {
+              field.traverse(visitor, initializerScope);
+            }
+          }
+        }
+        if (methods != null) {
+          int methodsLength = methods.length;
+          for (int i = 0; i < methodsLength; i++)
+            methods[i].traverse(visitor, scope);
+        }
+      }
+      visitor.endVisit(this, classScope);
+    } catch (AbortType e) {
+      // silent abort
+    }
+  }
+
+  /**
+   * Iteration for a package member type
+   *  
+   */
+  public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) {
+
+    if (ignoreFurtherInvestigation)
+      return;
+    try {
+      if (visitor.visit(this, unitScope)) {
+        if (superclass != null)
+          superclass.traverse(visitor, scope);
+        if (superInterfaces != null) {
+          int superInterfaceLength = superInterfaces.length;
+          for (int i = 0; i < superInterfaceLength; i++)
+            superInterfaces[i].traverse(visitor, scope);
+        }
+        if (memberTypes != null) {
+          int memberTypesLength = memberTypes.length;
+          for (int i = 0; i < memberTypesLength; i++)
+            memberTypes[i].traverse(visitor, scope);
+        }
+        if (fields != null) {
+          int fieldsLength = fields.length;
+          for (int i = 0; i < fieldsLength; i++) {
+            FieldDeclaration field;
+            if ((field = fields[i]).isStatic()) {
+              field.traverse(visitor, staticInitializerScope);
+            } else {
+              field.traverse(visitor, initializerScope);
+            }
+          }
+        }
+        if (methods != null) {
+          int methodsLength = methods.length;
+          for (int i = 0; i < methodsLength; i++)
+            methods[i].traverse(visitor, scope);
+        }
+      }
+      visitor.endVisit(this, unitScope);
+    } catch (AbortType e) {
+    }
+  }
+
+  /**
+   * MaxFieldCount's computation is necessary so as to reserve space for the flow info field portions. It corresponds to the maximum
+   * amount of fields this class or one of its innertypes have.
+   * 
+   * During name resolution, types are traversed, and the max field count is recorded on the outermost type. It is then propagated
+   * down during the flow analysis.
+   * 
+   * This method is doing either up/down propagation.
+   */
+  void updateMaxFieldCount() {
+
+    if (binding == null)
+      return; // error scenario
+    TypeDeclaration outerMostType = scope.outerMostClassScope().referenceType();
+    if (maxFieldCount > outerMostType.maxFieldCount) {
+      outerMostType.maxFieldCount = maxFieldCount; // up
+    } else {
+      maxFieldCount = outerMostType.maxFieldCount; // down
+    }
+  }
+}
\ No newline at end of file