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