KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > TypeDeclaration


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-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.*;
15 import org.eclipse.jdt.internal.compiler.impl.*;
16 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
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 extends Statement implements ProblemSeverities, ReferenceContext {
24     // Type decl kinds
25
public static final int CLASS_DECL = 1;
26     public static final int INTERFACE_DECL = 2;
27     public static final int ENUM_DECL = 3;
28     public static final int ANNOTATION_TYPE_DECL = 4;
29     
30     public int modifiers = ClassFileConstants.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
public CompilationResult compilationResult;
50     public MethodDeclaration[] missingAbstractMethods;
51     public Javadoc javadoc;
52     
53     public QualifiedAllocationExpression allocation; // for anonymous only
54
public TypeDeclaration enclosingType; // for member types only
55

56     public FieldBinding enumValuesSyntheticfield; // for enum
57

58     // 1.5 support
59
public TypeParameter[] typeParameters;
60     
61 public TypeDeclaration(CompilationResult compilationResult){
62     this.compilationResult = compilationResult;
63 }
64     
65 /*
66  * We cause the compilation task to abort to a given extent.
67  */

68 public void abort(int abortLevel, CategorizedProblem problem) {
69     switch (abortLevel) {
70         case AbortCompilation :
71             throw new AbortCompilation(this.compilationResult, problem);
72         case AbortCompilationUnit :
73             throw new AbortCompilationUnit(this.compilationResult, problem);
74         case AbortMethod :
75             throw new AbortMethod(this.compilationResult, problem);
76         default :
77             throw new AbortType(this.compilationResult, problem);
78     }
79 }
80
81 /**
82  * This method is responsible for adding a <clinit> method declaration to the type method collections.
83  * Note that this implementation is inserting it in first place (as VAJ or javac), and that this
84  * impacts the behavior of the method ConstantPool.resetForClinit(int. int), in so far as
85  * the latter will have to reset the constant pool state accordingly (if it was added first, it does
86  * not need to preserve some of the method specific cached entries since this will be the first method).
87  * inserts the clinit method declaration in the first position.
88  *
89  * @see org.eclipse.jdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int)
90  */

91 public final void addClinit() {
92     //see comment on needClassInitMethod
93
if (needClassInitMethod()) {
94         int length;
95         AbstractMethodDeclaration[] methodDeclarations;
96         if ((methodDeclarations = this.methods) == null) {
97             length = 0;
98             methodDeclarations = new AbstractMethodDeclaration[1];
99         } else {
100             length = methodDeclarations.length;
101             System.arraycopy(
102                 methodDeclarations,
103                 0,
104                 (methodDeclarations = new AbstractMethodDeclaration[length + 1]),
105                 1,
106                 length);
107         }
108         Clinit clinit = new Clinit(this.compilationResult);
109         methodDeclarations[0] = clinit;
110         // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
111
clinit.declarationSourceStart = clinit.sourceStart = this.sourceStart;
112         clinit.declarationSourceEnd = clinit.sourceEnd = this.sourceEnd;
113         clinit.bodyEnd = this.sourceEnd;
114         this.methods = methodDeclarations;
115     }
116 }
117
118 /*
119  * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding.
120  * It is used to report errors for missing abstract methods.
121  */

122 public MethodDeclaration addMissingAbstractMethodFor(MethodBinding methodBinding) {
123     TypeBinding[] argumentTypes = methodBinding.parameters;
124     int argumentsLength = argumentTypes.length;
125     //the constructor
126
MethodDeclaration methodDeclaration = new MethodDeclaration(this.compilationResult);
127     methodDeclaration.selector = methodBinding.selector;
128     methodDeclaration.sourceStart = this.sourceStart;
129     methodDeclaration.sourceEnd = this.sourceEnd;
130     methodDeclaration.modifiers = methodBinding.getAccessFlags() & ~ClassFileConstants.AccAbstract;
131
132     if (argumentsLength > 0) {
133         String JavaDoc baseName = "arg";//$NON-NLS-1$
134
Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]);
135         for (int i = argumentsLength; --i >= 0;) {
136             arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, ClassFileConstants.AccDefault);
137         }
138     }
139
140     //adding the constructor in the methods list
141
if (this.missingAbstractMethods == null) {
142         this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
143     } else {
144         MethodDeclaration[] newMethods;
145         System.arraycopy(
146             this.missingAbstractMethods,
147             0,
148             newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1],
149             1,
150             this.missingAbstractMethods.length);
151         newMethods[0] = methodDeclaration;
152         this.missingAbstractMethods = newMethods;
153     }
154
155     //============BINDING UPDATE==========================
156
methodDeclaration.binding = new MethodBinding(
157             methodDeclaration.modifiers, //methodDeclaration
158
methodBinding.selector,
159             methodBinding.returnType,
160             argumentsLength == 0 ? Binding.NO_PARAMETERS : argumentTypes, //arguments bindings
161
methodBinding.thrownExceptions, //exceptions
162
this.binding); //declaringClass
163

164     methodDeclaration.scope = new MethodScope(this.scope, methodDeclaration, true);
165     methodDeclaration.bindArguments();
166
167 /* if (binding.methods == null) {
168             binding.methods = new MethodBinding[] { methodDeclaration.binding };
169         } else {
170             MethodBinding[] newMethods;
171             System.arraycopy(
172                 binding.methods,
173                 0,
174                 newMethods = new MethodBinding[binding.methods.length + 1],
175                 1,
176                 binding.methods.length);
177             newMethods[0] = methodDeclaration.binding;
178             binding.methods = newMethods;
179         }*/

180     //===================================================
181

182     return methodDeclaration;
183 }
184
185 /**
186  * Flow analysis for a local innertype
187  *
188  */

189 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
190     if (this.ignoreFurtherInvestigation)
191         return flowInfo;
192     try {
193         if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
194             this.bits |= ASTNode.IsReachable;
195             LocalTypeBinding localType = (LocalTypeBinding) this.binding;
196             localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
197         }
198         manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
199         updateMaxFieldCount(); // propagate down the max field count
200
internalAnalyseCode(flowContext, flowInfo);
201     } catch (AbortType e) {
202         this.ignoreFurtherInvestigation = true;
203     }
204     return flowInfo;
205 }
206
207 /**
208  * Flow analysis for a member innertype
209  *
210  */

211 public void analyseCode(ClassScope enclosingClassScope) {
212     if (this.ignoreFurtherInvestigation)
213         return;
214     try {
215         // propagate down the max field count
216
updateMaxFieldCount();
217         internalAnalyseCode(null, FlowInfo.initial(this.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(ClassScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
228     if (this.ignoreFurtherInvestigation)
229         return;
230     try {
231         if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
232             this.bits |= ASTNode.IsReachable;
233             LocalTypeBinding localType = (LocalTypeBinding) this.binding;
234             localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
235         }
236         manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
237         updateMaxFieldCount(); // propagate down the max field count
238
internalAnalyseCode(flowContext, flowInfo);
239     } catch (AbortType e) {
240         this.ignoreFurtherInvestigation = true;
241     }
242 }
243
244 /**
245  * Flow analysis for a package member type
246  *
247  */

248 public void analyseCode(CompilationUnitScope unitScope) {
249     if (this.ignoreFurtherInvestigation)
250         return;
251     try {
252         internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCount));
253     } catch (AbortType e) {
254         this.ignoreFurtherInvestigation = true;
255     }
256 }
257
258 /**
259  * Check for constructor vs. method with no return type.
260  * Answers true if at least one constructor is defined
261  */

262 public boolean checkConstructors(Parser parser) {
263     //if a constructor has not the name of the type,
264
//convert it into a method with 'null' as its return type
265
boolean hasConstructor = false;
266     if (this.methods != null) {
267         for (int i = this.methods.length; --i >= 0;) {
268             AbstractMethodDeclaration am;
269             if ((am = this.methods[i]).isConstructor()) {
270                 if (!CharOperation.equals(am.selector, this.name)) {
271                     // the constructor was in fact a method with no return type
272
// unless an explicit constructor call was supplied
273
ConstructorDeclaration c = (ConstructorDeclaration) am;
274                     if (c.constructorCall == null || c.constructorCall.isImplicitSuper()) { //changed to a method
275
MethodDeclaration m = parser.convertToMethodDeclaration(c, this.compilationResult);
276                         this.methods[i] = m;
277                     }
278                 } else {
279                     switch (kind(this.modifiers)) {
280                         case TypeDeclaration.INTERFACE_DECL :
281                             // report the problem and continue the parsing
282
parser.problemReporter().interfaceCannotHaveConstructors((ConstructorDeclaration) am);
283                             break;
284                         case TypeDeclaration.ANNOTATION_TYPE_DECL :
285                             // report the problem and continue the parsing
286
parser.problemReporter().annotationTypeDeclarationCannotHaveConstructor((ConstructorDeclaration) am);
287                             break;
288                             
289                     }
290                     hasConstructor = true;
291                 }
292             }
293         }
294     }
295     return hasConstructor;
296 }
297
298 public CompilationResult compilationResult() {
299     return this.compilationResult;
300 }
301
302 public ConstructorDeclaration createDefaultConstructor( boolean needExplicitConstructorCall, boolean needToInsert) {
303     //Add to method'set, the default constuctor that just recall the
304
//super constructor with no arguments
305
//The arguments' type will be positionned by the TC so just use
306
//the default int instead of just null (consistency purpose)
307

308     //the constructor
309
ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
310     constructor.bits |= ASTNode.IsDefaultConstructor;
311     constructor.selector = this.name;
312     constructor.modifiers = this.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;
313
314     //if you change this setting, please update the
315
//SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
316
constructor.declarationSourceStart = constructor.sourceStart = this.sourceStart;
317     constructor.declarationSourceEnd =
318         constructor.sourceEnd = constructor.bodyEnd = this.sourceEnd;
319
320     //the super call inside the constructor
321
if (needExplicitConstructorCall) {
322         constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
323         constructor.constructorCall.sourceStart = this.sourceStart;
324         constructor.constructorCall.sourceEnd = this.sourceEnd;
325     }
326
327     //adding the constructor in the methods list: rank is not critical since bindings will be sorted
328
if (needToInsert) {
329         if (this.methods == null) {
330             this.methods = new AbstractMethodDeclaration[] { constructor };
331         } else {
332             AbstractMethodDeclaration[] newMethods;
333             System.arraycopy(
334                 this.methods,
335                 0,
336                 newMethods = new AbstractMethodDeclaration[this.methods.length + 1],
337                 1,
338                 this.methods.length);
339             newMethods[0] = constructor;
340             this.methods = newMethods;
341         }
342     }
343     return constructor;
344 }
345
346 // anonymous type constructor creation: rank is important since bindings already got sorted
347
public MethodBinding createDefaultConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
348     //Add to method'set, the default constuctor that just recall the
349
//super constructor with the same arguments
350
String JavaDoc baseName = "$anonymous"; //$NON-NLS-1$
351
TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
352     int argumentsLength = argumentTypes.length;
353     //the constructor
354
ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
355     constructor.selector = new char[] { 'x' }; //no maining
356
constructor.sourceStart = this.sourceStart;
357     constructor.sourceEnd = this.sourceEnd;
358     int newModifiers = this.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;
359     if (inheritedConstructorBinding.isVarargs()) {
360         newModifiers |= ClassFileConstants.AccVarargs;
361     }
362     constructor.modifiers = newModifiers;
363     constructor.bits |= ASTNode.IsDefaultConstructor;
364
365     if (argumentsLength > 0) {
366         Argument[] arguments = (constructor.arguments = new Argument[argumentsLength]);
367         for (int i = argumentsLength; --i >= 0;) {
368             arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, ClassFileConstants.AccDefault);
369         }
370     }
371     //the super call inside the constructor
372
constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
373     constructor.constructorCall.sourceStart = this.sourceStart;
374     constructor.constructorCall.sourceEnd = this.sourceEnd;
375
376     if (argumentsLength > 0) {
377         Expression[] args;
378         args = constructor.constructorCall.arguments = new Expression[argumentsLength];
379         for (int i = argumentsLength; --i >= 0;) {
380             args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
381         }
382     }
383
384     //adding the constructor in the methods list
385
if (this.methods == null) {
386         this.methods = new AbstractMethodDeclaration[] { constructor };
387     } else {
388         AbstractMethodDeclaration[] newMethods;
389         System.arraycopy(this.methods, 0, newMethods = new AbstractMethodDeclaration[this.methods.length + 1], 1, this.methods.length);
390         newMethods[0] = constructor;
391         this.methods = newMethods;
392     }
393
394     //============BINDING UPDATE==========================
395
SourceTypeBinding sourceType = this.binding;
396     constructor.binding = new MethodBinding(
397             constructor.modifiers, //methodDeclaration
398
argumentsLength == 0 ? Binding.NO_PARAMETERS : argumentTypes, //arguments bindings
399
inheritedConstructorBinding.thrownExceptions, //exceptions
400
sourceType); //declaringClass
401

402     constructor.binding.modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor;
403             
404     constructor.scope = new MethodScope(this.scope, constructor, true);
405     constructor.bindArguments();
406     constructor.constructorCall.resolve(constructor.scope);
407
408     MethodBinding[] methodBindings = sourceType.methods(); // trigger sorting
409
int length;
410     System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[(length = methodBindings.length) + 1], 1, length);
411     methodBindings[0] = constructor.binding;
412     if (++length > 1)
413         ReferenceBinding.sortMethods(methodBindings, 0, length); // need to resort, since could be valid methods ahead (140643) - DOM needs eager sorting
414
sourceType.setMethods(methodBindings);
415     //===================================================
416

417     return constructor.binding;
418 }
419
420 /**
421  * Find the matching parse node, answers null if nothing found
422  */

423 public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
424     if (fieldBinding != null && this.fields != null) {
425         for (int i = 0, max = this.fields.length; i < max; i++) {
426             FieldDeclaration fieldDecl;
427             if ((fieldDecl = this.fields[i]).binding == fieldBinding)
428                 return fieldDecl;
429         }
430     }
431     return null;
432 }
433
434 /**
435  * Find the matching parse node, answers null if nothing found
436  */

437 public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) {
438     if (memberTypeBinding != null && this.memberTypes != null) {
439         for (int i = 0, max = this.memberTypes.length; i < max; i++) {
440             TypeDeclaration memberTypeDecl;
441             if ((memberTypeDecl = this.memberTypes[i]).binding == memberTypeBinding)
442                 return memberTypeDecl;
443         }
444     }
445     return null;
446 }
447
448 /**
449  * Find the matching parse node, answers null if nothing found
450  */

451 public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
452     if (methodBinding != null && this.methods != null) {
453         for (int i = 0, max = this.methods.length; i < max; i++) {
454             AbstractMethodDeclaration methodDecl;
455
456             if ((methodDecl = this.methods[i]).binding == methodBinding)
457                 return methodDecl;
458         }
459     }
460     return null;
461 }
462
463 /**
464  * Finds the matching type amoung this type's member types.
465  * Returns null if no type with this name is found.
466  * The type name is a compound name relative to this type
467  * eg. if this type is X and we're looking for Y.X.A.B
468  * then a type name would be {X, A, B}
469  */

470 public TypeDeclaration declarationOfType(char[][] typeName) {
471     int typeNameLength = typeName.length;
472     if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) {
473         return null;
474     }
475     if (typeNameLength == 1) {
476         return this;
477     }
478     char[][] subTypeName = new char[typeNameLength - 1][];
479     System.arraycopy(typeName, 1, subTypeName, 0, typeNameLength - 1);
480     for (int i = 0; i < this.memberTypes.length; i++) {
481         TypeDeclaration typeDecl = this.memberTypes[i].declarationOfType(subTypeName);
482         if (typeDecl != null) {
483             return typeDecl;
484         }
485     }
486     return null;
487 }
488
489 /**
490  * Generic bytecode generation for type
491  */

492 public void generateCode(ClassFile enclosingClassFile) {
493     if ((this.bits & ASTNode.HasBeenGenerated) != 0)
494         return;
495     this.bits |= ASTNode.HasBeenGenerated;
496     if (this.ignoreFurtherInvestigation) {
497         if (this.binding == null)
498             return;
499         ClassFile.createProblemType(
500             this,
501             this.scope.referenceCompilationUnit().compilationResult);
502         return;
503     }
504     try {
505         // create the result for a compiled type
506
ClassFile classFile = ClassFile.getNewInstance(this.binding);
507         classFile.initialize(this.binding, enclosingClassFile, false);
508         if (this.binding.isMemberType()) {
509             classFile.recordInnerClasses(this.binding);
510         } else if (this.binding.isLocalType()) {
511             enclosingClassFile.recordInnerClasses(this.binding);
512             classFile.recordInnerClasses(this.binding);
513         }
514
515         // generate all fiels
516
classFile.addFieldInfos();
517
518         if (this.memberTypes != null) {
519             for (int i = 0, max = this.memberTypes.length; i < max; i++) {
520                 TypeDeclaration memberType = this.memberTypes[i];
521                 classFile.recordInnerClasses(memberType.binding);
522                 memberType.generateCode(this.scope, classFile);
523             }
524         }
525         // generate all methods
526
classFile.setForMethodInfos();
527         if (this.methods != null) {
528             for (int i = 0, max = this.methods.length; i < max; i++) {
529                 this.methods[i].generateCode(this.scope, classFile);
530             }
531         }
532         // generate all synthetic and abstract methods
533
classFile.addSpecialMethods();
534
535         if (this.ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
536
throw new AbortType(this.scope.referenceCompilationUnit().compilationResult, null);
537         }
538
539         // finalize the compiled type result
540
classFile.addAttributes();
541         this.scope.referenceCompilationUnit().compilationResult.record(
542             this.binding.constantPoolName(),
543             classFile);
544     } catch (AbortType e) {
545         if (this.binding == null)
546             return;
547         ClassFile.createProblemType(
548             this,
549             this.scope.referenceCompilationUnit().compilationResult);
550     }
551 }
552
553 /**
554  * Bytecode generation for a local inner type (API as a normal statement code gen)
555  */

556 public void generateCode(BlockScope blockScope, CodeStream codeStream) {
557     if ((this.bits & ASTNode.IsReachable) == 0) {
558         return;
559     }
560     if ((this.bits & ASTNode.HasBeenGenerated) != 0) return;
561     int pc = codeStream.position;
562     if (this.binding != null) ((NestedTypeBinding) this.binding).computeSyntheticArgumentSlotSizes();
563     generateCode(codeStream.classFile);
564     codeStream.recordPositionsFrom(pc, this.sourceStart);
565 }
566
567 /**
568  * Bytecode generation for a member inner type
569  */

570 public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) {
571     if ((this.bits & ASTNode.HasBeenGenerated) != 0) return;
572     if (this.binding != null) ((NestedTypeBinding) this.binding).computeSyntheticArgumentSlotSizes();
573     generateCode(enclosingClassFile);
574 }
575
576 /**
577  * Bytecode generation for a package member
578  */

579 public void generateCode(CompilationUnitScope unitScope) {
580     generateCode((ClassFile) null);
581 }
582
583 public boolean hasErrors() {
584     return this.ignoreFurtherInvestigation;
585 }
586
587 /**
588  * Common flow analysis for all types
589  */

590 private void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
591     if ((this.binding.isPrivate() || (this.binding.tagBits & (TagBits.IsAnonymousType|TagBits.IsLocalType)) == TagBits.IsLocalType) && !this.binding.isUsed()) {
592         if (!this.scope.referenceCompilationUnit().compilationResult.hasSyntaxError) {
593             this.scope.problemReporter().unusedPrivateType(this);
594         }
595     }
596     InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, this.initializerScope);
597     InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, this.staticInitializerScope);
598     FlowInfo nonStaticFieldInfo = flowInfo.unconditionalFieldLessCopy();
599     FlowInfo staticFieldInfo = flowInfo.unconditionalFieldLessCopy();
600     if (this.fields != null) {
601         for (int i = 0, count = this.fields.length; i < count; i++) {
602             FieldDeclaration field = this.fields[i];
603             if (field.isStatic()) {
604                 if ((staticFieldInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
605                     field.bits &= ~ASTNode.IsReachable;
606                 
607                 /*if (field.isField()){
608                     staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
609                 } else {*/

610                 staticInitializerContext.handledExceptions = Binding.ANY_EXCEPTION; // tolerate them all, and record them
611
/*}*/
612                 staticFieldInfo =
613                     field.analyseCode(
614                         this.staticInitializerScope,
615                         staticInitializerContext,
616                         staticFieldInfo);
617                 // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
618
// branch, since the previous initializer already got the blame.
619
if (staticFieldInfo == FlowInfo.DEAD_END) {
620                     this.staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
621                     staticFieldInfo = FlowInfo.initial(this.maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
622                 }
623             } else {
624                 if ((nonStaticFieldInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
625                     field.bits &= ~ASTNode.IsReachable;
626                 
627                 /*if (field.isField()){
628                     initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
629                 } else {*/

630                     initializerContext.handledExceptions = Binding.ANY_EXCEPTION; // tolerate them all, and record them
631
/*}*/
632                 nonStaticFieldInfo =
633                     field.analyseCode(this.initializerScope, initializerContext, nonStaticFieldInfo);
634                 // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
635
// branch, since the previous initializer already got the blame.
636
if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
637                     this.initializerScope.problemReporter().initializerMustCompleteNormally(field);
638                     nonStaticFieldInfo = FlowInfo.initial(this.maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
639                 }
640             }
641         }
642     }
643     if (this.memberTypes != null) {
644         for (int i = 0, count = this.memberTypes.length; i < count; i++) {
645             if (flowContext != null){ // local type
646
this.memberTypes[i].analyseCode(this.scope, flowContext, nonStaticFieldInfo.copy().setReachMode(flowInfo.reachMode())); // reset reach mode in case initializers did abrupt completely
647
} else {
648                 this.memberTypes[i].analyseCode(this.scope);
649             }
650         }
651     }
652     if (this.methods != null) {
653         UnconditionalFlowInfo outerInfo = flowInfo.unconditionalFieldLessCopy();
654         FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo);
655         for (int i = 0, count = this.methods.length; i < count; i++) {
656             AbstractMethodDeclaration method = this.methods[i];
657             if (method.ignoreFurtherInvestigation)
658                 continue;
659             if (method.isInitializationMethod()) {
660                 if (method.isStatic()) { // <clinit>
661
method.analyseCode(
662                         this.scope,
663                         staticInitializerContext,
664                         staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo));
665                 } else { // constructor
666
((ConstructorDeclaration)method).analyseCode(this.scope, initializerContext, constructorInfo.copy(), flowInfo.reachMode());
667                 }
668             } else { // regular method
669
method.analyseCode(this.scope, null, flowInfo.copy());
670             }
671         }
672     }
673     // enable enum support ?
674
if (this.binding.isEnum() && !this.binding.isAnonymousType()) {
675         this.enumValuesSyntheticfield = this.binding.addSyntheticFieldForEnumValues();
676     }
677 }
678
679 public final static int kind(int flags) {
680     switch (flags & (ClassFileConstants.AccInterface|ClassFileConstants.AccAnnotation|ClassFileConstants.AccEnum)) {
681         case ClassFileConstants.AccInterface :
682             return TypeDeclaration.INTERFACE_DECL;
683         case ClassFileConstants.AccInterface|ClassFileConstants.AccAnnotation :
684             return TypeDeclaration.ANNOTATION_TYPE_DECL;
685         case ClassFileConstants.AccEnum :
686             return TypeDeclaration.ENUM_DECL;
687         default :
688             return TypeDeclaration.CLASS_DECL;
689     }
690 }
691
692 /*
693  * Access emulation for a local type
694  * force to emulation of access to direct enclosing instance.
695  * By using the initializer scope, we actually only request an argument emulation, the
696  * field is not added until actually used. However we will force allocations to be qualified
697  * with an enclosing instance.
698  * 15.9.2
699  */

700 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
701     if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return;
702     NestedTypeBinding nestedType = (NestedTypeBinding) this.binding;
703     
704     MethodScope methodScope = currentScope.methodScope();
705     if (!methodScope.isStatic && !methodScope.isConstructorCall){
706         nestedType.addSyntheticArgumentAndField(nestedType.enclosingType());
707     }
708     // add superclass enclosing instance arg for anonymous types (if necessary)
709
if (nestedType.isAnonymousType()) {
710         ReferenceBinding superclassBinding = (ReferenceBinding)nestedType.superclass.erasure();
711         if (superclassBinding.enclosingType() != null && !superclassBinding.isStatic()) {
712             if (!superclassBinding.isLocalType()
713                     || ((NestedTypeBinding)superclassBinding).getSyntheticField(superclassBinding.enclosingType(), true) != null){
714
715                 nestedType.addSyntheticArgument(superclassBinding.enclosingType());
716             }
717         }
718         // From 1.5 on, provide access to enclosing instance synthetic constructor argument when declared inside constructor call
719
// only for direct anonymous type
720
//public class X {
721
// void foo() {}
722
// class M {
723
// M(Object o) {}
724
// M() { this(new Object() { void baz() { foo(); }}); } // access to #foo() indirects through constructor synthetic arg: val$this$0
725
// }
726
//}
727
if (!methodScope.isStatic && methodScope.isConstructorCall && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5) {
728             ReferenceBinding enclosing = nestedType.enclosingType();
729             if (enclosing.isNestedType()) {
730                 NestedTypeBinding nestedEnclosing = (NestedTypeBinding)enclosing;
731 // if (nestedEnclosing.findSuperTypeErasingTo(nestedEnclosing.enclosingType()) == null) { // only if not inheriting
732
SyntheticArgumentBinding syntheticEnclosingInstanceArgument = nestedEnclosing.getSyntheticArgument(nestedEnclosing.enclosingType(), true);
733                     if (syntheticEnclosingInstanceArgument != null) {
734                         nestedType.addSyntheticArgumentAndField(syntheticEnclosingInstanceArgument);
735                     }
736                 }
737 // }
738
}
739     }
740 }
741
742 /**
743  * Access emulation for a local member type
744  * force to emulation of access to direct enclosing instance.
745  * By using the initializer scope, we actually only request an argument emulation, the
746  * field is not added until actually used. However we will force allocations to be qualified
747  * with an enclosing instance.
748  *
749  * Local member cannot be static.
750  */

751 public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope, FlowInfo flowInfo) {
752     if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
753     NestedTypeBinding nestedType = (NestedTypeBinding) this.binding;
754     nestedType.addSyntheticArgumentAndField(this.binding.enclosingType());
755     }
756 }
757
758 /**
759  * A <clinit> will be requested as soon as static fields or assertions are present. It will be eliminated during
760  * classfile creation if no bytecode was actually produced based on some optimizations/compiler settings.
761  */

762 public final boolean needClassInitMethod() {
763     // always need a <clinit> when assertions are present
764
if ((this.bits & ASTNode.ContainsAssertion) != 0)
765         return true;
766     
767     switch (kind(this.modifiers)) {
768         case TypeDeclaration.INTERFACE_DECL:
769         case TypeDeclaration.ANNOTATION_TYPE_DECL:
770             return this.fields != null; // fields are implicitly statics
771
case TypeDeclaration.ENUM_DECL:
772             return true; // even if no enum constants, need to set $VALUES array
773
}
774     if (this.fields != null) {
775         for (int i = this.fields.length; --i >= 0;) {
776             FieldDeclaration field = this.fields[i];
777             //need to test the modifier directly while there is no binding yet
778
if ((field.modifiers & ClassFileConstants.AccStatic) != 0)
779                 return true; // TODO (philippe) shouldn't it check whether field is initializer or has some initial value ?
780
}
781     }
782     return false;
783 }
784
785 public void parseMethod(Parser parser, CompilationUnitDeclaration unit) {
786     //connect method bodies
787
if (unit.ignoreMethodBodies)
788         return;
789
790     //members
791
if (this.memberTypes != null) {
792         int length = this.memberTypes.length;
793         for (int i = 0; i < length; i++)
794             this.memberTypes[i].parseMethod(parser, unit);
795     }
796
797     //methods
798
if (this.methods != null) {
799         int length = this.methods.length;
800         for (int i = 0; i < length; i++) {
801             this.methods[i].parseStatements(parser, unit);
802         }
803     }
804
805     //initializers
806
if (this.fields != null) {
807         int length = this.fields.length;
808         for (int i = 0; i < length; i++) {
809             final FieldDeclaration fieldDeclaration = this.fields[i];
810             switch(fieldDeclaration.getKind()) {
811                 case AbstractVariableDeclaration.INITIALIZER:
812                     ((Initializer) fieldDeclaration).parseStatements(parser, this, unit);
813                     break;
814             }
815         }
816     }
817 }
818
819 public StringBuffer JavaDoc print(int indent, StringBuffer JavaDoc output) {
820     if (this.javadoc != null) {
821         this.javadoc.print(indent, output);
822     }
823     if ((this.bits & ASTNode.IsAnonymousType) == 0) {
824         printIndent(indent, output);
825         printHeader(0, output);
826     }
827     return printBody(indent, output);
828 }
829
830 public StringBuffer JavaDoc printBody(int indent, StringBuffer JavaDoc output) {
831     output.append(" {"); //$NON-NLS-1$
832
if (this.memberTypes != null) {
833         for (int i = 0; i < this.memberTypes.length; i++) {
834             if (this.memberTypes[i] != null) {
835   &