1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.ast;
13 import org.eclipse.jdt.core.compiler.*;
14 import org.eclipse.jdt.internal.compiler.ASTVisitor;
15 import org.eclipse.jdt.internal.compiler.*;
16 import org.eclipse.jdt.internal.compiler.impl.*;
17 import org.eclipse.jdt.internal.compiler.codegen.*;
18 import org.eclipse.jdt.internal.compiler.flow.*;
19 import org.eclipse.jdt.internal.compiler.lookup.*;
20 import org.eclipse.jdt.internal.compiler.parser.*;
21 import org.eclipse.jdt.internal.compiler.problem.*;
23 public class TypeDeclaration
25 implements ProblemSeverities, ReferenceContext {
27 public static final char[] ANONYMOUS_EMPTY_NAME = new char[] {};
29 public int modifiers = AccDefault;
30 public int modifiersSourceStart;
32 public TypeReference superclass;
33 public TypeReference[] superInterfaces;
34 public FieldDeclaration[] fields;
35 public AbstractMethodDeclaration[] methods;
36 public TypeDeclaration[] memberTypes;
37 public SourceTypeBinding binding;
38 public ClassScope scope;
39 public MethodScope initializerScope;
40 public MethodScope staticInitializerScope;
41 public boolean ignoreFurtherInvestigation = false;
42 public int maxFieldCount;
43 public int declarationSourceStart;
44 public int declarationSourceEnd;
46 public int bodyEnd; // doesn't include the trailing comment if any.
47 protected boolean hasBeenGenerated = false;
48 public CompilationResult compilationResult;
49 private MethodDeclaration[] missingAbstractMethods;
50 public Javadoc javadoc;
52 public QualifiedAllocationExpression allocation; // for anonymous only
53 public TypeDeclaration enclosingType; // for member types only
55 public TypeDeclaration(CompilationResult compilationResult){
56 this.compilationResult = compilationResult;
60 * We cause the compilation task to abort to a given extent.
62 public void abort(int abortLevel, IProblem problem) {
65 case AbortCompilation :
66 throw new AbortCompilation(this.compilationResult, problem);
67 case AbortCompilationUnit :
68 throw new AbortCompilationUnit(this.compilationResult, problem);
70 throw new AbortMethod(this.compilationResult, problem);
72 throw new AbortType(this.compilationResult, problem);
76 * This method is responsible for adding a <clinit> method declaration to the type method collections.
77 * Note that this implementation is inserting it in first place (as VAJ or javac), and that this
78 * impacts the behavior of the method ConstantPool.resetForClinit(int. int), in so far as
79 * the latter will have to reset the constant pool state accordingly (if it was added first, it does
80 * not need to preserve some of the method specific cached entries since this will be the first method).
81 * inserts the clinit method declaration in the first position.
83 * @see org.eclipse.jdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int)
85 public final void addClinit() {
87 //see comment on needClassInitMethod
88 if (needClassInitMethod()) {
90 AbstractMethodDeclaration[] methodDeclarations;
91 if ((methodDeclarations = this.methods) == null) {
93 methodDeclarations = new AbstractMethodDeclaration[1];
95 length = methodDeclarations.length;
99 (methodDeclarations = new AbstractMethodDeclaration[length + 1]),
103 Clinit clinit = new Clinit(this.compilationResult);
104 methodDeclarations[0] = clinit;
105 // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
106 clinit.declarationSourceStart = clinit.sourceStart = sourceStart;
107 clinit.declarationSourceEnd = clinit.sourceEnd = sourceEnd;
108 clinit.bodyEnd = sourceEnd;
109 this.methods = methodDeclarations;
114 * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding.
115 * It is used to report errors for missing abstract methods.
117 public MethodDeclaration addMissingAbstractMethodFor(MethodBinding methodBinding) {
118 TypeBinding[] argumentTypes = methodBinding.parameters;
119 int argumentsLength = argumentTypes.length;
121 MethodDeclaration methodDeclaration = new MethodDeclaration(this.compilationResult);
122 methodDeclaration.selector = methodBinding.selector;
123 methodDeclaration.sourceStart = sourceStart;
124 methodDeclaration.sourceEnd = sourceEnd;
125 methodDeclaration.modifiers = methodBinding.getAccessFlags() & ~AccAbstract;
127 if (argumentsLength > 0) {
128 String baseName = "arg";//$NON-NLS-1$
129 Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]);
130 for (int i = argumentsLength; --i >= 0;) {
131 arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, AccDefault);
135 //adding the constructor in the methods list
136 if (this.missingAbstractMethods == null) {
137 this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
139 MethodDeclaration[] newMethods;
141 this.missingAbstractMethods,
143 newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1],
145 this.missingAbstractMethods.length);
146 newMethods[0] = methodDeclaration;
147 this.missingAbstractMethods = newMethods;
150 //============BINDING UPDATE==========================
151 methodDeclaration.binding = new MethodBinding(
152 methodDeclaration.modifiers, //methodDeclaration
153 methodBinding.selector,
154 methodBinding.returnType,
155 argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
156 methodBinding.thrownExceptions, //exceptions
157 binding); //declaringClass
159 methodDeclaration.scope = new MethodScope(scope, methodDeclaration, true);
160 methodDeclaration.bindArguments();
162 /* if (binding.methods == null) {
163 binding.methods = new MethodBinding[] { methodDeclaration.binding };
165 MethodBinding[] newMethods;
169 newMethods = new MethodBinding[binding.methods.length + 1],
171 binding.methods.length);
172 newMethods[0] = methodDeclaration.binding;
173 binding.methods = newMethods;
175 //===================================================
177 return methodDeclaration;
181 * Flow analysis for a local innertype
184 public FlowInfo analyseCode(
185 BlockScope currentScope,
186 FlowContext flowContext,
189 if (ignoreFurtherInvestigation)
192 if (flowInfo.isReachable()) {
193 bits |= IsReachableMASK;
194 LocalTypeBinding localType = (LocalTypeBinding) binding;
195 localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
197 manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
198 updateMaxFieldCount(); // propagate down the max field count
199 internalAnalyseCode(flowContext, flowInfo);
200 } catch (AbortType e) {
201 this.ignoreFurtherInvestigation = true;
207 * Flow analysis for a member innertype
210 public void analyseCode(ClassScope enclosingClassScope) {
212 if (ignoreFurtherInvestigation)
215 // propagate down the max field count
216 updateMaxFieldCount();
217 internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
218 } catch (AbortType e) {
219 this.ignoreFurtherInvestigation = true;
224 * Flow analysis for a local member innertype
227 public void analyseCode(
228 ClassScope currentScope,
229 FlowContext flowContext,
232 if (ignoreFurtherInvestigation)
235 if (flowInfo.isReachable()) {
236 bits |= IsReachableMASK;
237 LocalTypeBinding localType = (LocalTypeBinding) binding;
238 localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
240 manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
241 updateMaxFieldCount(); // propagate down the max field count
242 internalAnalyseCode(flowContext, flowInfo);
243 } catch (AbortType e) {
244 this.ignoreFurtherInvestigation = true;
249 * Flow analysis for a package member type
252 public void analyseCode(CompilationUnitScope unitScope) {
254 if (ignoreFurtherInvestigation)
257 internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
258 } catch (AbortType e) {
259 this.ignoreFurtherInvestigation = true;
264 * Check for constructor vs. method with no return type.
265 * Answers true if at least one constructor is defined
267 public boolean checkConstructors(Parser parser) {
269 //if a constructor has not the name of the type,
270 //convert it into a method with 'null' as its return type
271 boolean hasConstructor = false;
272 if (methods != null) {
273 for (int i = methods.length; --i >= 0;) {
274 AbstractMethodDeclaration am;
275 if ((am = methods[i]).isConstructor()) {
276 if (!CharOperation.equals(am.selector, name)) {
277 // the constructor was in fact a method with no return type
278 // unless an explicit constructor call was supplied
279 ConstructorDeclaration c = (ConstructorDeclaration) am;
280 if (c.constructorCall == null || c.constructorCall.isImplicitSuper()) { //changed to a method
281 MethodDeclaration m = parser.convertToMethodDeclaration(c, this.compilationResult);
285 if (this.isInterface()) {
286 // report the problem and continue the parsing
287 parser.problemReporter().interfaceCannotHaveConstructors(
288 (ConstructorDeclaration) am);
290 hasConstructor = true;
295 return hasConstructor;
298 public CompilationResult compilationResult() {
300 return this.compilationResult;
303 public ConstructorDeclaration createsInternalConstructor(
304 boolean needExplicitConstructorCall,
305 boolean needToInsert) {
307 //Add to method'set, the default constuctor that just recall the
308 //super constructor with no arguments
309 //The arguments' type will be positionned by the TC so just use
310 //the default int instead of just null (consistency purpose)
313 ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
314 constructor.isDefaultConstructor = true;
315 constructor.selector = name;
316 if (modifiers != AccDefault) {
317 constructor.modifiers =
318 (((this.bits & ASTNode.IsMemberTypeMASK) != 0) && (modifiers & AccPrivate) != 0)
320 : modifiers & AccVisibilityMASK;
323 //if you change this setting, please update the
324 //SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
325 constructor.declarationSourceStart = constructor.sourceStart = sourceStart;
326 constructor.declarationSourceEnd =
327 constructor.sourceEnd = constructor.bodyEnd = sourceEnd;
329 //the super call inside the constructor
330 if (needExplicitConstructorCall) {
331 constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
332 constructor.constructorCall.sourceStart = sourceStart;
333 constructor.constructorCall.sourceEnd = sourceEnd;
336 //adding the constructor in the methods list
338 if (methods == null) {
339 methods = new AbstractMethodDeclaration[] { constructor };
341 AbstractMethodDeclaration[] newMethods;
345 newMethods = new AbstractMethodDeclaration[methods.length + 1],
348 newMethods[0] = constructor;
349 methods = newMethods;
355 // anonymous type constructor creation
356 public MethodBinding createsInternalConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
358 //Add to method'set, the default constuctor that just recall the
359 //super constructor with the same arguments
360 String baseName = "$anonymous"; //$NON-NLS-1$
361 TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
362 int argumentsLength = argumentTypes.length;
364 ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationResult);
365 cd.selector = new char[] { 'x' }; //no maining
366 cd.sourceStart = sourceStart;
367 cd.sourceEnd = sourceEnd;
368 cd.modifiers = modifiers & AccVisibilityMASK;
369 cd.isDefaultConstructor = true;
371 if (argumentsLength > 0) {
372 Argument[] arguments = (cd.arguments = new Argument[argumentsLength]);
373 for (int i = argumentsLength; --i >= 0;) {
374 arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, AccDefault);
378 //the super call inside the constructor
379 cd.constructorCall = SuperReference.implicitSuperConstructorCall();
380 cd.constructorCall.sourceStart = sourceStart;
381 cd.constructorCall.sourceEnd = sourceEnd;
383 if (argumentsLength > 0) {
385 args = cd.constructorCall.arguments = new Expression[argumentsLength];
386 for (int i = argumentsLength; --i >= 0;) {
387 args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
391 //adding the constructor in the methods list
392 if (methods == null) {
393 methods = new AbstractMethodDeclaration[] { cd };
395 AbstractMethodDeclaration[] newMethods;
399 newMethods = new AbstractMethodDeclaration[methods.length + 1],
403 methods = newMethods;
406 //============BINDING UPDATE==========================
407 cd.binding = new MethodBinding(
408 cd.modifiers, //methodDeclaration
409 argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
410 inheritedConstructorBinding.thrownExceptions, //exceptions
411 binding); //declaringClass
413 cd.scope = new MethodScope(scope, cd, true);
415 cd.constructorCall.resolve(cd.scope);
417 if (binding.methods == null) {
418 binding.methods = new MethodBinding[] { cd.binding };
420 MethodBinding[] newMethods;
424 newMethods = new MethodBinding[binding.methods.length + 1],
426 binding.methods.length);
427 newMethods[0] = cd.binding;
428 binding.methods = newMethods;
430 //===================================================
436 * Find the matching parse node, answers null if nothing found
438 public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
440 if (fieldBinding != null) {
441 for (int i = 0, max = this.fields.length; i < max; i++) {
442 FieldDeclaration fieldDecl;
443 if ((fieldDecl = this.fields[i]).binding == fieldBinding)
451 * Find the matching parse node, answers null if nothing found
453 public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) {
455 if (memberTypeBinding != null) {
456 for (int i = 0, max = this.memberTypes.length; i < max; i++) {
457 TypeDeclaration memberTypeDecl;
458 if ((memberTypeDecl = this.memberTypes[i]).binding == memberTypeBinding)
459 return memberTypeDecl;
466 * Find the matching parse node, answers null if nothing found
468 public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
470 if (methodBinding != null) {
471 for (int i = 0, max = this.methods.length; i < max; i++) {
472 AbstractMethodDeclaration methodDecl;
474 if ((methodDecl = this.methods[i]).binding == methodBinding)
482 * Finds the matching type amoung this type's member types.
483 * Returns null if no type with this name is found.
484 * The type name is a compound name relative to this type
485 * eg. if this type is X and we're looking for Y.X.A.B
486 * then a type name would be {X, A, B}
488 public TypeDeclaration declarationOfType(char[][] typeName) {
490 int typeNameLength = typeName.length;
491 if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) {
494 if (typeNameLength == 1) {
497 char[][] subTypeName = new char[typeNameLength - 1][];
498 System.arraycopy(typeName, 1, subTypeName, 0, typeNameLength - 1);
499 for (int i = 0; i < this.memberTypes.length; i++) {
500 TypeDeclaration typeDecl = this.memberTypes[i].declarationOfType(subTypeName);
501 if (typeDecl != null) {
509 * Generic bytecode generation for type
511 public void generateCode(ClassFile enclosingClassFile) {
513 if (hasBeenGenerated)
515 hasBeenGenerated = true;
516 if (ignoreFurtherInvestigation) {
519 ClassFile.createProblemType(
521 scope.referenceCompilationUnit().compilationResult);
525 // create the result for a compiled type
526 ClassFile classFile = new ClassFile(binding, enclosingClassFile, false);
527 // generate all fiels
528 classFile.addFieldInfos();
530 // record the inner type inside its own .class file to be able
531 // to generate inner classes attributes
532 if (binding.isMemberType())
533 classFile.recordEnclosingTypeAttributes(binding);
534 if (binding.isLocalType()) {
535 enclosingClassFile.recordNestedLocalAttribute(binding);
536 classFile.recordNestedLocalAttribute(binding);
538 if (memberTypes != null) {
539 for (int i = 0, max = memberTypes.length; i < max; i++) {
540 // record the inner type inside its own .class file to be able
541 // to generate inner classes attributes
542 classFile.recordNestedMemberAttribute(memberTypes[i].binding);
543 memberTypes[i].generateCode(scope, classFile);
546 // generate all methods
547 classFile.setForMethodInfos();
548 if (methods != null) {
549 for (int i = 0, max = methods.length; i < max; i++) {
550 methods[i].generateCode(scope, classFile);
554 classFile.generateMissingAbstractMethods(this.missingAbstractMethods, scope.referenceCompilationUnit().compilationResult);
556 // generate all methods
557 classFile.addSpecialMethods();
559 if (ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
560 throw new AbortType(scope.referenceCompilationUnit().compilationResult, null);
563 // finalize the compiled type result
564 classFile.addAttributes();
565 scope.referenceCompilationUnit().compilationResult.record(
566 binding.constantPoolName(),
568 } catch (AbortType e) {
571 ClassFile.createProblemType(
573 scope.referenceCompilationUnit().compilationResult);
578 * Bytecode generation for a local inner type (API as a normal statement code gen)
580 public void generateCode(BlockScope blockScope, CodeStream codeStream) {
582 if ((this.bits & IsReachableMASK) == 0) {
585 if (hasBeenGenerated) return;
586 int pc = codeStream.position;
587 if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
588 generateCode(codeStream.classFile);
589 codeStream.recordPositionsFrom(pc, this.sourceStart);
593 * Bytecode generation for a member inner type
595 public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) {
597 if (hasBeenGenerated) return;
598 if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
599 generateCode(enclosingClassFile);
603 * Bytecode generation for a package member
605 public void generateCode(CompilationUnitScope unitScope) {
607 generateCode((ClassFile) null);
610 public boolean hasErrors() {
611 return this.ignoreFurtherInvestigation;
615 * Common flow analysis for all types
618 public void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
620 if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
621 if (!scope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
622 scope.problemReporter().unusedPrivateType(this);
626 InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, initializerScope);
627 InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, staticInitializerScope);
628 FlowInfo nonStaticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
629 FlowInfo staticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
630 if (fields != null) {
631 for (int i = 0, count = fields.length; i < count; i++) {
632 FieldDeclaration field = fields[i];
633 if (field.isStatic()) {
634 /*if (field.isField()){
635 staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
637 staticInitializerContext.handledExceptions = AnyException; // tolerate them all, and record them
641 staticInitializerScope,
642 staticInitializerContext,
644 // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
645 // branch, since the previous initializer already got the blame.
646 if (staticFieldInfo == FlowInfo.DEAD_END) {
647 staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
648 staticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
651 /*if (field.isField()){
652 initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
654 initializerContext.handledExceptions = AnyException; // tolerate them all, and record them
657 field.analyseCode(initializerScope, initializerContext, nonStaticFieldInfo);
658 // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
659 // branch, since the previous initializer already got the blame.
660 if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
661 initializerScope.problemReporter().initializerMustCompleteNormally(field);
662 nonStaticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
667 if (memberTypes != null) {
668 for (int i = 0, count = memberTypes.length; i < count; i++) {
669 if (flowContext != null){ // local type
670 memberTypes[i].analyseCode(scope, flowContext, nonStaticFieldInfo.copy());
672 memberTypes[i].analyseCode(scope);
676 if (methods != null) {
677 UnconditionalFlowInfo outerInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
678 FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo);
679 for (int i = 0, count = methods.length; i < count; i++) {
680 AbstractMethodDeclaration method = methods[i];
681 if (method.ignoreFurtherInvestigation)
683 if (method.isInitializationMethod()) {
684 if (method.isStatic()) { // <clinit>
687 staticInitializerContext,
688 staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo));
689 } else { // constructor
690 method.analyseCode(scope, initializerContext, constructorInfo.copy());
692 } else { // regular method
693 method.analyseCode(scope, null, flowInfo.copy());
699 public boolean isInterface() {
701 return (modifiers & AccInterface) != 0;
705 * Access emulation for a local type
706 * force to emulation of access to direct enclosing instance.
707 * By using the initializer scope, we actually only request an argument emulation, the
708 * field is not added until actually used. However we will force allocations to be qualified
709 * with an enclosing instance.
712 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
714 if (!flowInfo.isReachable()) return;
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 necessary)
723 if (binding.isAnonymousType()) {
724 ReferenceBinding superclassBinding = binding.superclass;
725 if (superclassBinding.enclosingType() != null && !superclassBinding.isStatic()) {
726 if (!superclassBinding.isLocalType()
727 || ((NestedTypeBinding)superclassBinding).getSyntheticField(superclassBinding.enclosingType(), true) != null){
729 nestedType.addSyntheticArgument(superclassBinding.enclosingType());
736 * Access emulation for a local member type
737 * force to emulation of access to direct enclosing instance.
738 * By using the initializer scope, we actually only request an argument emulation, the
739 * field is not added until actually used. However we will force allocations to be qualified
740 * with an enclosing instance.
742 * Local member cannot be static.
744 public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope, FlowInfo flowInfo) {
746 if (!flowInfo.isReachable()) return;
747 NestedTypeBinding nestedType = (NestedTypeBinding) binding;
748 nestedType.addSyntheticArgumentAndField(binding.enclosingType());
752 * A <clinit> will be requested as soon as static fields or assertions are present. It will be eliminated during
753 * classfile creation if no bytecode was actually produced based on some optimizations/compiler settings.
755 public final boolean needClassInitMethod() {
757 // always need a <clinit> when assertions are present
758 if ((this.bits & AddAssertionMASK) != 0)
763 return true; // fields are implicitly statics
764 for (int i = fields.length; --i >= 0;) {
765 FieldDeclaration field = fields[i];
766 //need to test the modifier directly while there is no binding yet
767 if ((field.modifiers & AccStatic) != 0)
773 public void parseMethod(Parser parser, CompilationUnitDeclaration unit) {
775 //connect method bodies
776 if (unit.ignoreMethodBodies)
780 if (memberTypes != null) {
781 int length = memberTypes.length;
782 for (int i = 0; i < length; i++)
783 memberTypes[i].parseMethod(parser, unit);
787 if (methods != null) {
788 int length = methods.length;
789 for (int i = 0; i < length; i++)
790 methods[i].parseStatements(parser, unit);
794 if (fields != null) {
795 int length = fields.length;
796 for (int i = 0; i < length; i++) {
797 if (fields[i] instanceof Initializer) {
798 ((Initializer) fields[i]).parseStatements(parser, this, unit);
804 public StringBuffer print(int indent, StringBuffer output) {
806 if ((this.bits & IsAnonymousTypeMASK) == 0) {
807 printIndent(indent, output);
808 printHeader(0, output);
810 return printBody(indent, output);
813 public StringBuffer printBody(int indent, StringBuffer output) {
815 output.append(" {"); //$NON-NLS-1$
816 if (memberTypes != null) {
817 for (int i = 0; i < memberTypes.length; i++) {
818 if (memberTypes[i] != null) {
820 memberTypes[i].print(indent + 1, output);
824 if (fields != null) {
825 for (int fieldI = 0; fieldI < fields.length; fieldI++) {
826 if (fields[fieldI] != null) {
828 fields[fieldI].print(indent + 1, output);
832 if (methods != null) {
833 for (int i = 0; i < methods.length; i++) {
834 if (methods[i] != null) {
836 methods[i].print(indent + 1, output);
841 return printIndent(indent, output).append('}');
844 public StringBuffer printHeader(int indent, StringBuffer output) {
846 printModifiers(this.modifiers, output);
847 output.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
849 if (superclass != null) {
850 output.append(" extends "); //$NON-NLS-1$
851 superclass.print(0, output);
853 if (superInterfaces != null && superInterfaces.length > 0) {
854 output.append(isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
855 for (int i = 0; i < superInterfaces.length; i++) {
856 if (i > 0) output.append( ", "); //$NON-NLS-1$
857 superInterfaces[i].print(0, output);
863 public StringBuffer printStatement(int tab, StringBuffer output) {
864 return print(tab, output);
867 public void resolve() {
869 if (this.binding == null) {
870 this.ignoreFurtherInvestigation = true;
874 if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
875 this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd);
877 // check superclass & interfaces
878 if (this.binding.superclass != null) // watch out for Object ! (and other roots)
879 if (isTypeUseDeprecated(this.binding.superclass, this.scope))
880 this.scope.problemReporter().deprecatedType(this.binding.superclass, this.superclass);
881 if (this.superInterfaces != null)
882 for (int i = this.superInterfaces.length; --i >= 0;)
883 if (this.superInterfaces[i].resolvedType != null)
884 if (isTypeUseDeprecated(this.superInterfaces[i].resolvedType, this.scope))
885 this.scope.problemReporter().deprecatedType(
886 this.superInterfaces[i].resolvedType,
887 this.superInterfaces[i]);
888 this.maxFieldCount = 0;
889 int lastVisibleFieldID = -1;
890 if (this.fields != null) {
891 for (int i = 0, count = this.fields.length; i < count; i++) {
892 FieldDeclaration field = this.fields[i];
893 if (field.isField()) {
894 if (field.binding == null) {
895 // still discover secondary errors
896 if (field.initialization != null) field.initialization.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
897 this.ignoreFurtherInvestigation = true;
900 this.maxFieldCount++;
901 lastVisibleFieldID = field.binding.id;
902 } else { // initializer
903 ((Initializer) field).lastVisibleFieldID = lastVisibleFieldID + 1;
905 field.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
908 if (this.memberTypes != null) {
909 for (int i = 0, count = this.memberTypes.length; i < count; i++) {
910 this.memberTypes[i].resolve(this.scope);
913 int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
914 int methodsLength = this.methods == null ? 0 : this.methods.length;
915 if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) {
916 this.scope.problemReporter().tooManyMethods(this);
919 if (this.methods != null) {
920 for (int i = 0, count = this.methods.length; i < count; i++) {
921 this.methods[i].resolve(this.scope);
925 if (this.javadoc != null) {
926 if (this.scope != null) {
927 this.javadoc.resolve(this.scope);
929 } else if (this.binding != null && !this.binding.isLocalType()) {
930 this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
933 } catch (AbortType e) {
934 this.ignoreFurtherInvestigation = true;
939 public void resolve(BlockScope blockScope) {
940 // local type declaration
942 // need to build its scope first and proceed with binding's creation
943 if ((this.bits & IsAnonymousTypeMASK) == 0) blockScope.addLocalType(this);
945 if (binding != null) {
946 // remember local types binding for innerclass emulation propagation
947 blockScope.referenceCompilationUnit().record((LocalTypeBinding)binding);
949 // binding is not set if the receiver could not be created
951 updateMaxFieldCount();
955 public void resolve(ClassScope upperScope) {
956 // member scopes are already created
957 // request the construction of a binding if local member type
959 if (binding != null && binding instanceof LocalTypeBinding) {
960 // remember local types binding for innerclass emulation propagation
961 upperScope.referenceCompilationUnit().record((LocalTypeBinding)binding);
964 updateMaxFieldCount();
967 public void resolve(CompilationUnitScope upperScope) {
968 // top level : scope are already created
971 updateMaxFieldCount();
974 public void tagAsHavingErrors() {
975 ignoreFurtherInvestigation = true;
980 * Iteration for a package member type
983 public void traverse(
985 CompilationUnitScope unitScope) {
987 if (ignoreFurtherInvestigation)
990 if (visitor.visit(this, unitScope)) {
991 if (superclass != null)
992 superclass.traverse(visitor, scope);
993 if (superInterfaces != null) {
994 int superInterfaceLength = superInterfaces.length;
995 for (int i = 0; i < superInterfaceLength; i++)
996 superInterfaces[i].traverse(visitor, scope);
998 if (memberTypes != null) {
999 int memberTypesLength = memberTypes.length;
1000 for (int i = 0; i < memberTypesLength; i++)
1001 memberTypes[i].traverse(visitor, scope);
1003 if (fields != null) {
1004 int fieldsLength = fields.length;
1005 for (int i = 0; i < fieldsLength; i++) {
1006 FieldDeclaration field;
1007 if ((field = fields[i]).isStatic()) {
1008 field.traverse(visitor, staticInitializerScope);
1010 field.traverse(visitor, initializerScope);
1014 if (methods != null) {
1015 int methodsLength = methods.length;
1016 for (int i = 0; i < methodsLength; i++)
1017 methods[i].traverse(visitor, scope);
1020 visitor.endVisit(this, unitScope);
1021 } catch (AbortType e) {
1027 * Iteration for a local innertype
1030 public void traverse(ASTVisitor visitor, BlockScope blockScope) {
1031 if (ignoreFurtherInvestigation)
1034 if (visitor.visit(this, blockScope)) {
1035 if (superclass != null)
1036 superclass.traverse(visitor, scope);
1037 if (superInterfaces != null) {
1038 int superInterfaceLength = superInterfaces.length;
1039 for (int i = 0; i < superInterfaceLength; i++)
1040 superInterfaces[i].traverse(visitor, scope);
1042 if (memberTypes != null) {
1043 int memberTypesLength = memberTypes.length;
1044 for (int i = 0; i < memberTypesLength; i++)
1045 memberTypes[i].traverse(visitor, scope);
1047 if (fields != null) {
1048 int fieldsLength = fields.length;
1049 for (int i = 0; i < fieldsLength; i++) {
1050 FieldDeclaration field;
1051 if ((field = fields[i]).isStatic()) {
1052 // local type cannot have static fields
1054 field.traverse(visitor, initializerScope);
1058 if (methods != null) {
1059 int methodsLength = methods.length;
1060 for (int i = 0; i < methodsLength; i++)
1061 methods[i].traverse(visitor, scope);
1064 visitor.endVisit(this, blockScope);
1065 } catch (AbortType e) {
1071 * Iteration for a member innertype
1074 public void traverse(ASTVisitor visitor, ClassScope classScope) {
1075 if (ignoreFurtherInvestigation)
1078 if (visitor.visit(this, classScope)) {
1079 if (superclass != null)
1080 superclass.traverse(visitor, scope);
1081 if (superInterfaces != null) {
1082 int superInterfaceLength = superInterfaces.length;
1083 for (int i = 0; i < superInterfaceLength; i++)
1084 superInterfaces[i].traverse(visitor, scope);
1086 if (memberTypes != null) {
1087 int memberTypesLength = memberTypes.length;
1088 for (int i = 0; i < memberTypesLength; i++)
1089 memberTypes[i].traverse(visitor, scope);
1091 if (fields != null) {
1092 int fieldsLength = fields.length;
1093 for (int i = 0; i < fieldsLength; i++) {
1094 FieldDeclaration field;
1095 if ((field = fields[i]).isStatic()) {
1096 field.traverse(visitor, staticInitializerScope);
1098 field.traverse(visitor, initializerScope);
1102 if (methods != null) {
1103 int methodsLength = methods.length;
1104 for (int i = 0; i < methodsLength; i++)
1105 methods[i].traverse(visitor, scope);
1108 visitor.endVisit(this, classScope);
1109 } catch (AbortType e) {
1115 * MaxFieldCount's computation is necessary so as to reserve space for
1116 * the flow info field portions. It corresponds to the maximum amount of
1117 * fields this class or one of its innertypes have.
1119 * During name resolution, types are traversed, and the max field count is recorded
1120 * on the outermost type. It is then propagated down during the flow analysis.
1122 * This method is doing either up/down propagation.
1124 void updateMaxFieldCount() {
1126 if (binding == null)
1127 return; // error scenario
1128 TypeDeclaration outerMostType = scope.outerMostClassScope().referenceType();
1129 if (maxFieldCount > outerMostType.maxFieldCount) {
1130 outerMostType.maxFieldCount = maxFieldCount; // up
1132 maxFieldCount = outerMostType.maxFieldCount; // down