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