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
6 * Contributors: IBM Corporation - initial API and implementation
7 **********************************************************************************************************************************/
8 package net.sourceforge.phpdt.internal.compiler.ast;
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;
38 public class TypeDeclaration extends Statement implements ProblemSeverities,
43 public int modifiersSourceStart;
47 public TypeReference superclass;
49 public TypeReference[] superInterfaces;
51 public FieldDeclaration[] fields;
53 public AbstractMethodDeclaration[] methods;
55 public TypeDeclaration[] memberTypes;
57 public SourceTypeBinding binding;
59 public ClassScope scope;
61 public MethodScope initializerScope;
63 public MethodScope staticInitializerScope;
65 public boolean ignoreFurtherInvestigation = false;
67 public int maxFieldCount;
69 public int declarationSourceStart;
71 public int declarationSourceEnd;
75 public int bodyEnd; // doesn't include the trailing comment if any.
77 protected boolean hasBeenGenerated = false;
79 public CompilationResult compilationResult;
81 private MethodDeclaration[] missingAbstractMethods;
83 public TypeDeclaration(CompilationResult compilationResult) {
84 this.compilationResult = compilationResult;
88 * We cause the compilation task to abort to a given extent.
90 public void abort(int abortLevel) {
93 throw new AbortCompilation(); // cannot do better
96 CompilationResult compilationResult = scope.referenceCompilationUnit().compilationResult;
99 case AbortCompilation:
100 throw new AbortCompilation(compilationResult);
101 case AbortCompilationUnit:
102 throw new AbortCompilationUnit(compilationResult);
104 throw new AbortMethod(compilationResult);
106 throw new AbortType(compilationResult);
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.
120 * @see net.sourceforge.phpdt.internal.compiler.codegen.ConstantPool#resetForClinit(int,
123 public final void addClinit() {
125 // see comment on needClassInitMethod
126 if (needClassInitMethod()) {
128 AbstractMethodDeclaration[] methods;
129 if ((methods = this.methods) == null) {
131 methods = new AbstractMethodDeclaration[1];
133 length = methods.length;
134 System.arraycopy(methods, 0,
135 (methods = new AbstractMethodDeclaration[length + 1]),
138 Clinit clinit = new Clinit(this.compilationResult);
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;
150 * Flow analysis for a local innertype
153 public FlowInfo analyseCode(BlockScope currentScope,
154 FlowContext flowContext, FlowInfo flowInfo) {
156 if (ignoreFurtherInvestigation)
159 bits |= IsReachableMASK;
160 LocalTypeBinding localType = (LocalTypeBinding) binding;
162 localType.setConstantPoolName(currentScope.compilationUnitScope()
163 .computeConstantPoolName(localType));
164 manageEnclosingInstanceAccessIfNecessary(currentScope);
166 updateMaxFieldCount(); // propagate down the max field count
167 internalAnalyseCode(flowContext, flowInfo);
168 } catch (AbortType e) {
169 this.ignoreFurtherInvestigation = true;
175 * Flow analysis for a member innertype
178 public void analyseCode(ClassScope enclosingClassScope) {
180 if (ignoreFurtherInvestigation)
183 // propagate down the max field count
184 updateMaxFieldCount();
185 internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
186 } catch (AbortType e) {
187 this.ignoreFurtherInvestigation = true;
192 * Flow analysis for a local member innertype
195 public void analyseCode(ClassScope currentScope, FlowContext flowContext,
198 if (ignoreFurtherInvestigation)
201 bits |= IsReachableMASK;
202 LocalTypeBinding localType = (LocalTypeBinding) binding;
204 localType.setConstantPoolName(currentScope.compilationUnitScope()
205 .computeConstantPoolName(localType));
206 manageEnclosingInstanceAccessIfNecessary(currentScope);
208 updateMaxFieldCount(); // propagate down the max field count
209 internalAnalyseCode(flowContext, flowInfo);
210 } catch (AbortType e) {
211 this.ignoreFurtherInvestigation = true;
216 * Flow analysis for a package member type
219 public void analyseCode(CompilationUnitScope unitScope) {
221 if (ignoreFurtherInvestigation)
224 internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
225 } catch (AbortType e) {
226 this.ignoreFurtherInvestigation = true;
231 * Check for constructor vs. method with no return type. Answers true if at
232 * least one constructor is defined
234 public boolean checkConstructors(Parser parser) {
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
246 // unless an explicit constructor call was supplied
247 ConstructorDeclaration c = (ConstructorDeclaration) am;
248 if ((c.constructorCall == null)
249 || (c.constructorCall.isImplicitSuper())) { // changed
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;
270 if (this.isInterface()) {
271 // report the problem and continue the parsing
272 parser.problemReporter()
273 .interfaceCannotHaveConstructors(
274 (ConstructorDeclaration) am);
276 hasConstructor = true;
281 return hasConstructor;
284 public CompilationResult compilationResult() {
286 return this.compilationResult;
289 public ConstructorDeclaration createsInternalConstructor(
290 boolean needExplicitConstructorCall, boolean needToInsert) {
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)
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;
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;
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;
320 // adding the constructor in the methods list
322 if (methods == null) {
323 methods = new AbstractMethodDeclaration[] { constructor };
325 AbstractMethodDeclaration[] newMethods;
330 newMethods = new AbstractMethodDeclaration[methods.length + 1],
332 newMethods[0] = constructor;
333 methods = newMethods;
340 * INTERNAL USE ONLY - Creates a fake method declaration for the
341 * corresponding binding. It is used to report errors for missing abstract
344 public MethodDeclaration addMissingAbstractMethodFor(
345 MethodBinding methodBinding) {
346 TypeBinding[] argumentTypes = methodBinding.parameters;
347 int argumentsLength = argumentTypes.length;
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()
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);
366 // adding the constructor in the methods list
367 if (this.missingAbstractMethods == null) {
368 this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
370 MethodDeclaration[] newMethods;
373 this.missingAbstractMethods,
375 newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1],
376 1, this.missingAbstractMethods.length);
377 newMethods[0] = methodDeclaration;
378 this.missingAbstractMethods = newMethods;
381 // ============BINDING UPDATE==========================
382 methodDeclaration.binding = new MethodBinding(
383 methodDeclaration.modifiers, // methodDeclaration
384 methodBinding.selector, methodBinding.returnType,
385 argumentsLength == 0 ? NoParameters : argumentTypes, // arguments
387 methodBinding.thrownExceptions, // exceptions
388 binding); // declaringClass
390 methodDeclaration.scope = new MethodScope(scope, methodDeclaration,
392 methodDeclaration.bindArguments();
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; }
402 // ===================================================
403 return methodDeclaration;
407 * Find the matching parse node, answers null if nothing found
409 public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
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)
422 * Find the matching parse node, answers null if nothing found
424 public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) {
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;
437 * Find the matching parse node, answers null if nothing found
439 public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
441 if (methodBinding != null) {
442 for (int i = 0, max = this.methods.length; i < max; i++) {
443 AbstractMethodDeclaration methodDecl;
445 if ((methodDecl = this.methods[i]).binding == methodBinding)
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}
458 public TypeDeclaration declarationOfType(char[][] typeName) {
460 int typeNameLength = typeName.length;
461 if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) {
464 if (typeNameLength == 1) {
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) {
480 * Generic bytecode generation for type
482 // public void generateCode(ClassFile enclosingClassFile) {
484 // if (hasBeenGenerated)
486 // hasBeenGenerated = true;
487 // if (ignoreFurtherInvestigation) {
488 // if (binding == null)
490 // ClassFile.createProblemType(
492 // scope.referenceCompilationUnit().compilationResult);
496 // // create the result for a compiled type
497 // ClassFile classFile = new ClassFile(binding, enclosingClassFile, false);
498 // // generate all fiels
499 // classFile.addFieldInfos();
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);
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);
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);
525 // classFile.generateMissingAbstractMethods(this.missingAbstractMethods,
526 // scope.referenceCompilationUnit().compilationResult);
528 // // generate all methods
529 // classFile.addSpecialMethods();
531 // if (ignoreFurtherInvestigation) { // trigger problem type generation for
533 // throw new AbortType(scope.referenceCompilationUnit().compilationResult);
536 // // finalize the compiled type result
537 // classFile.addAttributes();
538 // scope.referenceCompilationUnit().compilationResult.record(
539 // binding.constantPoolName(),
541 // } catch (AbortType e) {
542 // if (binding == null)
544 // ClassFile.createProblemType(
546 // scope.referenceCompilationUnit().compilationResult);
550 * Bytecode generation for a local inner type (API as a normal statement
553 // public void generateCode(BlockScope blockScope, CodeStream codeStream) {
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);
563 * Bytecode generation for a member inner type
565 // public void generateCode(ClassScope classScope, ClassFile
566 // enclosingClassFile) {
568 // if (hasBeenGenerated) return;
569 // if (binding != null) ((NestedTypeBinding)
570 // binding).computeSyntheticArgumentSlotSizes();
571 // generateCode(enclosingClassFile);
574 * Bytecode generation for a package member
576 // public void generateCode(CompilationUnitScope unitScope) {
578 // generateCode((ClassFile) null);
580 public boolean hasErrors() {
581 return this.ignoreFurtherInvestigation;
585 * Common flow analysis for all types
588 public void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
590 if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
591 if (!scope.referenceCompilationUnit().compilationResult
593 scope.problemReporter().unusedPrivateType(this);
597 ReferenceBinding[] defaultHandledExceptions = new ReferenceBinding[] { scope
598 .getJavaLangThrowable() }; // tolerate any kind of
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()) {
613 * if (field.isField()){
614 * staticInitializerContext.handledExceptions =
615 * NoExceptions; // no exception is allowed jls8.3.2 } else {
617 staticInitializerContext.handledExceptions = defaultHandledExceptions; // tolerate
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
630 if (staticFieldInfo == FlowInfo.DEAD_END) {
631 staticInitializerScope.problemReporter()
632 .initializerMustCompleteNormally(field);
633 staticFieldInfo = FlowInfo.initial(maxFieldCount)
634 .setReachMode(FlowInfo.UNREACHABLE);
638 * if (field.isField()){
639 * initializerContext.handledExceptions = NoExceptions; //
640 * no exception is allowed jls8.3.2 } else {
642 initializerContext.handledExceptions = defaultHandledExceptions; // tolerate
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
655 if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
656 initializerScope.problemReporter()
657 .initializerMustCompleteNormally(field);
658 nonStaticFieldInfo = FlowInfo.initial(maxFieldCount)
659 .setReachMode(FlowInfo.UNREACHABLE);
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());
670 memberTypes[i].analyseCode(scope);
674 if (methods != null) {
675 UnconditionalFlowInfo outerInfo = flowInfo.copy()
676 .unconditionalInits().discardFieldInitializations();
677 FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits()
678 .discardNonFieldInitializations().addInitializationsFrom(
680 for (int i = 0, count = methods.length; i < count; i++) {
681 AbstractMethodDeclaration method = methods[i];
682 if (method.ignoreFurtherInvestigation)
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());
694 } else { // regular method
695 method.analyseCode(scope, null, flowInfo.copy());
701 public boolean isInterface() {
703 return (modifiers & AccInterface) != 0;
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
713 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
715 NestedTypeBinding nestedType = (NestedTypeBinding) binding;
717 MethodScope methodScope = currentScope.methodScope();
718 if (!methodScope.isStatic && !methodScope.isConstructorCall) {
720 nestedType.addSyntheticArgumentAndField(binding.enclosingType());
722 // add superclass enclosing instance arg for anonymous types (if
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(),
732 nestedType.addSyntheticArgument(superclass.enclosingType());
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
745 * Local member cannot be static.
747 public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope) {
749 NestedTypeBinding nestedType = (NestedTypeBinding) binding;
750 nestedType.addSyntheticArgumentAndField(binding.enclosingType());
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.
758 public final boolean needClassInitMethod() {
760 // always need a <clinit> when assertions are present
761 if ((this.bits & AddAssertionMASK) != 0)
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)
776 public void parseMethod(UnitParser parser, CompilationUnitDeclaration unit) {
778 // connect method bodies
779 if (unit.ignoreMethodBodies)
782 // no scope were created, so cannot report further errors
783 // if (binding == null)
787 if (memberTypes != null) {
788 int length = memberTypes.length;
789 for (int i = 0; i < length; i++)
790 memberTypes[i].parseMethod(parser, unit);
794 if (methods != null) {
795 int length = methods.length;
796 for (int i = 0; i < length; i++)
797 methods[i].parseStatements(parser, unit);
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,
812 public void resolve() {
814 if (binding == null) {
815 ignoreFurtherInvestigation = true;
820 // check superclass & interfaces
821 if (binding.superclass != null) // watch out for Object ! (and other
823 if (isTypeUseDeprecated(binding.superclass, scope))
824 scope.problemReporter().deprecatedType(binding.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,
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)
844 .resolve(field.isStatic() ? staticInitializerScope
846 ignoreFurtherInvestigation = true;
850 lastFieldID = field.binding.id;
851 } else { // initializer
852 ((Initializer) field).lastFieldID = lastFieldID + 1;
854 field.resolve(field.isStatic() ? staticInitializerScope
858 if (memberTypes != null) {
859 for (int i = 0, count = memberTypes.length; i < count; i++) {
860 memberTypes[i].resolve(scope);
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);
870 if (methods != null) {
871 for (int i = 0, count = methods.length; i < count; i++) {
872 methods[i].resolve(scope);
875 } catch (AbortType e) {
876 this.ignoreFurtherInvestigation = true;
882 public void resolve(BlockScope blockScope) {
883 // local type declaration
885 // need to build its scope first and proceed with binding's creation
886 blockScope.addLocalType(this);
889 if (binding != null) {
890 // remember local types binding for innerclass emulation propagation
891 blockScope.referenceCompilationUnit().record(
892 (LocalTypeBinding) binding);
894 // binding is not set if the receiver could not be created
896 updateMaxFieldCount();
900 public void resolve(ClassScope upperScope) {
901 // member scopes are already created
902 // request the construction of a binding if local member type
904 if (binding != null && binding instanceof LocalTypeBinding) {
905 // remember local types binding for innerclass emulation propagation
906 upperScope.referenceCompilationUnit().record(
907 (LocalTypeBinding) binding);
910 updateMaxFieldCount();
913 public void resolve(CompilationUnitScope upperScope) {
914 // top level : scope are already created
917 updateMaxFieldCount();
920 public void tagAsHavingErrors() {
921 ignoreFurtherInvestigation = true;
924 public StringBuffer print(int indent, StringBuffer output) {
926 // if ((this.bits & IsAnonymousTypeMASK) == 0) {
927 printIndent(indent, output);
928 printHeader(0, output);
930 return printBody(indent, output);
933 public StringBuffer printBody(int indent, StringBuffer output) {
935 output.append(" {"); //$NON-NLS-1$
936 if (memberTypes != null) {
937 for (int i = 0; i < memberTypes.length; i++) {
938 if (memberTypes[i] != null) {
940 memberTypes[i].print(indent + 1, output);
944 if (fields != null) {
945 for (int fieldI = 0; fieldI < fields.length; fieldI++) {
946 if (fields[fieldI] != null) {
948 fields[fieldI].print(indent + 1, output);
952 if (methods != null) {
953 for (int i = 0; i < methods.length; i++) {
954 if (methods[i] != null) {
956 methods[i].print(indent + 1, output);
961 return printIndent(indent, output).append('}');
964 public StringBuffer printHeader(int indent, StringBuffer output) {
966 printModifiers(this.modifiers, output);
967 output.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
969 if (superclass != null) {
970 output.append(" extends "); //$NON-NLS-1$
971 superclass.print(0, output);
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++) {
977 output.append(", "); //$NON-NLS-1$
978 superInterfaces[i].print(0, output);
984 public StringBuffer printStatement(int tab, StringBuffer output) {
985 return print(tab, output);
988 public String toString(int tab) {
990 return tabString(tab) + toStringHeader() + toStringBody(tab);
993 public String toStringBody(int tab) {
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$
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$
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$
1019 s += "\n" + tabString(tab) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
1023 public String toStringHeader() {
1025 String s = ""; //$NON-NLS-1$
1026 if (modifiers != AccDefault) {
1027 s += modifiersString(modifiers);
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$
1046 * Iteration for a local innertype
1049 public void traverse(ASTVisitor visitor, BlockScope blockScope) {
1050 if (ignoreFurtherInvestigation)
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);
1061 if (memberTypes != null) {
1062 int memberTypesLength = memberTypes.length;
1063 for (int i = 0; i < memberTypesLength; i++)
1064 memberTypes[i].traverse(visitor, scope);
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
1073 field.traverse(visitor, initializerScope);
1077 if (methods != null) {
1078 int methodsLength = methods.length;
1079 for (int i = 0; i < methodsLength; i++)
1080 methods[i].traverse(visitor, scope);
1083 visitor.endVisit(this, blockScope);
1084 } catch (AbortType e) {
1090 * Iteration for a member innertype
1093 public void traverse(ASTVisitor visitor, ClassScope classScope) {
1094 if (ignoreFurtherInvestigation)
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);
1105 if (memberTypes != null) {
1106 int memberTypesLength = memberTypes.length;
1107 for (int i = 0; i < memberTypesLength; i++)
1108 memberTypes[i].traverse(visitor, scope);
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);
1117 field.traverse(visitor, initializerScope);
1121 if (methods != null) {
1122 int methodsLength = methods.length;
1123 for (int i = 0; i < methodsLength; i++)
1124 methods[i].traverse(visitor, scope);
1127 visitor.endVisit(this, classScope);
1128 } catch (AbortType e) {
1134 * Iteration for a package member type
1137 public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) {
1139 if (ignoreFurtherInvestigation)
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);
1150 if (memberTypes != null) {
1151 int memberTypesLength = memberTypes.length;
1152 for (int i = 0; i < memberTypesLength; i++)
1153 memberTypes[i].traverse(visitor, scope);
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);
1162 field.traverse(visitor, initializerScope);
1166 if (methods != null) {
1167 int methodsLength = methods.length;
1168 for (int i = 0; i < methodsLength; i++)
1169 methods[i].traverse(visitor, scope);
1172 visitor.endVisit(this, unitScope);
1173 } catch (AbortType e) {
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.
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
1186 * This method is doing either up/down propagation.
1188 void updateMaxFieldCount() {
1190 if (binding == null)
1191 return; // error scenario
1192 TypeDeclaration outerMostType = scope.outerMostClassScope()
1194 if (maxFieldCount > outerMostType.maxFieldCount) {
1195 outerMostType.maxFieldCount = maxFieldCount; // up
1197 maxFieldCount = outerMostType.maxFieldCount; // down