1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 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 net.sourceforge.phpeclipse.internal.compiler.ast;
13 import net.sourceforge.phpdt.core.compiler.CharOperation;
14 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
15 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
17 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
18 import net.sourceforge.phpdt.internal.compiler.flow.InitializationFlowContext;
19 import net.sourceforge.phpdt.internal.compiler.flow.UnconditionalFlowInfo;
20 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
21 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
22 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
23 import net.sourceforge.phpdt.internal.compiler.lookup.CompilationUnitScope;
24 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
25 import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding;
26 import net.sourceforge.phpdt.internal.compiler.lookup.MemberTypeBinding;
27 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
28 import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
29 import net.sourceforge.phpdt.internal.compiler.lookup.NestedTypeBinding;
30 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
31 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
32 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
33 import net.sourceforge.phpdt.internal.compiler.parser.Parser;
34 import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
35 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
36 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilationUnit;
37 import net.sourceforge.phpdt.internal.compiler.problem.AbortMethod;
38 import net.sourceforge.phpdt.internal.compiler.problem.AbortType;
39 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
41 public class TypeDeclaration
43 implements ProblemSeverities, ReferenceContext {
46 public int modifiersSourceStart;
48 public TypeReference superclass;
49 public TypeReference[] superInterfaces;
50 public FieldDeclaration[] fields;
51 public AbstractMethodDeclaration[] methods;
52 public MemberTypeDeclaration[] memberTypes;
53 public SourceTypeBinding binding;
54 public ClassScope scope;
55 public MethodScope initializerScope;
56 public MethodScope staticInitializerScope;
57 public boolean ignoreFurtherInvestigation = false;
58 public int maxFieldCount;
59 public int declarationSourceStart;
60 public int declarationSourceEnd;
62 public int bodyEnd; // doesn't include the trailing comment if any.
63 protected boolean hasBeenGenerated = false;
64 public CompilationResult compilationResult;
65 private MethodDeclaration[] missingAbstractMethods;
67 public TypeDeclaration(CompilationResult compilationResult){
68 this.compilationResult = compilationResult;
72 * We cause the compilation task to abort to a given extent.
74 public void abort(int abortLevel) {
77 throw new AbortCompilation(); // cannot do better
80 CompilationResult compilationResult =
81 scope.referenceCompilationUnit().compilationResult;
84 case AbortCompilation :
85 throw new AbortCompilation(compilationResult);
86 case AbortCompilationUnit :
87 throw new AbortCompilationUnit(compilationResult);
89 throw new AbortMethod(compilationResult);
91 throw new AbortType(compilationResult);
95 * This method is responsible for adding a <clinit> method declaration to the type method collections.
96 * Note that this implementation is inserting it in first place (as VAJ or javac), and that this
97 * impacts the behavior of the method ConstantPool.resetForClinit(int. int), in so far as
98 * the latter will have to reset the constant pool state accordingly (if it was added first, it does
99 * not need to preserve some of the method specific cached entries since this will be the first method).
100 * inserts the clinit method declaration in the first position.
102 * @see org.eclipse.jdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int)
104 public final void addClinit() {
106 //see comment on needClassInitMethod
107 if (needClassInitMethod()) {
109 AbstractMethodDeclaration[] methods;
110 if ((methods = this.methods) == null) {
112 methods = new AbstractMethodDeclaration[1];
114 length = methods.length;
118 (methods = new AbstractMethodDeclaration[length + 1]),
122 Clinit clinit = new Clinit(this.compilationResult);
124 // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
125 clinit.declarationSourceStart = clinit.sourceStart = sourceStart;
126 clinit.declarationSourceEnd = clinit.sourceEnd = sourceEnd;
127 clinit.bodyEnd = sourceEnd;
128 this.methods = methods;
133 * Flow analysis for a local innertype
136 public FlowInfo analyseCode(
137 BlockScope currentScope,
138 FlowContext flowContext,
141 if (ignoreFurtherInvestigation)
144 bits |= IsReachableMASK;
145 LocalTypeBinding localType = (LocalTypeBinding) binding;
147 localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
148 manageEnclosingInstanceAccessIfNecessary(currentScope);
150 updateMaxFieldCount(); // propagate down the max field count
151 internalAnalyseCode(flowContext, flowInfo);
152 } catch (AbortType e) {
153 this.ignoreFurtherInvestigation = true;
159 * Flow analysis for a member innertype
162 public void analyseCode(ClassScope enclosingClassScope) {
164 if (ignoreFurtherInvestigation)
167 // propagate down the max field count
168 updateMaxFieldCount();
169 internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
170 } catch (AbortType e) {
171 this.ignoreFurtherInvestigation = true;
176 * Flow analysis for a local member innertype
179 public void analyseCode(
180 ClassScope currentScope,
181 FlowContext flowContext,
184 if (ignoreFurtherInvestigation)
187 bits |= IsReachableMASK;
188 LocalTypeBinding localType = (LocalTypeBinding) binding;
190 localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
191 manageEnclosingInstanceAccessIfNecessary(currentScope);
193 updateMaxFieldCount(); // propagate down the max field count
194 internalAnalyseCode(flowContext, flowInfo);
195 } catch (AbortType e) {
196 this.ignoreFurtherInvestigation = true;
201 * Flow analysis for a package member type
204 public void analyseCode(CompilationUnitScope unitScope) {
206 if (ignoreFurtherInvestigation)
209 internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
210 } catch (AbortType e) {
211 this.ignoreFurtherInvestigation = true;
216 * Check for constructor vs. method with no return type.
217 * Answers true if at least one constructor is defined
219 public boolean checkConstructors(Parser parser) {
221 //if a constructor has not the name of the type,
222 //convert it into a method with 'null' as its return type
223 boolean hasConstructor = false;
224 if (methods != null) {
225 for (int i = methods.length; --i >= 0;) {
226 AbstractMethodDeclaration am;
227 if ((am = methods[i]).isConstructor()) {
228 if (!CharOperation.equals(am.selector, name)) {
229 // the constructor was in fact a method with no return type
230 // unless an explicit constructor call was supplied
231 ConstructorDeclaration c = (ConstructorDeclaration) am;
232 if ((c.constructorCall == null)
233 || (c.constructorCall.isImplicitSuper())) { //changed to a method
234 MethodDeclaration m = new MethodDeclaration(this.compilationResult);
235 m.sourceStart = c.sourceStart;
236 m.sourceEnd = c.sourceEnd;
237 m.bodyStart = c.bodyStart;
238 m.bodyEnd = c.bodyEnd;
239 m.declarationSourceEnd = c.declarationSourceEnd;
240 m.declarationSourceStart = c.declarationSourceStart;
241 m.selector = c.selector;
242 m.statements = c.statements;
243 m.modifiers = c.modifiers;
244 m.arguments = c.arguments;
245 m.thrownExceptions = c.thrownExceptions;
246 m.explicitDeclarations = c.explicitDeclarations;
251 if (this.isInterface()) {
252 // report the problem and continue the parsing
253 parser.problemReporter().interfaceCannotHaveConstructors(
254 (ConstructorDeclaration) am);
256 hasConstructor = true;
261 return hasConstructor;
264 public CompilationResult compilationResult() {
266 return this.compilationResult;
269 public ConstructorDeclaration createsInternalConstructor(
270 boolean needExplicitConstructorCall,
271 boolean needToInsert) {
273 //Add to method'set, the default constuctor that just recall the
274 //super constructor with no arguments
275 //The arguments' type will be positionned by the TC so just use
276 //the default int instead of just null (consistency purpose)
279 ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
280 constructor.isDefaultConstructor = true;
281 constructor.selector = name;
282 if (modifiers != AccDefault) {
283 constructor.modifiers =
284 ((this instanceof MemberTypeDeclaration) && (modifiers & AccPrivate) != 0)
286 : modifiers & AccVisibilityMASK;
289 //if you change this setting, please update the
290 //SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
291 constructor.declarationSourceStart = constructor.sourceStart = sourceStart;
292 constructor.declarationSourceEnd =
293 constructor.sourceEnd = constructor.bodyEnd = sourceEnd;
295 //the super call inside the constructor
296 if (needExplicitConstructorCall) {
297 constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
298 constructor.constructorCall.sourceStart = sourceStart;
299 constructor.constructorCall.sourceEnd = sourceEnd;
302 //adding the constructor in the methods list
304 if (methods == null) {
305 methods = new AbstractMethodDeclaration[] { constructor };
307 AbstractMethodDeclaration[] newMethods;
311 newMethods = new AbstractMethodDeclaration[methods.length + 1],
314 newMethods[0] = constructor;
315 methods = newMethods;
322 * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding.
323 * It is used to report errors for missing abstract methods.
325 public MethodDeclaration addMissingAbstractMethodFor(MethodBinding methodBinding) {
326 TypeBinding[] argumentTypes = methodBinding.parameters;
327 int argumentsLength = argumentTypes.length;
329 MethodDeclaration methodDeclaration = new MethodDeclaration(this.compilationResult);
330 methodDeclaration.selector = methodBinding.selector;
331 methodDeclaration.sourceStart = sourceStart;
332 methodDeclaration.sourceEnd = sourceEnd;
333 methodDeclaration.modifiers = methodBinding.getAccessFlags() & ~AccAbstract;
335 if (argumentsLength > 0) {
336 String baseName = "arg";//$NON-NLS-1$
337 Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]);
338 for (int i = argumentsLength; --i >= 0;) {
339 arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, AccDefault);
343 //adding the constructor in the methods list
344 if (this.missingAbstractMethods == null) {
345 this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
347 MethodDeclaration[] newMethods;
349 this.missingAbstractMethods,
351 newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1],
353 this.missingAbstractMethods.length);
354 newMethods[0] = methodDeclaration;
355 this.missingAbstractMethods = newMethods;
358 //============BINDING UPDATE==========================
359 methodDeclaration.binding = new MethodBinding(
360 methodDeclaration.modifiers, //methodDeclaration
361 methodBinding.selector,
362 methodBinding.returnType,
363 argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
364 methodBinding.thrownExceptions, //exceptions
365 binding); //declaringClass
367 methodDeclaration.scope = new MethodScope(scope, methodDeclaration, true);
368 methodDeclaration.bindArguments();
370 /* if (binding.methods == null) {
371 binding.methods = new MethodBinding[] { methodDeclaration.binding };
373 MethodBinding[] newMethods;
377 newMethods = new MethodBinding[binding.methods.length + 1],
379 binding.methods.length);
380 newMethods[0] = methodDeclaration.binding;
381 binding.methods = newMethods;
383 //===================================================
385 return methodDeclaration;
389 * Find the matching parse node, answers null if nothing found
391 public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
393 if (fieldBinding != null) {
394 for (int i = 0, max = this.fields.length; i < max; i++) {
395 FieldDeclaration fieldDecl;
396 if ((fieldDecl = this.fields[i]).binding == fieldBinding)
404 * Find the matching parse node, answers null if nothing found
406 public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) {
408 if (memberTypeBinding != null) {
409 for (int i = 0, max = this.memberTypes.length; i < max; i++) {
410 TypeDeclaration memberTypeDecl;
411 if ((memberTypeDecl = this.memberTypes[i]).binding == memberTypeBinding)
412 return memberTypeDecl;
419 * Find the matching parse node, answers null if nothing found
421 public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
423 if (methodBinding != null) {
424 for (int i = 0, max = this.methods.length; i < max; i++) {
425 AbstractMethodDeclaration methodDecl;
427 if ((methodDecl = this.methods[i]).binding == methodBinding)
435 * Finds the matching type amoung this type's member types.
436 * Returns null if no type with this name is found.
437 * The type name is a compound name relative to this type
438 * eg. if this type is X and we're looking for Y.X.A.B
439 * then a type name would be {X, A, B}
441 public TypeDeclaration declarationOfType(char[][] typeName) {
443 int typeNameLength = typeName.length;
444 if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) {
447 if (typeNameLength == 1) {
450 char[][] subTypeName = new char[typeNameLength - 1][];
451 System.arraycopy(typeName, 1, subTypeName, 0, typeNameLength - 1);
452 for (int i = 0; i < this.memberTypes.length; i++) {
453 TypeDeclaration typeDecl = this.memberTypes[i].declarationOfType(subTypeName);
454 if (typeDecl != null) {
462 * Generic bytecode generation for type
464 // public void generateCode(ClassFile enclosingClassFile) {
466 // if (hasBeenGenerated)
468 // hasBeenGenerated = true;
469 // if (ignoreFurtherInvestigation) {
470 // if (binding == null)
472 // ClassFile.createProblemType(
474 // scope.referenceCompilationUnit().compilationResult);
478 // // create the result for a compiled type
479 // ClassFile classFile = new ClassFile(binding, enclosingClassFile, false);
480 // // generate all fiels
481 // classFile.addFieldInfos();
483 // // record the inner type inside its own .class file to be able
484 // // to generate inner classes attributes
485 // if (binding.isMemberType())
486 // classFile.recordEnclosingTypeAttributes(binding);
487 // if (binding.isLocalType()) {
488 // enclosingClassFile.recordNestedLocalAttribute(binding);
489 // classFile.recordNestedLocalAttribute(binding);
491 // if (memberTypes != null) {
492 // for (int i = 0, max = memberTypes.length; i < max; i++) {
493 // // record the inner type inside its own .class file to be able
494 // // to generate inner classes attributes
495 // classFile.recordNestedMemberAttribute(memberTypes[i].binding);
496 // memberTypes[i].generateCode(scope, classFile);
499 // // generate all methods
500 // classFile.setForMethodInfos();
501 // if (methods != null) {
502 // for (int i = 0, max = methods.length; i < max; i++) {
503 // methods[i].generateCode(scope, classFile);
507 // classFile.generateMissingAbstractMethods(this.missingAbstractMethods, scope.referenceCompilationUnit().compilationResult);
509 // // generate all methods
510 // classFile.addSpecialMethods();
512 // if (ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
513 // throw new AbortType(scope.referenceCompilationUnit().compilationResult);
516 // // finalize the compiled type result
517 // classFile.addAttributes();
518 // scope.referenceCompilationUnit().compilationResult.record(
519 // binding.constantPoolName(),
521 // } catch (AbortType e) {
522 // if (binding == null)
524 // ClassFile.createProblemType(
526 // scope.referenceCompilationUnit().compilationResult);
531 * Bytecode generation for a local inner type (API as a normal statement code gen)
533 // public void generateCode(BlockScope blockScope, CodeStream codeStream) {
535 // if (hasBeenGenerated) return;
536 // int pc = codeStream.position;
537 // if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
538 // generateCode(codeStream.classFile);
539 // codeStream.recordPositionsFrom(pc, this.sourceStart);
543 * Bytecode generation for a member inner type
545 // public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) {
547 // if (hasBeenGenerated) return;
548 // if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
549 // generateCode(enclosingClassFile);
553 * Bytecode generation for a package member
555 // public void generateCode(CompilationUnitScope unitScope) {
557 // generateCode((ClassFile) null);
560 public boolean hasErrors() {
561 return this.ignoreFurtherInvestigation;
565 * Common flow analysis for all types
568 public void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
570 if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
571 if (!scope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
572 scope.problemReporter().unusedPrivateType(this);
576 ReferenceBinding[] defaultHandledExceptions = new ReferenceBinding[] { scope.getJavaLangThrowable()}; // tolerate any kind of exception
577 InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, initializerScope);
578 InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, staticInitializerScope);
579 FlowInfo nonStaticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
580 FlowInfo staticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
581 if (fields != null) {
582 for (int i = 0, count = fields.length; i < count; i++) {
583 FieldDeclaration field = fields[i];
584 if (field.isStatic()) {
585 /*if (field.isField()){
586 staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
588 staticInitializerContext.handledExceptions = defaultHandledExceptions; // tolerate them all, and record them
592 staticInitializerScope,
593 staticInitializerContext,
595 // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
596 // branch, since the previous initializer already got the blame.
597 if (staticFieldInfo == FlowInfo.DEAD_END) {
598 staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
599 staticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
602 /*if (field.isField()){
603 initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
605 initializerContext.handledExceptions = defaultHandledExceptions; // tolerate them all, and record them
608 field.analyseCode(initializerScope, initializerContext, nonStaticFieldInfo);
609 // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
610 // branch, since the previous initializer already got the blame.
611 if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
612 initializerScope.problemReporter().initializerMustCompleteNormally(field);
613 nonStaticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
618 if (memberTypes != null) {
619 for (int i = 0, count = memberTypes.length; i < count; i++) {
620 if (flowContext != null){ // local type
621 memberTypes[i].analyseCode(scope, flowContext, nonStaticFieldInfo.copy());
623 memberTypes[i].analyseCode(scope);
627 if (methods != null) {
628 UnconditionalFlowInfo outerInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
629 FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo);
630 for (int i = 0, count = methods.length; i < count; i++) {
631 AbstractMethodDeclaration method = methods[i];
632 if (method.ignoreFurtherInvestigation)
634 if (method.isInitializationMethod()) {
635 if (method.isStatic()) { // <clinit>
638 staticInitializerContext,
639 staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo));
640 } else { // constructor
641 method.analyseCode(scope, initializerContext, constructorInfo.copy());
643 } else { // regular method
644 method.analyseCode(scope, null, flowInfo.copy());
650 public boolean isInterface() {
652 return (modifiers & AccInterface) != 0;
656 * Access emulation for a local type
657 * force to emulation of access to direct enclosing instance.
658 * By using the initializer scope, we actually only request an argument emulation, the
659 * field is not added until actually used. However we will force allocations to be qualified
660 * with an enclosing instance.
663 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
665 NestedTypeBinding nestedType = (NestedTypeBinding) binding;
667 MethodScope methodScope = currentScope.methodScope();
668 if (!methodScope.isStatic && !methodScope.isConstructorCall){
670 nestedType.addSyntheticArgumentAndField(binding.enclosingType());
672 // add superclass enclosing instance arg for anonymous types (if necessary)
673 if (binding.isAnonymousType()) {
674 ReferenceBinding superclass = binding.superclass;
675 if (superclass.enclosingType() != null && !superclass.isStatic()) {
676 if (!binding.superclass.isLocalType()
677 || ((NestedTypeBinding)binding.superclass).getSyntheticField(superclass.enclosingType(), true) != null){
679 nestedType.addSyntheticArgument(superclass.enclosingType());
686 * Access emulation for a local member type
687 * force to emulation of access to direct enclosing instance.
688 * By using the initializer scope, we actually only request an argument emulation, the
689 * field is not added until actually used. However we will force allocations to be qualified
690 * with an enclosing instance.
692 * Local member cannot be static.
694 public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope) {
696 NestedTypeBinding nestedType = (NestedTypeBinding) binding;
697 nestedType.addSyntheticArgumentAndField(binding.enclosingType());
701 * A <clinit> will be requested as soon as static fields or assertions are present. It will be eliminated during
702 * classfile creation if no bytecode was actually produced based on some optimizations/compiler settings.
704 public final boolean needClassInitMethod() {
706 // always need a <clinit> when assertions are present
707 if ((this.bits & AddAssertionMASK) != 0)
712 return true; // fields are implicitly statics
713 for (int i = fields.length; --i >= 0;) {
714 FieldDeclaration field = fields[i];
715 //need to test the modifier directly while there is no binding yet
716 if ((field.modifiers & AccStatic) != 0)
722 public void parseMethod(UnitParser parser, CompilationUnitDeclaration unit) {
724 //connect method bodies
725 if (unit.ignoreMethodBodies)
728 // no scope were created, so cannot report further errors
729 // if (binding == null)
733 if (memberTypes != null) {
734 int length = memberTypes.length;
735 for (int i = 0; i < length; i++)
736 memberTypes[i].parseMethod(parser, unit);
740 if (methods != null) {
741 int length = methods.length;
742 for (int i = 0; i < length; i++)
743 methods[i].parseStatements(parser, unit);
747 if (fields != null) {
748 int length = fields.length;
749 for (int i = 0; i < length; i++) {
750 if (fields[i] instanceof Initializer) {
751 ((Initializer) fields[i]).parseStatements(parser, this, unit);
757 public void resolve() {
759 if (binding == null) {
760 ignoreFurtherInvestigation = true;
765 // check superclass & interfaces
766 if (binding.superclass != null) // watch out for Object ! (and other roots)
767 if (isTypeUseDeprecated(binding.superclass, scope))
768 scope.problemReporter().deprecatedType(binding.superclass, superclass);
769 if (superInterfaces != null)
770 for (int i = superInterfaces.length; --i >= 0;)
771 if (superInterfaces[i].resolvedType != null)
772 if (isTypeUseDeprecated(superInterfaces[i].resolvedType, scope))
773 scope.problemReporter().deprecatedType(
774 superInterfaces[i].resolvedType,
777 int lastFieldID = -1;
778 if (fields != null) {
779 for (int i = 0, count = fields.length; i < count; i++) {
780 FieldDeclaration field = fields[i];
781 if (field.isField()) {
782 if (field.binding == null) {
783 // still discover secondary errors
784 if (field.initialization != null) field.initialization.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
785 ignoreFurtherInvestigation = true;
789 lastFieldID = field.binding.id;
790 } else { // initializer
791 ((Initializer) field).lastFieldID = lastFieldID + 1;
793 field.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
796 if (memberTypes != null) {
797 for (int i = 0, count = memberTypes.length; i < count; i++) {
798 memberTypes[i].resolve(scope);
801 int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
802 int methodsLength = this.methods == null ? 0 : methods.length;
803 if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) {
804 scope.problemReporter().tooManyMethods(this);
807 if (methods != null) {
808 for (int i = 0, count = methods.length; i < count; i++) {
809 methods[i].resolve(scope);
812 } catch (AbortType e) {
813 this.ignoreFurtherInvestigation = true;
818 public void resolve(BlockScope blockScope) {
819 // local type declaration
821 // need to build its scope first and proceed with binding's creation
822 blockScope.addLocalType(this);
825 if (binding != null) {
826 // remember local types binding for innerclass emulation propagation
827 blockScope.referenceCompilationUnit().record((LocalTypeBinding)binding);
829 // binding is not set if the receiver could not be created
831 updateMaxFieldCount();
835 public void resolve(ClassScope upperScope) {
836 // member scopes are already created
837 // request the construction of a binding if local member type
839 if (binding != null && binding instanceof LocalTypeBinding) {
840 // remember local types binding for innerclass emulation propagation
841 upperScope.referenceCompilationUnit().record((LocalTypeBinding)binding);
844 updateMaxFieldCount();
847 public void resolve(CompilationUnitScope upperScope) {
848 // top level : scope are already created
851 updateMaxFieldCount();
854 public void tagAsHavingErrors() {
855 ignoreFurtherInvestigation = true;
858 public String toString(int tab) {
860 return tabString(tab) + toStringHeader() + toStringBody(tab);
863 public String toStringBody(int tab) {
865 String s = " {"; //$NON-NLS-1$
866 if (memberTypes != null) {
867 for (int i = 0; i < memberTypes.length; i++) {
868 if (memberTypes[i] != null) {
869 s += "\n" + memberTypes[i].toString(tab + 1); //$NON-NLS-1$
873 if (fields != null) {
874 for (int fieldI = 0; fieldI < fields.length; fieldI++) {
875 if (fields[fieldI] != null) {
876 s += "\n" + fields[fieldI].toString(tab + 1); //$NON-NLS-1$
877 if (fields[fieldI].isField())
878 s += ";"; //$NON-NLS-1$
882 if (methods != null) {
883 for (int i = 0; i < methods.length; i++) {
884 if (methods[i] != null) {
885 s += "\n" + methods[i].toString(tab + 1); //$NON-NLS-1$
889 s += "\n" + tabString(tab) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
893 public String toStringHeader() {
895 String s = ""; //$NON-NLS-1$
896 if (modifiers != AccDefault) {
897 s += modifiersString(modifiers);
899 s += (isInterface() ? "interface " : "class ") + new String(name);//$NON-NLS-1$ //$NON-NLS-2$
900 if (superclass != null)
901 s += " extends " + superclass.toString(0); //$NON-NLS-1$
902 if (superInterfaces != null && superInterfaces.length > 0) {
903 s += (isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
904 for (int i = 0; i < superInterfaces.length; i++) {
905 s += superInterfaces[i].toString(0);
906 if (i != superInterfaces.length - 1)
907 s += ", "; //$NON-NLS-1$
914 * Iteration for a package member type
917 public void traverse(
918 IAbstractSyntaxTreeVisitor visitor,
919 CompilationUnitScope unitScope) {
921 if (ignoreFurtherInvestigation)
924 if (visitor.visit(this, unitScope)) {
925 if (superclass != null)
926 superclass.traverse(visitor, scope);
927 if (superInterfaces != null) {
928 int superInterfaceLength = superInterfaces.length;
929 for (int i = 0; i < superInterfaceLength; i++)
930 superInterfaces[i].traverse(visitor, scope);
932 if (memberTypes != null) {
933 int memberTypesLength = memberTypes.length;
934 for (int i = 0; i < memberTypesLength; i++)
935 memberTypes[i].traverse(visitor, scope);
937 if (fields != null) {
938 int fieldsLength = fields.length;
939 for (int i = 0; i < fieldsLength; i++) {
940 FieldDeclaration field;
941 if ((field = fields[i]).isStatic()) {
942 field.traverse(visitor, staticInitializerScope);
944 field.traverse(visitor, initializerScope);
948 if (methods != null) {
949 int methodsLength = methods.length;
950 for (int i = 0; i < methodsLength; i++)
951 methods[i].traverse(visitor, scope);
954 visitor.endVisit(this, unitScope);
955 } catch (AbortType e) {
960 * MaxFieldCount's computation is necessary so as to reserve space for
961 * the flow info field portions. It corresponds to the maximum amount of
962 * fields this class or one of its innertypes have.
964 * During name resolution, types are traversed, and the max field count is recorded
965 * on the outermost type. It is then propagated down during the flow analysis.
967 * This method is doing either up/down propagation.
969 void updateMaxFieldCount() {
972 return; // error scenario
973 TypeDeclaration outerMostType = scope.outerMostClassScope().referenceType();
974 if (maxFieldCount > outerMostType.maxFieldCount) {
975 outerMostType.maxFieldCount = maxFieldCount; // up
977 maxFieldCount = outerMostType.maxFieldCount; // down