added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / ast / TypeDeclaration.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.ast;
12
13 import org.eclipse.jdt.core.compiler.*;
14 import org.eclipse.jdt.internal.compiler.ASTVisitor;
15 import org.eclipse.jdt.internal.compiler.*;
16 import org.eclipse.jdt.internal.compiler.impl.*;
17 import org.eclipse.jdt.internal.compiler.codegen.*;
18 import org.eclipse.jdt.internal.compiler.env.IGenericType;
19 import org.eclipse.jdt.internal.compiler.flow.*;
20 import org.eclipse.jdt.internal.compiler.lookup.*;
21 import org.eclipse.jdt.internal.compiler.parser.*;
22 import org.eclipse.jdt.internal.compiler.problem.*;
23
24 public class TypeDeclaration
25         extends Statement
26         implements ProblemSeverities, ReferenceContext {
27
28         public static final char[] ANONYMOUS_EMPTY_NAME = new char[] {};
29
30         public int modifiers = AccDefault;
31         public int modifiersSourceStart;
32         public Annotation[] annotations;
33         public char[] name;
34         public TypeReference superclass;
35         public TypeReference[] superInterfaces;
36         public FieldDeclaration[] fields;
37         public AbstractMethodDeclaration[] methods;
38         public TypeDeclaration[] memberTypes;
39         public SourceTypeBinding binding;
40         public ClassScope scope;
41         public MethodScope initializerScope;
42         public MethodScope staticInitializerScope;
43         public boolean ignoreFurtherInvestigation = false;
44         public int maxFieldCount;
45         public int declarationSourceStart;
46         public int declarationSourceEnd;
47         public int bodyStart;
48         public int bodyEnd; // doesn't include the trailing comment if any.
49         protected boolean hasBeenGenerated = false;
50         public CompilationResult compilationResult;
51         public MethodDeclaration[] missingAbstractMethods;
52         public Javadoc javadoc; 
53
54         public QualifiedAllocationExpression allocation; // for anonymous only
55         public TypeDeclaration enclosingType; // for member types only
56         
57         public FieldBinding enumValuesSyntheticfield;   // for enum
58
59         // 1.5 support
60         public TypeParameter[] typeParameters;
61         
62         public TypeDeclaration(CompilationResult compilationResult){
63                 this.compilationResult = compilationResult;
64         }
65                 
66         /*
67          *      We cause the compilation task to abort to a given extent.
68          */
69         public void abort(int abortLevel, IProblem problem) {
70
71                 switch (abortLevel) {
72                         case AbortCompilation :
73                                 throw new AbortCompilation(this.compilationResult, problem);
74                         case AbortCompilationUnit :
75                                 throw new AbortCompilationUnit(this.compilationResult, problem);
76                         case AbortMethod :
77                                 throw new AbortMethod(this.compilationResult, problem);
78                         default :
79                                 throw new AbortType(this.compilationResult, problem);
80                 }
81         }
82         /**
83          * This method is responsible for adding a <clinit> method declaration to the type method collections.
84          * Note that this implementation is inserting it in first place (as VAJ or javac), and that this
85          * impacts the behavior of the method ConstantPool.resetForClinit(int. int), in so far as 
86          * the latter will have to reset the constant pool state accordingly (if it was added first, it does 
87          * not need to preserve some of the method specific cached entries since this will be the first method).
88          * inserts the clinit method declaration in the first position.
89          * 
90          * @see org.eclipse.jdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int)
91          */
92         public final void addClinit() {
93
94                 //see comment on needClassInitMethod
95                 if (needClassInitMethod()) {
96                         int length;
97                         AbstractMethodDeclaration[] methodDeclarations;
98                         if ((methodDeclarations = this.methods) == null) {
99                                 length = 0;
100                                 methodDeclarations = new AbstractMethodDeclaration[1];
101                         } else {
102                                 length = methodDeclarations.length;
103                                 System.arraycopy(
104                                         methodDeclarations,
105                                         0,
106                                         (methodDeclarations = new AbstractMethodDeclaration[length + 1]),
107                                         1,
108                                         length);
109                         }
110                         Clinit clinit = new Clinit(this.compilationResult);
111                         methodDeclarations[0] = clinit;
112                         // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
113                         clinit.declarationSourceStart = clinit.sourceStart = sourceStart;
114                         clinit.declarationSourceEnd = clinit.sourceEnd = sourceEnd;
115                         clinit.bodyEnd = sourceEnd;
116                         this.methods = methodDeclarations;
117                 }
118         }
119
120         /*
121          * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding.
122          * It is used to report errors for missing abstract methods.
123          */
124         public MethodDeclaration addMissingAbstractMethodFor(MethodBinding methodBinding) {
125                 TypeBinding[] argumentTypes = methodBinding.parameters;
126                 int argumentsLength = argumentTypes.length;
127                 //the constructor
128                 MethodDeclaration methodDeclaration = new MethodDeclaration(this.compilationResult);
129                 methodDeclaration.selector = methodBinding.selector;
130                 methodDeclaration.sourceStart = sourceStart;
131                 methodDeclaration.sourceEnd = sourceEnd;
132                 methodDeclaration.modifiers = methodBinding.getAccessFlags() & ~AccAbstract;
133
134                 if (argumentsLength > 0) {
135                         String baseName = "arg";//$NON-NLS-1$
136                         Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]);
137                         for (int i = argumentsLength; --i >= 0;) {
138                                 arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, AccDefault);
139                         }
140                 }
141
142                 //adding the constructor in the methods list
143                 if (this.missingAbstractMethods == null) {
144                         this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
145                 } else {
146                         MethodDeclaration[] newMethods;
147                         System.arraycopy(
148                                 this.missingAbstractMethods,
149                                 0,
150                                 newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1],
151                                 1,
152                                 this.missingAbstractMethods.length);
153                         newMethods[0] = methodDeclaration;
154                         this.missingAbstractMethods = newMethods;
155                 }
156
157                 //============BINDING UPDATE==========================
158                 methodDeclaration.binding = new MethodBinding(
159                                 methodDeclaration.modifiers, //methodDeclaration
160                                 methodBinding.selector,
161                                 methodBinding.returnType,
162                                 argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
163                                 methodBinding.thrownExceptions, //exceptions
164                                 binding); //declaringClass
165                                 
166                 methodDeclaration.scope = new MethodScope(scope, methodDeclaration, true);
167                 methodDeclaration.bindArguments();
168
169 /*              if (binding.methods == null) {
170                         binding.methods = new MethodBinding[] { methodDeclaration.binding };
171                 } else {
172                         MethodBinding[] newMethods;
173                         System.arraycopy(
174                                 binding.methods,
175                                 0,
176                                 newMethods = new MethodBinding[binding.methods.length + 1],
177                                 1,
178                                 binding.methods.length);
179                         newMethods[0] = methodDeclaration.binding;
180                         binding.methods = newMethods;
181                 }*/
182                 //===================================================
183
184                 return methodDeclaration;
185         }
186
187         /**
188          *      Flow analysis for a local innertype
189          *
190          */
191         public FlowInfo analyseCode(
192                 BlockScope currentScope,
193                 FlowContext flowContext,
194                 FlowInfo flowInfo) {
195
196                 if (ignoreFurtherInvestigation)
197                         return flowInfo;
198                 try {
199                         if (flowInfo.isReachable()) {
200                                 bits |= IsReachableMASK;
201                                 LocalTypeBinding localType = (LocalTypeBinding) binding;
202                                 localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
203                         }
204                         manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
205                         updateMaxFieldCount(); // propagate down the max field count
206                         internalAnalyseCode(flowContext, flowInfo); 
207                 } catch (AbortType e) {
208                         this.ignoreFurtherInvestigation = true;
209                 }
210                 return flowInfo;
211         }
212
213         /**
214          *      Flow analysis for a member innertype
215          *
216          */
217         public void analyseCode(ClassScope enclosingClassScope) {
218
219                 if (ignoreFurtherInvestigation)
220                         return;
221                 try {
222                         // propagate down the max field count
223                         updateMaxFieldCount();
224                         internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
225                 } catch (AbortType e) {
226                         this.ignoreFurtherInvestigation = true;
227                 }
228         }
229
230         /**
231          *      Flow analysis for a local member innertype
232          *
233          */
234         public void analyseCode(
235                 ClassScope currentScope,
236                 FlowContext flowContext,
237                 FlowInfo flowInfo) {
238
239                 if (ignoreFurtherInvestigation)
240                         return;
241                 try {
242                         if (flowInfo.isReachable()) {
243                                 bits |= IsReachableMASK;
244                                 LocalTypeBinding localType = (LocalTypeBinding) binding;
245                                 localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
246                         }
247                         manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
248                         updateMaxFieldCount(); // propagate down the max field count
249                         internalAnalyseCode(flowContext, flowInfo);
250                 } catch (AbortType e) {
251                         this.ignoreFurtherInvestigation = true;
252                 }
253         }
254
255         /**
256          *      Flow analysis for a package member type
257          *
258          */
259         public void analyseCode(CompilationUnitScope unitScope) {
260
261                 if (ignoreFurtherInvestigation)
262                         return;
263                 try {
264                         internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
265                 } catch (AbortType e) {
266                         this.ignoreFurtherInvestigation = true;
267                 }
268         }
269
270         /*
271          * Check for constructor vs. method with no return type.
272          * Answers true if at least one constructor is defined
273          */
274         public boolean checkConstructors(Parser parser) {
275
276                 //if a constructor has not the name of the type,
277                 //convert it into a method with 'null' as its return type
278                 boolean hasConstructor = false;
279                 if (methods != null) {
280                         for (int i = methods.length; --i >= 0;) {
281                                 AbstractMethodDeclaration am;
282                                 if ((am = methods[i]).isConstructor()) {
283                                         if (!CharOperation.equals(am.selector, name)) {
284                                                 // the constructor was in fact a method with no return type
285                                                 // unless an explicit constructor call was supplied
286                                                 ConstructorDeclaration c = (ConstructorDeclaration) am;
287                                                 if (c.constructorCall == null || c.constructorCall.isImplicitSuper()) { //changed to a method
288                                                         MethodDeclaration m = parser.convertToMethodDeclaration(c, this.compilationResult);
289                                                         methods[i] = m;
290                                                 }
291                                         } else {
292                                                 if (this.kind() == IGenericType.INTERFACE_DECL) {
293                                                         // report the problem and continue the parsing
294                                                         parser.problemReporter().interfaceCannotHaveConstructors(
295                                                                 (ConstructorDeclaration) am);
296                                                 }
297                                                 hasConstructor = true;
298                                         }
299                                 }
300                         }
301                 }
302                 return hasConstructor;
303         }
304
305         public CompilationResult compilationResult() {
306
307                 return this.compilationResult;
308         }
309
310         public ConstructorDeclaration createDefaultConstructor(
311                 boolean needExplicitConstructorCall,
312                 boolean needToInsert) {
313
314                 //Add to method'set, the default constuctor that just recall the
315                 //super constructor with no arguments
316                 //The arguments' type will be positionned by the TC so just use
317                 //the default int instead of just null (consistency purpose)
318
319                 //the constructor
320                 ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
321                 constructor.isDefaultConstructor = true;
322                 constructor.selector = this.name;
323                 if (modifiers != AccDefault) {
324                         constructor.modifiers =
325                                 (((this.bits & ASTNode.IsMemberTypeMASK) != 0) && (modifiers & AccPrivate) != 0)
326                                         ? AccDefault
327                                         : modifiers & AccVisibilityMASK;
328                 }
329
330                 //if you change this setting, please update the 
331                 //SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
332                 constructor.declarationSourceStart = constructor.sourceStart = sourceStart;
333                 constructor.declarationSourceEnd =
334                         constructor.sourceEnd = constructor.bodyEnd = sourceEnd;
335
336                 //the super call inside the constructor
337                 if (needExplicitConstructorCall) {
338                         constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
339                         constructor.constructorCall.sourceStart = sourceStart;
340                         constructor.constructorCall.sourceEnd = sourceEnd;
341                 }
342
343                 //adding the constructor in the methods list
344                 if (needToInsert) {
345                         if (methods == null) {
346                                 methods = new AbstractMethodDeclaration[] { constructor };
347                         } else {
348                                 AbstractMethodDeclaration[] newMethods;
349                                 System.arraycopy(
350                                         methods,
351                                         0,
352                                         newMethods = new AbstractMethodDeclaration[methods.length + 1],
353                                         1,
354                                         methods.length);
355                                 newMethods[0] = constructor;
356                                 methods = newMethods;
357                         }
358                 }
359                 return constructor;
360         }
361         
362         // anonymous type constructor creation
363         public MethodBinding createDefaultConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
364
365                 //Add to method'set, the default constuctor that just recall the
366                 //super constructor with the same arguments
367                 String baseName = "$anonymous"; //$NON-NLS-1$
368                 TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
369                 int argumentsLength = argumentTypes.length;
370                 //the constructor
371                 ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationResult);
372                 cd.selector = new char[] { 'x' }; //no maining
373                 cd.sourceStart = sourceStart;
374                 cd.sourceEnd = sourceEnd;
375                 cd.modifiers = modifiers & AccVisibilityMASK;
376                 cd.isDefaultConstructor = true;
377
378                 if (argumentsLength > 0) {
379                         Argument[] arguments = (cd.arguments = new Argument[argumentsLength]);
380                         for (int i = argumentsLength; --i >= 0;) {
381                                 arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, AccDefault);
382                         }
383                 }
384
385                 //the super call inside the constructor
386                 cd.constructorCall = SuperReference.implicitSuperConstructorCall();
387                 cd.constructorCall.sourceStart = sourceStart;
388                 cd.constructorCall.sourceEnd = sourceEnd;
389
390                 if (argumentsLength > 0) {
391                         Expression[] args;
392                         args = cd.constructorCall.arguments = new Expression[argumentsLength];
393                         for (int i = argumentsLength; --i >= 0;) {
394                                 args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
395                         }
396                 }
397
398                 //adding the constructor in the methods list
399                 if (methods == null) {
400                         methods = new AbstractMethodDeclaration[] { cd };
401                 } else {
402                         AbstractMethodDeclaration[] newMethods;
403                         System.arraycopy(
404                                 methods,
405                                 0,
406                                 newMethods = new AbstractMethodDeclaration[methods.length + 1],
407                                 1,
408                                 methods.length);
409                         newMethods[0] = cd;
410                         methods = newMethods;
411                 }
412
413                 //============BINDING UPDATE==========================
414                 cd.binding = new MethodBinding(
415                                 cd.modifiers, //methodDeclaration
416                                 argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
417                                 inheritedConstructorBinding.thrownExceptions, //exceptions
418                                 binding); //declaringClass
419                                 
420                 cd.scope = new MethodScope(scope, cd, true);
421                 cd.bindArguments();
422                 cd.constructorCall.resolve(cd.scope);
423
424                 if (binding.methods == null) {
425                         binding.methods = new MethodBinding[] { cd.binding };
426                 } else {
427                         MethodBinding[] newMethods;
428                         System.arraycopy(
429                                 binding.methods,
430                                 0,
431                                 newMethods = new MethodBinding[binding.methods.length + 1],
432                                 1,
433                                 binding.methods.length);
434                         newMethods[0] = cd.binding;
435                         binding.methods = newMethods;
436                 }
437                 //===================================================
438
439                 return cd.binding;
440         }
441
442         /*
443          * Find the matching parse node, answers null if nothing found
444          */
445         public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
446
447                 if (fieldBinding != null) {
448                         for (int i = 0, max = this.fields.length; i < max; i++) {
449                                 FieldDeclaration fieldDecl;
450                                 if ((fieldDecl = this.fields[i]).binding == fieldBinding)
451                                         return fieldDecl;
452                         }
453                 }
454                 return null;
455         }
456
457         /*
458          * Find the matching parse node, answers null if nothing found
459          */
460         public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) {
461
462                 if (memberTypeBinding != null) {
463                         for (int i = 0, max = this.memberTypes.length; i < max; i++) {
464                                 TypeDeclaration memberTypeDecl;
465                                 if ((memberTypeDecl = this.memberTypes[i]).binding == memberTypeBinding)
466                                         return memberTypeDecl;
467                         }
468                 }
469                 return null;
470         }
471
472         /*
473          * Find the matching parse node, answers null if nothing found
474          */
475         public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
476
477                 if (methodBinding != null) {
478                         for (int i = 0, max = this.methods.length; i < max; i++) {
479                                 AbstractMethodDeclaration methodDecl;
480
481                                 if ((methodDecl = this.methods[i]).binding == methodBinding)
482                                         return methodDecl;
483                         }
484                 }
485                 return null;
486         }
487
488         /*
489          * Finds the matching type amoung this type's member types.
490          * Returns null if no type with this name is found.
491          * The type name is a compound name relative to this type
492          * eg. if this type is X and we're looking for Y.X.A.B
493          *     then a type name would be {X, A, B}
494          */
495         public TypeDeclaration declarationOfType(char[][] typeName) {
496
497                 int typeNameLength = typeName.length;
498                 if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) {
499                         return null;
500                 }
501                 if (typeNameLength == 1) {
502                         return this;
503                 }
504                 char[][] subTypeName = new char[typeNameLength - 1][];
505                 System.arraycopy(typeName, 1, subTypeName, 0, typeNameLength - 1);
506                 for (int i = 0; i < this.memberTypes.length; i++) {
507                         TypeDeclaration typeDecl = this.memberTypes[i].declarationOfType(subTypeName);
508                         if (typeDecl != null) {
509                                 return typeDecl;
510                         }
511                 }
512                 return null;
513         }
514
515         /**
516          * Generic bytecode generation for type
517          */
518         public void generateCode(ClassFile enclosingClassFile) {
519
520                 if (hasBeenGenerated)
521                         return;
522                 hasBeenGenerated = true;
523                 if (ignoreFurtherInvestigation) {
524                         if (binding == null)
525                                 return;
526                         ClassFile.createProblemType(
527                                 this,
528                                 scope.referenceCompilationUnit().compilationResult);
529                         return;
530                 }
531                 try {
532                         // create the result for a compiled type
533                         ClassFile classFile = new ClassFile(binding, enclosingClassFile, false);
534                         // generate all fiels
535                         classFile.addFieldInfos();
536
537                         // record the inner type inside its own .class file to be able
538                         // to generate inner classes attributes
539                         if (binding.isMemberType())
540                                 classFile.recordEnclosingTypeAttributes(binding);
541                         if (binding.isLocalType()) {
542                                 enclosingClassFile.recordNestedLocalAttribute(binding);
543                                 classFile.recordNestedLocalAttribute(binding);
544                         }
545                         if (memberTypes != null) {
546                                 for (int i = 0, max = memberTypes.length; i < max; i++) {
547                                         // record the inner type inside its own .class file to be able
548                                         // to generate inner classes attributes
549                                         classFile.recordNestedMemberAttribute(memberTypes[i].binding);
550                                         memberTypes[i].generateCode(scope, classFile);
551                                 }
552                         }
553                         // generate all methods
554                         classFile.setForMethodInfos();
555                         if (methods != null) {
556                                 for (int i = 0, max = methods.length; i < max; i++) {
557                                         methods[i].generateCode(scope, classFile);
558                                 }
559                         }
560                         // generate all synthetic and abstract methods
561                         classFile.addSpecialMethods();
562
563                         if (ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
564                                 throw new AbortType(scope.referenceCompilationUnit().compilationResult, null);
565                         }
566
567                         // finalize the compiled type result
568                         classFile.addAttributes();
569                         scope.referenceCompilationUnit().compilationResult.record(
570                                 binding.constantPoolName(),
571                                 classFile);
572                 } catch (AbortType e) {
573                         if (binding == null)
574                                 return;
575                         ClassFile.createProblemType(
576                                 this,
577                                 scope.referenceCompilationUnit().compilationResult);
578                 }
579         }
580
581         /**
582          * Bytecode generation for a local inner type (API as a normal statement code gen)
583          */
584         public void generateCode(BlockScope blockScope, CodeStream codeStream) {
585
586                 if ((this.bits & IsReachableMASK) == 0) {
587                         return;
588                 }               
589                 if (hasBeenGenerated) return;
590                 int pc = codeStream.position;
591                 if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
592                 generateCode(codeStream.classFile);
593                 codeStream.recordPositionsFrom(pc, this.sourceStart);
594         }
595
596         /**
597          * Bytecode generation for a member inner type
598          */
599         public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) {
600
601                 if (hasBeenGenerated) return;
602                 if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
603                 generateCode(enclosingClassFile);
604         }
605
606         /**
607          * Bytecode generation for a package member
608          */
609         public void generateCode(CompilationUnitScope unitScope) {
610
611                 generateCode((ClassFile) null);
612         }
613
614         public boolean hasErrors() {
615                 return this.ignoreFurtherInvestigation;
616         }
617
618         /**
619          *      Common flow analysis for all types
620          *
621          */
622         public void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
623
624                 if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
625                         if (!scope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
626                                 scope.problemReporter().unusedPrivateType(this);
627                         }
628                 }
629
630                 InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, initializerScope);
631                 InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, staticInitializerScope);
632                 FlowInfo nonStaticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
633                 FlowInfo staticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
634                 if (fields != null) {
635                         for (int i = 0, count = fields.length; i < count; i++) {
636                                 FieldDeclaration field = fields[i];
637                                 if (field.isStatic()) {
638                                         /*if (field.isField()){
639                                                 staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
640                                         } else {*/
641                                         staticInitializerContext.handledExceptions = AnyException; // tolerate them all, and record them
642                                         /*}*/
643                                         staticFieldInfo =
644                                                 field.analyseCode(
645                                                         staticInitializerScope,
646                                                         staticInitializerContext,
647                                                         staticFieldInfo);
648                                         // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
649                                         // branch, since the previous initializer already got the blame.
650                                         if (staticFieldInfo == FlowInfo.DEAD_END) {
651                                                 staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
652                                                 staticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
653                                         }
654                                 } else {
655                                         /*if (field.isField()){
656                                                 initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
657                                         } else {*/
658                                                 initializerContext.handledExceptions = AnyException; // tolerate them all, and record them
659                                         /*}*/
660                                         nonStaticFieldInfo =
661                                                 field.analyseCode(initializerScope, initializerContext, nonStaticFieldInfo);
662                                         // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
663                                         // branch, since the previous initializer already got the blame.
664                                         if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
665                                                 initializerScope.problemReporter().initializerMustCompleteNormally(field);
666                                                 nonStaticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
667                                         } 
668                                 }
669                         }
670                 }
671                 if (memberTypes != null) {
672                         for (int i = 0, count = memberTypes.length; i < count; i++) {
673                                 if (flowContext != null){ // local type
674                                         memberTypes[i].analyseCode(scope, flowContext, nonStaticFieldInfo.copy().setReachMode(flowInfo.reachMode())); // reset reach mode in case initializers did abrupt completely
675                                 } else {
676                                         memberTypes[i].analyseCode(scope);
677                                 }
678                         }
679                 }
680                 if (methods != null) {
681                         UnconditionalFlowInfo outerInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
682                         FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo);
683                         for (int i = 0, count = methods.length; i < count; i++) {
684                                 AbstractMethodDeclaration method = methods[i];
685                                 if (method.ignoreFurtherInvestigation)
686                                         continue;
687                                 if (method.isInitializationMethod()) {
688                                         if (method.isStatic()) { // <clinit>
689                                                 method.analyseCode(
690                                                         scope, 
691                                                         staticInitializerContext,  
692                                                         staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo).setReachMode(flowInfo.reachMode()));  // reset reach mode in case initializers did abrupt completely
693                                         } else { // constructor
694                                                 method.analyseCode(scope, initializerContext, constructorInfo.copy().setReachMode(flowInfo.reachMode())); // reset reach mode in case initializers did abrupt completely
695                                         }
696                                 } else { // regular method
697                                         method.analyseCode(scope, null, flowInfo.copy());
698                                 }
699                         }
700                 }
701                 // enable enum support ?
702                 if (this.binding.isEnum()) {
703                         this.enumValuesSyntheticfield = this.binding.addSyntheticFieldForEnumValues();
704                 }
705         }
706
707         public int kind() {
708                 if ((modifiers & AccInterface) != 0) {
709                         if ((modifiers & AccAnnotation) != 0) 
710                                 return IGenericType.ANNOTATION_TYPE_DECL;
711                         return IGenericType.INTERFACE_DECL;
712                 } else if ((modifiers & AccEnum) != 0) 
713                         return IGenericType.ENUM_DECL;
714                 return IGenericType.CLASS_DECL;
715         }
716         
717         /* 
718          * Access emulation for a local type
719          * force to emulation of access to direct enclosing instance.
720          * By using the initializer scope, we actually only request an argument emulation, the
721          * field is not added until actually used. However we will force allocations to be qualified
722          * with an enclosing instance.
723          * 15.9.2
724          */
725         public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
726
727                 if (!flowInfo.isReachable()) return;
728                 NestedTypeBinding nestedType = (NestedTypeBinding) binding;
729                 
730                 MethodScope methodScope = currentScope.methodScope();
731                 if (!methodScope.isStatic && !methodScope.isConstructorCall){
732
733                         nestedType.addSyntheticArgumentAndField(binding.enclosingType());       
734                 }
735                 // add superclass enclosing instance arg for anonymous types (if necessary)
736                 if (binding.isAnonymousType()) { 
737                         ReferenceBinding superclassBinding = (ReferenceBinding)binding.superclass.erasure();
738                         if (superclassBinding.enclosingType() != null && !superclassBinding.isStatic()) {
739                                 if (!superclassBinding.isLocalType()
740                                                 || ((NestedTypeBinding)superclassBinding).getSyntheticField(superclassBinding.enclosingType(), true) != null){
741
742                                         nestedType.addSyntheticArgument(superclassBinding.enclosingType());     
743                                 }
744                         }
745                 }
746         }
747         
748         /* 
749          * Access emulation for a local member type
750          * force to emulation of access to direct enclosing instance.
751          * By using the initializer scope, we actually only request an argument emulation, the
752          * field is not added until actually used. However we will force allocations to be qualified
753          * with an enclosing instance.
754          * 
755          * Local member cannot be static.
756          */
757         public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope, FlowInfo flowInfo) {
758
759                 if (!flowInfo.isReachable()) return;
760                 NestedTypeBinding nestedType = (NestedTypeBinding) binding;
761                 nestedType.addSyntheticArgumentAndField(binding.enclosingType());
762         }       
763         
764         /**
765          * A <clinit> will be requested as soon as static fields or assertions are present. It will be eliminated during
766          * classfile creation if no bytecode was actually produced based on some optimizations/compiler settings.
767          */
768         public final boolean needClassInitMethod() {
769
770                 // always need a <clinit> when assertions are present
771                 if ((this.bits & AddAssertionMASK) != 0)
772                         return true;
773                 if (fields == null)
774                         return false;
775                 
776                 if (kind() == IGenericType.INTERFACE_DECL)
777                         return true; // fields are implicitly statics
778                 for (int i = fields.length; --i >= 0;) {
779                         FieldDeclaration field = fields[i];
780                         //need to test the modifier directly while there is no binding yet
781                         if ((field.modifiers & AccStatic) != 0)
782                                 return true; // TODO (philippe) shouldn't it check whether field is initializer or has some initial value ?
783                         if (field.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT)
784                                 return true;
785                 }
786                 return false;
787         }
788
789         public void parseMethod(Parser parser, CompilationUnitDeclaration unit) {
790
791                 //connect method bodies
792                 if (unit.ignoreMethodBodies)
793                         return;
794
795                 //members
796                 if (memberTypes != null) {
797                         int length = memberTypes.length;
798                         for (int i = 0; i < length; i++)
799                                 memberTypes[i].parseMethod(parser, unit);
800                 }
801
802                 //methods
803                 if (methods != null) {
804                         int length = methods.length;
805                         for (int i = 0; i < length; i++) {
806                                 methods[i].parseStatements(parser, unit);
807                         }
808                 }
809
810                 //initializers
811                 if (fields != null) {
812                         int length = fields.length;
813                         for (int i = 0; i < length; i++) {
814                                 final FieldDeclaration fieldDeclaration = fields[i];
815                                 switch(fieldDeclaration.getKind()) {
816                                         case AbstractVariableDeclaration.INITIALIZER:
817                                                 ((Initializer) fieldDeclaration).parseStatements(parser, this, unit);
818                                                 break;
819                                 }
820                         }
821                 }
822         }
823
824         public StringBuffer print(int indent, StringBuffer output) {
825
826                 if ((this.bits & IsAnonymousTypeMASK) == 0) {
827                         printIndent(indent, output);
828                         printHeader(0, output);
829                 }
830                 return printBody(indent, output);
831         }
832
833         public StringBuffer printBody(int indent, StringBuffer output) {
834
835                 output.append(" {"); //$NON-NLS-1$
836                 if (memberTypes != null) {
837                         for (int i = 0; i < memberTypes.length; i++) {
838                                 if (memberTypes[i] != null) {
839                                         output.append('\n');
840                                         memberTypes[i].print(indent + 1, output);
841                                 }
842                         }
843                 }
844                 if (fields != null) {
845                         for (int fieldI = 0; fieldI < fields.length; fieldI++) {
846                                 if (fields[fieldI] != null) { // TODO (olivier) should improve to deal with enumconstants using ',' separator
847                                         output.append('\n');
848                                         fields[fieldI].print(indent + 1, output);
849                                 }
850                         }
851                 }
852                 if (methods != null) {
853                         for (int i = 0; i < methods.length; i++) {
854                                 if (methods[i] != null) {
855                                         output.append('\n');
856                                         methods[i].print(indent + 1, output); 
857                                 }
858                         }
859                 }
860                 output.append('\n');
861                 return printIndent(indent, output).append('}');
862         }
863
864         public StringBuffer printHeader(int indent, StringBuffer output) {
865
866                 printModifiers(this.modifiers, output);
867                 if (this.annotations != null) printAnnotations(this.annotations, output);
868                 
869                 switch (kind()) {
870                         case IGenericType.CLASS_DECL :
871                                 output.append("class "); //$NON-NLS-1$
872                                 break;
873                         case IGenericType.INTERFACE_DECL :
874                                 output.append("interface "); //$NON-NLS-1$
875                                 break;
876                         case IGenericType.ENUM_DECL :
877                                 output.append("enum "); //$NON-NLS-1$
878                                 break;
879                         case IGenericType.ANNOTATION_TYPE_DECL :
880                                 output.append("@interface "); //$NON-NLS-1$
881                                 break;
882                 }                       
883                 output.append(name);
884                 if (typeParameters != null) {
885                         output.append("<");//$NON-NLS-1$
886                         for (int i = 0; i < typeParameters.length; i++) {
887                                 if (i > 0) output.append( ", "); //$NON-NLS-1$
888                                 typeParameters[i].print(0, output);
889                         }
890                         output.append(">");//$NON-NLS-1$
891                 }
892                 if (superclass != null) {
893                         output.append(" extends ");  //$NON-NLS-1$
894                         superclass.print(0, output);
895                 }
896                 if (superInterfaces != null && superInterfaces.length > 0) {
897                         switch (kind()) {
898                                 case IGenericType.CLASS_DECL :
899                                 case IGenericType.ENUM_DECL :
900                                         output.append(" implements "); //$NON-NLS-1$
901                                         break;
902                                 case IGenericType.INTERFACE_DECL :
903                                 case IGenericType.ANNOTATION_TYPE_DECL :
904                                         output.append(" extends "); //$NON-NLS-1$
905                                         break;
906                         }                       
907                         for (int i = 0; i < superInterfaces.length; i++) {
908                                 if (i > 0) output.append( ", "); //$NON-NLS-1$
909                                 superInterfaces[i].print(0, output);
910                         }
911                 }
912                 return output;
913         }
914
915         public StringBuffer printStatement(int tab, StringBuffer output) {
916                 return print(tab, output);
917         }
918         
919
920
921         public void resolve() {
922                 SourceTypeBinding sourceType = this.binding;
923                 if (sourceType == null) {
924                         this.ignoreFurtherInvestigation = true;
925                         return;
926                 }
927                 try {
928                         resolveAnnotations(this.staticInitializerScope, this.annotations, sourceType);
929                         
930                         if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
931                                 this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd);
932                         }
933                         boolean needSerialVersion = 
934                                                         this.scope.environment().options.getSeverity(CompilerOptions.MissingSerialVersion) != ProblemSeverities.Ignore
935                                                         && sourceType.isClass() 
936                                                         && !sourceType.isAbstract() 
937                                                         && sourceType.findSuperTypeErasingTo(T_JavaIoSerializable, false /*Serializable is not a class*/) != null;
938                         
939                         if (this.typeParameters != null && scope.getJavaLangThrowable().isSuperclassOf(sourceType)) {
940                                 this.scope.problemReporter().genericTypeCannotExtendThrowable(this);
941                         }
942                         this.maxFieldCount = 0;
943                         int lastVisibleFieldID = -1;
944                         boolean hasEnumConstants = false;
945                         boolean hasEnumConstantsWithoutBody = false;
946                         if (this.memberTypes != null) {
947                                 for (int i = 0, count = this.memberTypes.length; i < count; i++) {
948                                         this.memberTypes[i].resolve(this.scope);
949                                 }
950                         }
951                         if (this.fields != null) {
952                                 for (int i = 0, count = this.fields.length; i < count; i++) {
953                                         FieldDeclaration field = this.fields[i];
954                                         switch(field.getKind()) {
955                                                 case AbstractVariableDeclaration.ENUM_CONSTANT:
956                                                         hasEnumConstants = true;
957                                                         if (!(field.initialization instanceof QualifiedAllocationExpression))
958                                                                 hasEnumConstantsWithoutBody = true;
959                                                 case AbstractVariableDeclaration.FIELD:
960                                                         FieldBinding fieldBinding = field.binding;
961                                                         if (fieldBinding == null) {
962                                                                 // still discover secondary errors
963                                                                 if (field.initialization != null) field.initialization.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
964                                                                 this.ignoreFurtherInvestigation = true;
965                                                                 continue;
966                                                         }
967                                                         if (needSerialVersion
968                                                                         && ((fieldBinding.modifiers & (AccStatic | AccFinal)) == (AccStatic | AccFinal))
969                                                                         && CharOperation.equals(TypeConstants.SERIALVERSIONUID, fieldBinding.name)
970                                                                         && BaseTypes.LongBinding == fieldBinding.type) {
971                                                                 needSerialVersion = false;
972                                                         }
973                                                         this.maxFieldCount++;
974                                                         lastVisibleFieldID = field.binding.id;
975                                                         break;
976         
977                                                 case AbstractVariableDeclaration.INITIALIZER:
978                                                          ((Initializer) field).lastVisibleFieldID = lastVisibleFieldID + 1;
979                                                         break;
980                                         }
981                                         field.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
982                                 }
983                         }
984                         if (needSerialVersion) {
985                                 this.scope.problemReporter().missingSerialVersion(this);
986                         }
987                         // check extends/implements for annotation type
988                         if (kind() == IGenericType.ANNOTATION_TYPE_DECL) {
989                                 if (this.superclass != null) {
990                                         this.scope.problemReporter().annotationTypeDeclarationCannotHaveSuperclass(this);
991                                 }
992                                 if (this.superInterfaces != null) {
993                                         this.scope.problemReporter().annotationTypeDeclarationCannotHaveSuperinterfaces(this);
994                                 }
995                         }
996                         // check enum abstract methods
997                         if (kind() == IGenericType.ENUM_DECL && this.binding.isAbstract()) {
998                                 if (!hasEnumConstants || hasEnumConstantsWithoutBody) {
999                                         for (int i = 0, count = this.methods.length; i < count; i++) {
1000                                                 if (this.methods[i].isAbstract()) {
1001                                                         this.scope.problemReporter().enumAbstractMethodMustBeImplemented(this.methods[i]);
1002                                                 }
1003                                         }
1004                                 }
1005                         }
1006                         int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
1007                         int methodsLength = this.methods == null ? 0 : this.methods.length;
1008                         if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) {
1009                                 this.scope.problemReporter().tooManyMethods(this);
1010                         }
1011                         
1012                         if (this.methods != null) {
1013                                 for (int i = 0, count = this.methods.length; i < count; i++) {
1014                                         this.methods[i].resolve(this.scope);
1015                                 }
1016                         }
1017                         // Resolve javadoc
1018                         if (this.javadoc != null) {
1019                                 if (this.scope != null) {
1020                                         this.javadoc.resolve(this.scope);
1021                                 }
1022                         } else if (sourceType != null && !sourceType.isLocalType()) {
1023                                 this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, sourceType.modifiers);
1024                         }
1025                         
1026                 } catch (AbortType e) {
1027                         this.ignoreFurtherInvestigation = true;
1028                         return;
1029                 }
1030         }
1031
1032         public void resolve(BlockScope blockScope) {
1033                 // local type declaration
1034
1035                 // need to build its scope first and proceed with binding's creation
1036                 if ((this.bits & IsAnonymousTypeMASK) == 0) blockScope.addLocalType(this);
1037
1038                 if (binding != null) {
1039                         // remember local types binding for innerclass emulation propagation
1040                         blockScope.referenceCompilationUnit().record((LocalTypeBinding)binding);
1041
1042                         // binding is not set if the receiver could not be created
1043                         resolve();
1044                         updateMaxFieldCount();
1045                 }
1046         }
1047         
1048         public void resolve(ClassScope upperScope) {
1049                 // member scopes are already created
1050                 // request the construction of a binding if local member type
1051
1052                 if (binding != null && binding instanceof LocalTypeBinding) {
1053                         // remember local types binding for innerclass emulation propagation
1054                         upperScope.referenceCompilationUnit().record((LocalTypeBinding)binding);
1055                 }
1056                 resolve();
1057                 updateMaxFieldCount();
1058         }
1059
1060         public void resolve(CompilationUnitScope upperScope) {
1061                 // top level : scope are already created
1062
1063                 resolve();
1064                 updateMaxFieldCount();
1065         }
1066
1067         public void tagAsHavingErrors() {
1068                 ignoreFurtherInvestigation = true;
1069         }
1070
1071
1072         /**
1073          *      Iteration for a package member type
1074          *
1075          */
1076         public void traverse(
1077                 ASTVisitor visitor,
1078                 CompilationUnitScope unitScope) {
1079
1080                 if (ignoreFurtherInvestigation)
1081                         return;
1082                 try {
1083                         if (visitor.visit(this, unitScope)) {
1084                                 if (this.annotations != null) {
1085                                         int annotationsLength = this.annotations.length;
1086                                         for (int i = 0; i < annotationsLength; i++)
1087                                                 this.annotations[i].traverse(visitor, scope);
1088                                 }
1089                                 if (this.superclass != null)
1090                                         this.superclass.traverse(visitor, scope);
1091                                 if (this.superInterfaces != null) {
1092                                         int length = this.superInterfaces.length;
1093                                         for (int i = 0; i < length; i++)
1094                                                 this.superInterfaces[i].traverse(visitor, scope);
1095                                 }
1096                                 if (this.typeParameters != null) {
1097                                         int length = this.typeParameters.length;
1098                                         for (int i = 0; i < length; i++) {
1099                                                 this.typeParameters[i].traverse(visitor, scope);
1100                                         }
1101                                 }                               
1102                                 if (this.memberTypes != null) {
1103                                         int length = this.memberTypes.length;
1104                                         for (int i = 0; i < length; i++)
1105                                                 this.memberTypes[i].traverse(visitor, scope);
1106                                 }
1107                                 if (this.fields != null) {
1108                                         int length = this.fields.length;
1109                                         for (int i = 0; i < length; i++) {
1110                                                 FieldDeclaration field;
1111                                                 if ((field = this.fields[i]).isStatic()) {
1112                                                         field.traverse(visitor, staticInitializerScope);
1113                                                 } else {
1114                                                         field.traverse(visitor, initializerScope);
1115                                                 }
1116                                         }
1117                                 }
1118                                 if (this.methods != null) {
1119                                         int length = this.methods.length;
1120                                         for (int i = 0; i < length; i++)
1121                                                 this.methods[i].traverse(visitor, scope);
1122                                 }
1123                         }
1124                         visitor.endVisit(this, unitScope);
1125                 } catch (AbortType e) {
1126                         // silent abort
1127                 }
1128         }
1129
1130         /**
1131          *      Iteration for a local innertype
1132          *
1133          */
1134         public void traverse(ASTVisitor visitor, BlockScope blockScope) {
1135                 if (ignoreFurtherInvestigation)
1136                         return;
1137                 try {
1138                         if (visitor.visit(this, blockScope)) {
1139                                 if (this.annotations != null) {
1140                                         int annotationsLength = this.annotations.length;
1141                                         for (int i = 0; i < annotationsLength; i++)
1142                                                 this.annotations[i].traverse(visitor, scope);
1143                                 }
1144                                 if (this.superclass != null)
1145                                         this.superclass.traverse(visitor, scope);
1146                                 if (this.superInterfaces != null) {
1147                                         int length = this.superInterfaces.length;
1148                                         for (int i = 0; i < length; i++)
1149                                                 this.superInterfaces[i].traverse(visitor, scope);
1150                                 }
1151                                 if (this.typeParameters != null) {
1152                                         int length = this.typeParameters.length;
1153                                         for (int i = 0; i < length; i++) {
1154                                                 this.typeParameters[i].traverse(visitor, scope);
1155                                         }
1156                                 }                               
1157                                 if (this.memberTypes != null) {
1158                                         int length = this.memberTypes.length;
1159                                         for (int i = 0; i < length; i++)
1160                                                 this.memberTypes[i].traverse(visitor, scope);
1161                                 }
1162                                 if (this.fields != null) {
1163                                         int length = this.fields.length;
1164                                         for (int i = 0; i < length; i++) {
1165                                                 FieldDeclaration field;
1166                                                 if ((field = this.fields[i]).isStatic()) {
1167                                                         // local type cannot have static fields
1168                                                 } else {
1169                                                         field.traverse(visitor, initializerScope);
1170                                                 }
1171                                         }
1172                                 }
1173                                 if (this.methods != null) {
1174                                         int length = this.methods.length;
1175                                         for (int i = 0; i < length; i++)
1176                                                 this.methods[i].traverse(visitor, scope);
1177                                 }
1178                         }
1179                         visitor.endVisit(this, blockScope);
1180                 } catch (AbortType e) {
1181                         // silent abort
1182                 }
1183         }
1184
1185         /**
1186          *      Iteration for a member innertype
1187          *
1188          */
1189         public void traverse(ASTVisitor visitor, ClassScope classScope) {
1190                 if (ignoreFurtherInvestigation)
1191                         return;
1192                 try {
1193                         if (visitor.visit(this, classScope)) {
1194                                 if (this.annotations != null) {
1195                                         int annotationsLength = this.annotations.length;
1196                                         for (int i = 0; i < annotationsLength; i++)
1197                                                 this.annotations[i].traverse(visitor, scope);
1198                                 }
1199                                 if (this.superclass != null)
1200                                         this.superclass.traverse(visitor, scope);
1201                                 if (this.superInterfaces != null) {
1202                                         int length = this.superInterfaces.length;
1203                                         for (int i = 0; i < length; i++)
1204                                                 this.superInterfaces[i].traverse(visitor, scope);
1205                                 }
1206                                 if (this.typeParameters != null) {
1207                                         int length = this.typeParameters.length;
1208                                         for (int i = 0; i < length; i++) {
1209                                                 this.typeParameters[i].traverse(visitor, scope);
1210                                         }
1211                                 }                               
1212                                 if (this.memberTypes != null) {
1213                                         int length = this.memberTypes.length;
1214                                         for (int i = 0; i < length; i++)
1215                                                 this.memberTypes[i].traverse(visitor, scope);
1216                                 }
1217                                 if (this.fields != null) {
1218                                         int length = this.fields.length;
1219                                         for (int i = 0; i < length; i++) {
1220                                                 FieldDeclaration field;
1221                                                 if ((field = this.fields[i]).isStatic()) {
1222                                                         field.traverse(visitor, staticInitializerScope);
1223                                                 } else {
1224                                                         field.traverse(visitor, initializerScope);
1225                                                 }
1226                                         }
1227                                 }
1228                                 if (this.methods != null) {
1229                                         int length = this.methods.length;
1230                                         for (int i = 0; i < length; i++)
1231                                                 this.methods[i].traverse(visitor, scope);
1232                                 }
1233                         }
1234                         visitor.endVisit(this, classScope);
1235                 } catch (AbortType e) {
1236                         // silent abort
1237                 }
1238         }       
1239
1240         /**
1241          * MaxFieldCount's computation is necessary so as to reserve space for
1242          * the flow info field portions. It corresponds to the maximum amount of
1243          * fields this class or one of its innertypes have.
1244          *
1245          * During name resolution, types are traversed, and the max field count is recorded
1246          * on the outermost type. It is then propagated down during the flow analysis.
1247          *
1248          * This method is doing either up/down propagation.
1249          */
1250         void updateMaxFieldCount() {
1251
1252                 if (binding == null)
1253                         return; // error scenario
1254                 TypeDeclaration outerMostType = scope.outerMostClassScope().referenceType();
1255                 if (maxFieldCount > outerMostType.maxFieldCount) {
1256                         outerMostType.maxFieldCount = maxFieldCount; // up
1257                 } else {
1258                         maxFieldCount = outerMostType.maxFieldCount; // down
1259                 }
1260         }       
1261 }