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.phpeclipse.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, ReferenceContext {
42 public int modifiersSourceStart;
46 public TypeReference superclass;
48 public TypeReference[] superInterfaces;
50 public FieldDeclaration[] fields;
52 public AbstractMethodDeclaration[] methods;
54 public TypeDeclaration[] memberTypes;
56 public SourceTypeBinding binding;
58 public ClassScope scope;
60 public MethodScope initializerScope;
62 public MethodScope staticInitializerScope;
64 public boolean ignoreFurtherInvestigation = false;
66 public int maxFieldCount;
68 public int declarationSourceStart;
70 public int declarationSourceEnd;
74 public int bodyEnd; // doesn't include the trailing comment if any.
76 protected boolean hasBeenGenerated = false;
78 public CompilationResult compilationResult;
80 private MethodDeclaration[] missingAbstractMethods;
82 public TypeDeclaration(CompilationResult compilationResult) {
83 this.compilationResult = compilationResult;
87 * We cause the compilation task to abort to a given extent.
89 public void abort(int abortLevel) {
92 throw new AbortCompilation(); // cannot do better
95 CompilationResult compilationResult = scope.referenceCompilationUnit().compilationResult;
98 case AbortCompilation:
99 throw new AbortCompilation(compilationResult);
100 case AbortCompilationUnit:
101 throw new AbortCompilationUnit(compilationResult);
103 throw new AbortMethod(compilationResult);
105 throw new AbortType(compilationResult);
110 * This method is responsible for adding a <clinit>method declaration to the type method collections. Note that this
111 * implementation is inserting it in first place (as VAJ or javac), and that this impacts the behavior of the method
112 * ConstantPool.resetForClinit(int. int), in so far as the latter will have to reset the constant pool state accordingly (if it
113 * was added first, it does not need to preserve some of the method specific cached entries since this will be the first method).
114 * inserts the clinit method declaration in the first position.
116 * @see net.sourceforge.phpdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int)
118 public final void addClinit() {
120 //see comment on needClassInitMethod
121 if (needClassInitMethod()) {
123 AbstractMethodDeclaration[] methods;
124 if ((methods = this.methods) == null) {
126 methods = new AbstractMethodDeclaration[1];
128 length = methods.length;
129 System.arraycopy(methods, 0, (methods = new AbstractMethodDeclaration[length + 1]), 1, length);
131 Clinit clinit = new Clinit(this.compilationResult);
133 // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
134 clinit.declarationSourceStart = clinit.sourceStart = sourceStart;
135 clinit.declarationSourceEnd = clinit.sourceEnd = sourceEnd;
136 clinit.bodyEnd = sourceEnd;
137 this.methods = methods;
142 * Flow analysis for a local innertype
145 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
147 if (ignoreFurtherInvestigation)
150 bits |= IsReachableMASK;
151 LocalTypeBinding localType = (LocalTypeBinding) binding;
153 localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
154 manageEnclosingInstanceAccessIfNecessary(currentScope);
156 updateMaxFieldCount(); // propagate down the max field count
157 internalAnalyseCode(flowContext, flowInfo);
158 } catch (AbortType e) {
159 this.ignoreFurtherInvestigation = true;
165 * Flow analysis for a member innertype
168 public void analyseCode(ClassScope enclosingClassScope) {
170 if (ignoreFurtherInvestigation)
173 // propagate down the max field count
174 updateMaxFieldCount();
175 internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
176 } catch (AbortType e) {
177 this.ignoreFurtherInvestigation = true;
182 * Flow analysis for a local member innertype
185 public void analyseCode(ClassScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
187 if (ignoreFurtherInvestigation)
190 bits |= IsReachableMASK;
191 LocalTypeBinding localType = (LocalTypeBinding) binding;
193 localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
194 manageEnclosingInstanceAccessIfNecessary(currentScope);
196 updateMaxFieldCount(); // propagate down the max field count
197 internalAnalyseCode(flowContext, flowInfo);
198 } catch (AbortType e) {
199 this.ignoreFurtherInvestigation = true;
204 * Flow analysis for a package member type
207 public void analyseCode(CompilationUnitScope unitScope) {
209 if (ignoreFurtherInvestigation)
212 internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
213 } catch (AbortType e) {
214 this.ignoreFurtherInvestigation = true;
219 * Check for constructor vs. method with no return type. Answers true if at least one constructor is defined
221 public boolean checkConstructors(Parser parser) {
223 //if a constructor has not the name of the type,
224 //convert it into a method with 'null' as its return type
225 boolean hasConstructor = false;
226 if (methods != null) {
227 for (int i = methods.length; --i >= 0;) {
228 AbstractMethodDeclaration am;
229 if ((am = methods[i]).isConstructor()) {
230 if (!CharOperation.equals(am.selector, name)) {
231 // the constructor was in fact a method with no return type
232 // unless an explicit constructor call was supplied
233 ConstructorDeclaration c = (ConstructorDeclaration) am;
234 if ((c.constructorCall == null) || (c.constructorCall.isImplicitSuper())) { //changed to a method
235 MethodDeclaration m = new MethodDeclaration(this.compilationResult);
236 m.sourceStart = c.sourceStart;
237 m.sourceEnd = c.sourceEnd;
238 m.bodyStart = c.bodyStart;
239 m.bodyEnd = c.bodyEnd;
240 m.declarationSourceEnd = c.declarationSourceEnd;
241 m.declarationSourceStart = c.declarationSourceStart;
242 m.selector = c.selector;
243 m.statements = c.statements;
244 m.modifiers = c.modifiers;
245 m.arguments = c.arguments;
246 m.thrownExceptions = c.thrownExceptions;
247 m.explicitDeclarations = c.explicitDeclarations;
252 if (this.isInterface()) {
253 // report the problem and continue the parsing
254 parser.problemReporter().interfaceCannotHaveConstructors((ConstructorDeclaration) am);
256 hasConstructor = true;
261 return hasConstructor;
264 public CompilationResult compilationResult() {
266 return this.compilationResult;
269 public ConstructorDeclaration createsInternalConstructor(boolean needExplicitConstructorCall, boolean needToInsert) {
271 //Add to method'set, the default constuctor that just recall the
272 //super constructor with no arguments
273 //The arguments' type will be positionned by the TC so just use
274 //the default int instead of just null (consistency purpose)
277 ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
278 constructor.isDefaultConstructor = true;
279 constructor.selector = name;
280 if (modifiers != AccDefault) {
281 constructor.modifiers = ((this instanceof MemberTypeDeclaration) && (modifiers & AccPrivate) != 0) ? AccDefault : modifiers
285 //if you change this setting, please update the
286 //SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
287 constructor.declarationSourceStart = constructor.sourceStart = sourceStart;
288 constructor.declarationSourceEnd = constructor.sourceEnd = constructor.bodyEnd = sourceEnd;
290 //the super call inside the constructor
291 if (needExplicitConstructorCall) {
292 constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
293 constructor.constructorCall.sourceStart = sourceStart;
294 constructor.constructorCall.sourceEnd = sourceEnd;
297 //adding the constructor in the methods list
299 if (methods == null) {
300 methods = new AbstractMethodDeclaration[] { constructor };
302 AbstractMethodDeclaration[] newMethods;
303 System.arraycopy(methods, 0, newMethods = new AbstractMethodDeclaration[methods.length + 1], 1, methods.length);
304 newMethods[0] = constructor;
305 methods = newMethods;
312 * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding. It is used to report errors for missing
315 public MethodDeclaration addMissingAbstractMethodFor(MethodBinding methodBinding) {
316 TypeBinding[] argumentTypes = methodBinding.parameters;
317 int argumentsLength = argumentTypes.length;
319 MethodDeclaration methodDeclaration = new MethodDeclaration(this.compilationResult);
320 methodDeclaration.selector = methodBinding.selector;
321 methodDeclaration.sourceStart = sourceStart;
322 methodDeclaration.sourceEnd = sourceEnd;
323 methodDeclaration.modifiers = methodBinding.getAccessFlags() & ~AccAbstract;
325 if (argumentsLength > 0) {
326 String baseName = "arg";//$NON-NLS-1$
327 Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]);
328 for (int i = argumentsLength; --i >= 0;) {
329 arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /* type ref */, AccDefault);
333 //adding the constructor in the methods list
334 if (this.missingAbstractMethods == null) {
335 this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
337 MethodDeclaration[] newMethods;
338 System.arraycopy(this.missingAbstractMethods, 0, newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1],
339 1, this.missingAbstractMethods.length);
340 newMethods[0] = methodDeclaration;
341 this.missingAbstractMethods = newMethods;
344 //============BINDING UPDATE==========================
345 methodDeclaration.binding = new MethodBinding(methodDeclaration.modifiers, //methodDeclaration
346 methodBinding.selector, methodBinding.returnType, argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
347 methodBinding.thrownExceptions, //exceptions
348 binding); //declaringClass
350 methodDeclaration.scope = new MethodScope(scope, methodDeclaration, true);
351 methodDeclaration.bindArguments();
354 * if (binding.methods == null) { binding.methods = new MethodBinding[] { methodDeclaration.binding }; } else { MethodBinding[]
355 * newMethods; System.arraycopy( binding.methods, 0, newMethods = new MethodBinding[binding.methods.length + 1], 1,
356 * binding.methods.length); newMethods[0] = methodDeclaration.binding; binding.methods = newMethods; }
358 //===================================================
359 return methodDeclaration;
363 * Find the matching parse node, answers null if nothing found
365 public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
367 if (fieldBinding != null) {
368 for (int i = 0, max = this.fields.length; i < max; i++) {
369 FieldDeclaration fieldDecl;
370 if ((fieldDecl = this.fields[i]).binding == fieldBinding)
378 * Find the matching parse node, answers null if nothing found
380 public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) {
382 if (memberTypeBinding != null) {
383 for (int i = 0, max = this.memberTypes.length; i < max; i++) {
384 TypeDeclaration memberTypeDecl;
385 if ((memberTypeDecl = this.memberTypes[i]).binding == memberTypeBinding)
386 return memberTypeDecl;
393 * Find the matching parse node, answers null if nothing found
395 public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
397 if (methodBinding != null) {
398 for (int i = 0, max = this.methods.length; i < max; i++) {
399 AbstractMethodDeclaration methodDecl;
401 if ((methodDecl = this.methods[i]).binding == methodBinding)
409 * Finds the matching type amoung this type's member types. Returns null if no type with this name is found. The type name is a
410 * compound name relative to this type eg. if this type is X and we're looking for Y.X.A.B then a type name would be {X, A, B}
412 public TypeDeclaration declarationOfType(char[][] typeName) {
414 int typeNameLength = typeName.length;
415 if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) {
418 if (typeNameLength == 1) {
421 char[][] subTypeName = new char[typeNameLength - 1][];
422 System.arraycopy(typeName, 1, subTypeName, 0, typeNameLength - 1);
423 for (int i = 0; i < this.memberTypes.length; i++) {
424 TypeDeclaration typeDecl = this.memberTypes[i].declarationOfType(subTypeName);
425 if (typeDecl != null) {
433 * Generic bytecode generation for type
435 // public void generateCode(ClassFile enclosingClassFile) {
437 // if (hasBeenGenerated)
439 // hasBeenGenerated = true;
440 // if (ignoreFurtherInvestigation) {
441 // if (binding == null)
443 // ClassFile.createProblemType(
445 // scope.referenceCompilationUnit().compilationResult);
449 // // create the result for a compiled type
450 // ClassFile classFile = new ClassFile(binding, enclosingClassFile, false);
451 // // generate all fiels
452 // classFile.addFieldInfos();
454 // // record the inner type inside its own .class file to be able
455 // // to generate inner classes attributes
456 // if (binding.isMemberType())
457 // classFile.recordEnclosingTypeAttributes(binding);
458 // if (binding.isLocalType()) {
459 // enclosingClassFile.recordNestedLocalAttribute(binding);
460 // classFile.recordNestedLocalAttribute(binding);
462 // if (memberTypes != null) {
463 // for (int i = 0, max = memberTypes.length; i < max; i++) {
464 // // record the inner type inside its own .class file to be able
465 // // to generate inner classes attributes
466 // classFile.recordNestedMemberAttribute(memberTypes[i].binding);
467 // memberTypes[i].generateCode(scope, classFile);
470 // // generate all methods
471 // classFile.setForMethodInfos();
472 // if (methods != null) {
473 // for (int i = 0, max = methods.length; i < max; i++) {
474 // methods[i].generateCode(scope, classFile);
478 // classFile.generateMissingAbstractMethods(this.missingAbstractMethods, scope.referenceCompilationUnit().compilationResult);
480 // // generate all methods
481 // classFile.addSpecialMethods();
483 // if (ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
484 // throw new AbortType(scope.referenceCompilationUnit().compilationResult);
487 // // finalize the compiled type result
488 // classFile.addAttributes();
489 // scope.referenceCompilationUnit().compilationResult.record(
490 // binding.constantPoolName(),
492 // } catch (AbortType e) {
493 // if (binding == null)
495 // ClassFile.createProblemType(
497 // scope.referenceCompilationUnit().compilationResult);
501 * Bytecode generation for a local inner type (API as a normal statement code gen)
503 // public void generateCode(BlockScope blockScope, CodeStream codeStream) {
505 // if (hasBeenGenerated) return;
506 // int pc = codeStream.position;
507 // if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
508 // generateCode(codeStream.classFile);
509 // codeStream.recordPositionsFrom(pc, this.sourceStart);
512 * Bytecode generation for a member inner type
514 // public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) {
516 // if (hasBeenGenerated) return;
517 // if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
518 // generateCode(enclosingClassFile);
521 * Bytecode generation for a package member
523 // public void generateCode(CompilationUnitScope unitScope) {
525 // generateCode((ClassFile) null);
527 public boolean hasErrors() {
528 return this.ignoreFurtherInvestigation;
532 * Common flow analysis for all types
535 public void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
537 if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
538 if (!scope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
539 scope.problemReporter().unusedPrivateType(this);
543 ReferenceBinding[] defaultHandledExceptions = new ReferenceBinding[] { scope.getJavaLangThrowable() }; // tolerate any kind of
545 InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, initializerScope);
546 InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, staticInitializerScope);
547 FlowInfo nonStaticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
548 FlowInfo staticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
549 if (fields != null) {
550 for (int i = 0, count = fields.length; i < count; i++) {
551 FieldDeclaration field = fields[i];
552 if (field.isStatic()) {
554 * if (field.isField()){ staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2 }
557 staticInitializerContext.handledExceptions = defaultHandledExceptions; // tolerate them all, and record them
559 staticFieldInfo = field.analyseCode(staticInitializerScope, staticInitializerContext, staticFieldInfo);
560 // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
561 // branch, since the previous initializer already got the blame.
562 if (staticFieldInfo == FlowInfo.DEAD_END) {
563 staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
564 staticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
568 * if (field.isField()){ initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2 } else {
570 initializerContext.handledExceptions = defaultHandledExceptions; // tolerate them all, and record them
572 nonStaticFieldInfo = field.analyseCode(initializerScope, initializerContext, nonStaticFieldInfo);
573 // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
574 // branch, since the previous initializer already got the blame.
575 if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
576 initializerScope.problemReporter().initializerMustCompleteNormally(field);
577 nonStaticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
582 if (memberTypes != null) {
583 for (int i = 0, count = memberTypes.length; i < count; i++) {
584 if (flowContext != null) { // local type
585 memberTypes[i].analyseCode(scope, flowContext, nonStaticFieldInfo.copy());
587 memberTypes[i].analyseCode(scope);
591 if (methods != null) {
592 UnconditionalFlowInfo outerInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
593 FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(
595 for (int i = 0, count = methods.length; i < count; i++) {
596 AbstractMethodDeclaration method = methods[i];
597 if (method.ignoreFurtherInvestigation)
599 if (method.isInitializationMethod()) {
600 if (method.isStatic()) { // <clinit>
601 method.analyseCode(scope, staticInitializerContext, staticFieldInfo.unconditionalInits()
602 .discardNonFieldInitializations().addInitializationsFrom(outerInfo));
603 } else { // constructor
604 method.analyseCode(scope, initializerContext, constructorInfo.copy());
606 } else { // regular method
607 method.analyseCode(scope, null, flowInfo.copy());
613 public boolean isInterface() {
615 return (modifiers & AccInterface) != 0;
619 * Access emulation for a local type force to emulation of access to direct enclosing instance. By using the initializer scope, we
620 * actually only request an argument emulation, the field is not added until actually used. However we will force allocations to
621 * be qualified with an enclosing instance. 15.9.2
623 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
625 NestedTypeBinding nestedType = (NestedTypeBinding) binding;
627 MethodScope methodScope = currentScope.methodScope();
628 if (!methodScope.isStatic && !methodScope.isConstructorCall) {
630 nestedType.addSyntheticArgumentAndField(binding.enclosingType());
632 // add superclass enclosing instance arg for anonymous types (if necessary)
633 if (binding.isAnonymousType()) {
634 ReferenceBinding superclass = binding.superclass;
635 if (superclass.enclosingType() != null && !superclass.isStatic()) {
636 if (!binding.superclass.isLocalType()
637 || ((NestedTypeBinding) binding.superclass).getSyntheticField(superclass.enclosingType(), true) != null) {
639 nestedType.addSyntheticArgument(superclass.enclosingType());
646 * Access emulation for a local member type force to emulation of access to direct enclosing instance. By using the initializer
647 * scope, we actually only request an argument emulation, the field is not added until actually used. However we will force
648 * allocations to be qualified with an enclosing instance.
650 * Local member cannot be static.
652 public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope) {
654 NestedTypeBinding nestedType = (NestedTypeBinding) binding;
655 nestedType.addSyntheticArgumentAndField(binding.enclosingType());
659 * A <clinit>will be requested as soon as static fields or assertions are present. It will be eliminated during classfile creation
660 * if no bytecode was actually produced based on some optimizations/compiler settings.
662 public final boolean needClassInitMethod() {
664 // always need a <clinit> when assertions are present
665 if ((this.bits & AddAssertionMASK) != 0)
670 return true; // fields are implicitly statics
671 for (int i = fields.length; --i >= 0;) {
672 FieldDeclaration field = fields[i];
673 //need to test the modifier directly while there is no binding yet
674 if ((field.modifiers & AccStatic) != 0)
680 public void parseMethod(UnitParser parser, CompilationUnitDeclaration unit) {
682 //connect method bodies
683 if (unit.ignoreMethodBodies)
686 // no scope were created, so cannot report further errors
687 // if (binding == null)
691 if (memberTypes != null) {
692 int length = memberTypes.length;
693 for (int i = 0; i < length; i++)
694 memberTypes[i].parseMethod(parser, unit);
698 if (methods != null) {
699 int length = methods.length;
700 for (int i = 0; i < length; i++)
701 methods[i].parseStatements(parser, unit);
705 if (fields != null) {
706 int length = fields.length;
707 for (int i = 0; i < length; i++) {
708 if (fields[i] instanceof Initializer) {
709 ((Initializer) fields[i]).parseStatements(parser, this, unit);
715 public void resolve() {
717 if (binding == null) {
718 ignoreFurtherInvestigation = true;
723 // check superclass & interfaces
724 if (binding.superclass != null) // watch out for Object ! (and other roots)
725 if (isTypeUseDeprecated(binding.superclass, scope))
726 scope.problemReporter().deprecatedType(binding.superclass, superclass);
727 if (superInterfaces != null)
728 for (int i = superInterfaces.length; --i >= 0;)
729 if (superInterfaces[i].resolvedType != null)
730 if (isTypeUseDeprecated(superInterfaces[i].resolvedType, scope))
731 scope.problemReporter().deprecatedType(superInterfaces[i].resolvedType, superInterfaces[i]);
733 int lastFieldID = -1;
734 if (fields != null) {
735 for (int i = 0, count = fields.length; i < count; i++) {
736 FieldDeclaration field = fields[i];
737 if (field.isField()) {
738 if (field.binding == null) {
739 // still discover secondary errors
740 if (field.initialization != null)
741 field.initialization.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
742 ignoreFurtherInvestigation = true;
746 lastFieldID = field.binding.id;
747 } else { // initializer
748 ((Initializer) field).lastFieldID = lastFieldID + 1;
750 field.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
753 if (memberTypes != null) {
754 for (int i = 0, count = memberTypes.length; i < count; i++) {
755 memberTypes[i].resolve(scope);
758 int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
759 int methodsLength = this.methods == null ? 0 : methods.length;
760 if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) {
761 scope.problemReporter().tooManyMethods(this);
764 if (methods != null) {
765 for (int i = 0, count = methods.length; i < count; i++) {
766 methods[i].resolve(scope);
769 } catch (AbortType e) {
770 this.ignoreFurtherInvestigation = true;
776 public void resolve(BlockScope blockScope) {
777 // local type declaration
779 // need to build its scope first and proceed with binding's creation
780 blockScope.addLocalType(this);
783 if (binding != null) {
784 // remember local types binding for innerclass emulation propagation
785 blockScope.referenceCompilationUnit().record((LocalTypeBinding) binding);
787 // binding is not set if the receiver could not be created
789 updateMaxFieldCount();
793 public void resolve(ClassScope upperScope) {
794 // member scopes are already created
795 // request the construction of a binding if local member type
797 if (binding != null && binding instanceof LocalTypeBinding) {
798 // remember local types binding for innerclass emulation propagation
799 upperScope.referenceCompilationUnit().record((LocalTypeBinding) binding);
802 updateMaxFieldCount();
805 public void resolve(CompilationUnitScope upperScope) {
806 // top level : scope are already created
809 updateMaxFieldCount();
812 public void tagAsHavingErrors() {
813 ignoreFurtherInvestigation = true;
816 public StringBuffer print(int indent, StringBuffer output) {
818 // if ((this.bits & IsAnonymousTypeMASK) == 0) {
819 printIndent(indent, output);
820 printHeader(0, output);
822 return printBody(indent, output);
825 public StringBuffer printBody(int indent, StringBuffer output) {
827 output.append(" {"); //$NON-NLS-1$
828 if (memberTypes != null) {
829 for (int i = 0; i < memberTypes.length; i++) {
830 if (memberTypes[i] != null) {
832 memberTypes[i].print(indent + 1, output);
836 if (fields != null) {
837 for (int fieldI = 0; fieldI < fields.length; fieldI++) {
838 if (fields[fieldI] != null) {
840 fields[fieldI].print(indent + 1, output);
844 if (methods != null) {
845 for (int i = 0; i < methods.length; i++) {
846 if (methods[i] != null) {
848 methods[i].print(indent + 1, output);
853 return printIndent(indent, output).append('}');
856 public StringBuffer printHeader(int indent, StringBuffer output) {
858 printModifiers(this.modifiers, output);
859 output.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
861 if (superclass != null) {
862 output.append(" extends "); //$NON-NLS-1$
863 superclass.print(0, output);
865 if (superInterfaces != null && superInterfaces.length > 0) {
866 output.append(isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
867 for (int i = 0; i < superInterfaces.length; i++) {
869 output.append(", "); //$NON-NLS-1$
870 superInterfaces[i].print(0, output);
876 public StringBuffer printStatement(int tab, StringBuffer output) {
877 return print(tab, output);
880 public String toString(int tab) {
882 return tabString(tab) + toStringHeader() + toStringBody(tab);
885 public String toStringBody(int tab) {
887 String s = " {"; //$NON-NLS-1$
888 if (memberTypes != null) {
889 for (int i = 0; i < memberTypes.length; i++) {
890 if (memberTypes[i] != null) {
891 s += "\n" + memberTypes[i].toString(tab + 1); //$NON-NLS-1$
895 if (fields != null) {
896 for (int fieldI = 0; fieldI < fields.length; fieldI++) {
897 if (fields[fieldI] != null) {
898 s += "\n" + fields[fieldI].toString(tab + 1); //$NON-NLS-1$
899 if (fields[fieldI].isField())
900 s += ";"; //$NON-NLS-1$
904 if (methods != null) {
905 for (int i = 0; i < methods.length; i++) {
906 if (methods[i] != null) {
907 s += "\n" + methods[i].toString(tab + 1); //$NON-NLS-1$
911 s += "\n" + tabString(tab) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
915 public String toStringHeader() {
917 String s = ""; //$NON-NLS-1$
918 if (modifiers != AccDefault) {
919 s += modifiersString(modifiers);
921 s += (isInterface() ? "interface " : "class ") + new String(name);//$NON-NLS-1$ //$NON-NLS-2$
922 if (superclass != null)
923 s += " extends " + superclass.toString(0); //$NON-NLS-1$
924 if (superInterfaces != null && superInterfaces.length > 0) {
925 s += (isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
926 for (int i = 0; i < superInterfaces.length; i++) {
927 s += superInterfaces[i].toString(0);
928 if (i != superInterfaces.length - 1)
929 s += ", "; //$NON-NLS-1$
938 * Iteration for a local innertype
941 public void traverse(ASTVisitor visitor, BlockScope blockScope) {
942 if (ignoreFurtherInvestigation)
945 if (visitor.visit(this, blockScope)) {
946 if (superclass != null)
947 superclass.traverse(visitor, scope);
948 if (superInterfaces != null) {
949 int superInterfaceLength = superInterfaces.length;
950 for (int i = 0; i < superInterfaceLength; i++)
951 superInterfaces[i].traverse(visitor, scope);
953 if (memberTypes != null) {
954 int memberTypesLength = memberTypes.length;
955 for (int i = 0; i < memberTypesLength; i++)
956 memberTypes[i].traverse(visitor, scope);
958 if (fields != null) {
959 int fieldsLength = fields.length;
960 for (int i = 0; i < fieldsLength; i++) {
961 FieldDeclaration field;
962 if ((field = fields[i]).isStatic()) {
963 // local type cannot have static fields
965 field.traverse(visitor, initializerScope);
969 if (methods != null) {
970 int methodsLength = methods.length;
971 for (int i = 0; i < methodsLength; i++)
972 methods[i].traverse(visitor, scope);
975 visitor.endVisit(this, blockScope);
976 } catch (AbortType e) {
982 * Iteration for a member innertype
985 public void traverse(ASTVisitor visitor, ClassScope classScope) {
986 if (ignoreFurtherInvestigation)
989 if (visitor.visit(this, classScope)) {
990 if (superclass != null)
991 superclass.traverse(visitor, scope);
992 if (superInterfaces != null) {
993 int superInterfaceLength = superInterfaces.length;
994 for (int i = 0; i < superInterfaceLength; i++)
995 superInterfaces[i].traverse(visitor, scope);
997 if (memberTypes != null) {
998 int memberTypesLength = memberTypes.length;
999 for (int i = 0; i < memberTypesLength; i++)
1000 memberTypes[i].traverse(visitor, scope);
1002 if (fields != null) {
1003 int fieldsLength = fields.length;
1004 for (int i = 0; i < fieldsLength; i++) {
1005 FieldDeclaration field;
1006 if ((field = fields[i]).isStatic()) {
1007 field.traverse(visitor, staticInitializerScope);
1009 field.traverse(visitor, initializerScope);
1013 if (methods != null) {
1014 int methodsLength = methods.length;
1015 for (int i = 0; i < methodsLength; i++)
1016 methods[i].traverse(visitor, scope);
1019 visitor.endVisit(this, classScope);
1020 } catch (AbortType e) {
1026 * Iteration for a package member type
1029 public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) {
1031 if (ignoreFurtherInvestigation)
1034 if (visitor.visit(this, unitScope)) {
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 field.traverse(visitor, staticInitializerScope);
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, unitScope);
1065 } catch (AbortType e) {
1070 * MaxFieldCount's computation is necessary so as to reserve space for the flow info field portions. It corresponds to the maximum
1071 * amount of fields this class or one of its innertypes have.
1073 * During name resolution, types are traversed, and the max field count is recorded on the outermost type. It is then propagated
1074 * down during the flow analysis.
1076 * This method is doing either up/down propagation.
1078 void updateMaxFieldCount() {
1080 if (binding == null)
1081 return; // error scenario
1082 TypeDeclaration outerMostType = scope.outerMostClassScope().referenceType();
1083 if (maxFieldCount > outerMostType.maxFieldCount) {
1084 outerMostType.maxFieldCount = maxFieldCount; // up
1086 maxFieldCount = outerMostType.maxFieldCount; // down