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.phpeclipse.internal.compiler.ast.FieldDeclaration;
12 import net.sourceforge.phpdt.core.compiler.CharOperation;
13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.flow.InitializationFlowContext;
18 import net.sourceforge.phpdt.internal.compiler.flow.UnconditionalFlowInfo;
19 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
20 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
21 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
22 import net.sourceforge.phpdt.internal.compiler.lookup.CompilationUnitScope;
23 import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
24 import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding;
25 import net.sourceforge.phpdt.internal.compiler.lookup.MemberTypeBinding;
26 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
27 import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
28 import net.sourceforge.phpdt.internal.compiler.lookup.NestedTypeBinding;
29 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
30 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
31 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
32 import net.sourceforge.phpdt.internal.compiler.parser.Parser;
33 import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
34 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
35 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilationUnit;
36 import net.sourceforge.phpdt.internal.compiler.problem.AbortMethod;
37 import net.sourceforge.phpdt.internal.compiler.problem.AbortType;
38 import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
40 public class TypeDeclaration extends Statement implements ProblemSeverities, ReferenceContext {
44 public int modifiersSourceStart;
48 public TypeReference superclass;
50 public TypeReference[] superInterfaces;
52 public FieldDeclaration[] fields;
54 public AbstractMethodDeclaration[] methods;
56 public TypeDeclaration[] memberTypes;
58 public SourceTypeBinding binding;
60 public ClassScope scope;
62 public MethodScope initializerScope;
64 public MethodScope staticInitializerScope;
66 public boolean ignoreFurtherInvestigation = false;
68 public int maxFieldCount;
70 public int declarationSourceStart;
72 public int declarationSourceEnd;
76 public int bodyEnd; // doesn't include the trailing comment if any.
78 protected boolean hasBeenGenerated = false;
80 public CompilationResult compilationResult;
82 private MethodDeclaration[] missingAbstractMethods;
84 public TypeDeclaration(CompilationResult compilationResult) {
85 this.compilationResult = compilationResult;
89 * We cause the compilation task to abort to a given extent.
91 public void abort(int abortLevel) {
94 throw new AbortCompilation(); // cannot do better
97 CompilationResult compilationResult = scope.referenceCompilationUnit().compilationResult;
100 case AbortCompilation:
101 throw new AbortCompilation(compilationResult);
102 case AbortCompilationUnit:
103 throw new AbortCompilationUnit(compilationResult);
105 throw new AbortMethod(compilationResult);
107 throw new AbortType(compilationResult);
112 * This method is responsible for adding a <clinit>method declaration to the type method collections. Note that this
113 * implementation is inserting it in first place (as VAJ or javac), and that this impacts the behavior of the method
114 * ConstantPool.resetForClinit(int. int), in so far as the latter will have to reset the constant pool state accordingly (if it
115 * was added first, it does not need to preserve some of the method specific cached entries since this will be the first method).
116 * inserts the clinit method declaration in the first position.
118 * @see net.sourceforge.phpdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int)
120 public final void addClinit() {
122 //see comment on needClassInitMethod
123 if (needClassInitMethod()) {
125 AbstractMethodDeclaration[] methods;
126 if ((methods = this.methods) == null) {
128 methods = new AbstractMethodDeclaration[1];
130 length = methods.length;
131 System.arraycopy(methods, 0, (methods = new AbstractMethodDeclaration[length + 1]), 1, length);
133 Clinit clinit = new Clinit(this.compilationResult);
135 // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
136 clinit.declarationSourceStart = clinit.sourceStart = sourceStart;
137 clinit.declarationSourceEnd = clinit.sourceEnd = sourceEnd;
138 clinit.bodyEnd = sourceEnd;
139 this.methods = methods;
144 * Flow analysis for a local innertype
147 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
149 if (ignoreFurtherInvestigation)
152 bits |= IsReachableMASK;
153 LocalTypeBinding localType = (LocalTypeBinding) binding;
155 localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
156 manageEnclosingInstanceAccessIfNecessary(currentScope);
158 updateMaxFieldCount(); // propagate down the max field count
159 internalAnalyseCode(flowContext, flowInfo);
160 } catch (AbortType e) {
161 this.ignoreFurtherInvestigation = true;
167 * Flow analysis for a member innertype
170 public void analyseCode(ClassScope enclosingClassScope) {
172 if (ignoreFurtherInvestigation)
175 // propagate down the max field count
176 updateMaxFieldCount();
177 internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
178 } catch (AbortType e) {
179 this.ignoreFurtherInvestigation = true;
184 * Flow analysis for a local member innertype
187 public void analyseCode(ClassScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
189 if (ignoreFurtherInvestigation)
192 bits |= IsReachableMASK;
193 LocalTypeBinding localType = (LocalTypeBinding) binding;
195 localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
196 manageEnclosingInstanceAccessIfNecessary(currentScope);
198 updateMaxFieldCount(); // propagate down the max field count
199 internalAnalyseCode(flowContext, flowInfo);
200 } catch (AbortType e) {
201 this.ignoreFurtherInvestigation = true;
206 * Flow analysis for a package member type
209 public void analyseCode(CompilationUnitScope unitScope) {
211 if (ignoreFurtherInvestigation)
214 internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
215 } catch (AbortType e) {
216 this.ignoreFurtherInvestigation = true;
221 * Check for constructor vs. method with no return type. Answers true if at least one constructor is defined
223 public boolean checkConstructors(Parser parser) {
225 //if a constructor has not the name of the type,
226 //convert it into a method with 'null' as its return type
227 boolean hasConstructor = false;
228 if (methods != null) {
229 for (int i = methods.length; --i >= 0;) {
230 AbstractMethodDeclaration am;
231 if ((am = methods[i]).isConstructor()) {
232 if (!CharOperation.equals(am.selector, name)) {
233 // the constructor was in fact a method with no return type
234 // unless an explicit constructor call was supplied
235 ConstructorDeclaration c = (ConstructorDeclaration) am;
236 if ((c.constructorCall == null) || (c.constructorCall.isImplicitSuper())) { //changed to a method
237 MethodDeclaration m = new MethodDeclaration(this.compilationResult);
238 m.sourceStart = c.sourceStart;
239 m.sourceEnd = c.sourceEnd;
240 m.bodyStart = c.bodyStart;
241 m.bodyEnd = c.bodyEnd;
242 m.declarationSourceEnd = c.declarationSourceEnd;
243 m.declarationSourceStart = c.declarationSourceStart;
244 m.selector = c.selector;
245 m.statements = c.statements;
246 m.modifiers = c.modifiers;
247 m.arguments = c.arguments;
248 m.thrownExceptions = c.thrownExceptions;
249 m.explicitDeclarations = c.explicitDeclarations;
254 if (this.isInterface()) {
255 // report the problem and continue the parsing
256 parser.problemReporter().interfaceCannotHaveConstructors((ConstructorDeclaration) am);
258 hasConstructor = true;
263 return hasConstructor;
266 public CompilationResult compilationResult() {
268 return this.compilationResult;
271 public ConstructorDeclaration createsInternalConstructor(boolean needExplicitConstructorCall, 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 = ((this instanceof MemberTypeDeclaration) && (modifiers & AccPrivate) != 0) ? AccDefault : modifiers
287 //if you change this setting, please update the
288 //SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
289 constructor.declarationSourceStart = constructor.sourceStart = sourceStart;
290 constructor.declarationSourceEnd = constructor.sourceEnd = constructor.bodyEnd = sourceEnd;
292 //the super call inside the constructor
293 if (needExplicitConstructorCall) {
294 constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
295 constructor.constructorCall.sourceStart = sourceStart;
296 constructor.constructorCall.sourceEnd = sourceEnd;
299 //adding the constructor in the methods list
301 if (methods == null) {
302 methods = new AbstractMethodDeclaration[] { constructor };
304 AbstractMethodDeclaration[] newMethods;
305 System.arraycopy(methods, 0, newMethods = new AbstractMethodDeclaration[methods.length + 1], 1, methods.length);
306 newMethods[0] = constructor;
307 methods = newMethods;
314 * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding. It is used to report errors for missing
317 public MethodDeclaration addMissingAbstractMethodFor(MethodBinding methodBinding) {
318 TypeBinding[] argumentTypes = methodBinding.parameters;
319 int argumentsLength = argumentTypes.length;
321 MethodDeclaration methodDeclaration = new MethodDeclaration(this.compilationResult);
322 methodDeclaration.selector = methodBinding.selector;
323 methodDeclaration.sourceStart = sourceStart;
324 methodDeclaration.sourceEnd = sourceEnd;
325 methodDeclaration.modifiers = methodBinding.getAccessFlags() & ~AccAbstract;
327 if (argumentsLength > 0) {
328 String baseName = "arg";//$NON-NLS-1$
329 Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]);
330 for (int i = argumentsLength; --i >= 0;) {
331 arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /* type ref */, AccDefault);
335 //adding the constructor in the methods list
336 if (this.missingAbstractMethods == null) {
337 this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
339 MethodDeclaration[] newMethods;
340 System.arraycopy(this.missingAbstractMethods, 0, newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1],
341 1, this.missingAbstractMethods.length);
342 newMethods[0] = methodDeclaration;
343 this.missingAbstractMethods = newMethods;
346 //============BINDING UPDATE==========================
347 methodDeclaration.binding = new MethodBinding(methodDeclaration.modifiers, //methodDeclaration
348 methodBinding.selector, methodBinding.returnType, argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
349 methodBinding.thrownExceptions, //exceptions
350 binding); //declaringClass
352 methodDeclaration.scope = new MethodScope(scope, methodDeclaration, true);
353 methodDeclaration.bindArguments();
356 * if (binding.methods == null) { binding.methods = new MethodBinding[] { methodDeclaration.binding }; } else { MethodBinding[]
357 * newMethods; System.arraycopy( binding.methods, 0, newMethods = new MethodBinding[binding.methods.length + 1], 1,
358 * binding.methods.length); newMethods[0] = methodDeclaration.binding; binding.methods = newMethods; }
360 //===================================================
361 return methodDeclaration;
365 * Find the matching parse node, answers null if nothing found
367 public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
369 if (fieldBinding != null) {
370 for (int i = 0, max = this.fields.length; i < max; i++) {
371 FieldDeclaration fieldDecl;
372 if ((fieldDecl = this.fields[i]).binding == fieldBinding)
380 * Find the matching parse node, answers null if nothing found
382 public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) {
384 if (memberTypeBinding != null) {
385 for (int i = 0, max = this.memberTypes.length; i < max; i++) {
386 TypeDeclaration memberTypeDecl;
387 if ((memberTypeDecl = this.memberTypes[i]).binding == memberTypeBinding)
388 return memberTypeDecl;
395 * Find the matching parse node, answers null if nothing found
397 public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
399 if (methodBinding != null) {
400 for (int i = 0, max = this.methods.length; i < max; i++) {
401 AbstractMethodDeclaration methodDecl;
403 if ((methodDecl = this.methods[i]).binding == methodBinding)
411 * 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
412 * 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}
414 public TypeDeclaration declarationOfType(char[][] typeName) {
416 int typeNameLength = typeName.length;
417 if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) {
420 if (typeNameLength == 1) {
423 char[][] subTypeName = new char[typeNameLength - 1][];
424 System.arraycopy(typeName, 1, subTypeName, 0, typeNameLength - 1);
425 for (int i = 0; i < this.memberTypes.length; i++) {
426 TypeDeclaration typeDecl = this.memberTypes[i].declarationOfType(subTypeName);
427 if (typeDecl != null) {
435 * Generic bytecode generation for type
437 // public void generateCode(ClassFile enclosingClassFile) {
439 // if (hasBeenGenerated)
441 // hasBeenGenerated = true;
442 // if (ignoreFurtherInvestigation) {
443 // if (binding == null)
445 // ClassFile.createProblemType(
447 // scope.referenceCompilationUnit().compilationResult);
451 // // create the result for a compiled type
452 // ClassFile classFile = new ClassFile(binding, enclosingClassFile, false);
453 // // generate all fiels
454 // classFile.addFieldInfos();
456 // // record the inner type inside its own .class file to be able
457 // // to generate inner classes attributes
458 // if (binding.isMemberType())
459 // classFile.recordEnclosingTypeAttributes(binding);
460 // if (binding.isLocalType()) {
461 // enclosingClassFile.recordNestedLocalAttribute(binding);
462 // classFile.recordNestedLocalAttribute(binding);
464 // if (memberTypes != null) {
465 // for (int i = 0, max = memberTypes.length; i < max; i++) {
466 // // record the inner type inside its own .class file to be able
467 // // to generate inner classes attributes
468 // classFile.recordNestedMemberAttribute(memberTypes[i].binding);
469 // memberTypes[i].generateCode(scope, classFile);
472 // // generate all methods
473 // classFile.setForMethodInfos();
474 // if (methods != null) {
475 // for (int i = 0, max = methods.length; i < max; i++) {
476 // methods[i].generateCode(scope, classFile);
480 // classFile.generateMissingAbstractMethods(this.missingAbstractMethods, scope.referenceCompilationUnit().compilationResult);
482 // // generate all methods
483 // classFile.addSpecialMethods();
485 // if (ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
486 // throw new AbortType(scope.referenceCompilationUnit().compilationResult);
489 // // finalize the compiled type result
490 // classFile.addAttributes();
491 // scope.referenceCompilationUnit().compilationResult.record(
492 // binding.constantPoolName(),
494 // } catch (AbortType e) {
495 // if (binding == null)
497 // ClassFile.createProblemType(
499 // scope.referenceCompilationUnit().compilationResult);
503 * Bytecode generation for a local inner type (API as a normal statement code gen)
505 // public void generateCode(BlockScope blockScope, CodeStream codeStream) {
507 // if (hasBeenGenerated) return;
508 // int pc = codeStream.position;
509 // if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
510 // generateCode(codeStream.classFile);
511 // codeStream.recordPositionsFrom(pc, this.sourceStart);
514 * Bytecode generation for a member inner type
516 // public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) {
518 // if (hasBeenGenerated) return;
519 // if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
520 // generateCode(enclosingClassFile);
523 * Bytecode generation for a package member
525 // public void generateCode(CompilationUnitScope unitScope) {
527 // generateCode((ClassFile) null);
529 public boolean hasErrors() {
530 return this.ignoreFurtherInvestigation;
534 * Common flow analysis for all types
537 public void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
539 if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
540 if (!scope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
541 scope.problemReporter().unusedPrivateType(this);
545 ReferenceBinding[] defaultHandledExceptions = new ReferenceBinding[] { scope.getJavaLangThrowable() }; // tolerate any kind of
547 InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, initializerScope);
548 InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, staticInitializerScope);
549 FlowInfo nonStaticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
550 FlowInfo staticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
551 if (fields != null) {
552 for (int i = 0, count = fields.length; i < count; i++) {
553 FieldDeclaration field = fields[i];
554 if (field.isStatic()) {
556 * if (field.isField()){ staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2 }
559 staticInitializerContext.handledExceptions = defaultHandledExceptions; // tolerate them all, and record them
561 staticFieldInfo = field.analyseCode(staticInitializerScope, staticInitializerContext, staticFieldInfo);
562 // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
563 // branch, since the previous initializer already got the blame.
564 if (staticFieldInfo == FlowInfo.DEAD_END) {
565 staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
566 staticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
570 * if (field.isField()){ initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2 } else {
572 initializerContext.handledExceptions = defaultHandledExceptions; // tolerate them all, and record them
574 nonStaticFieldInfo = field.analyseCode(initializerScope, initializerContext, nonStaticFieldInfo);
575 // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
576 // branch, since the previous initializer already got the blame.
577 if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
578 initializerScope.problemReporter().initializerMustCompleteNormally(field);
579 nonStaticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
584 if (memberTypes != null) {
585 for (int i = 0, count = memberTypes.length; i < count; i++) {
586 if (flowContext != null) { // local type
587 memberTypes[i].analyseCode(scope, flowContext, nonStaticFieldInfo.copy());
589 memberTypes[i].analyseCode(scope);
593 if (methods != null) {
594 UnconditionalFlowInfo outerInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
595 FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(
597 for (int i = 0, count = methods.length; i < count; i++) {
598 AbstractMethodDeclaration method = methods[i];
599 if (method.ignoreFurtherInvestigation)
601 if (method.isInitializationMethod()) {
602 if (method.isStatic()) { // <clinit>
603 method.analyseCode(scope, staticInitializerContext, staticFieldInfo.unconditionalInits()
604 .discardNonFieldInitializations().addInitializationsFrom(outerInfo));
605 } else { // constructor
606 method.analyseCode(scope, initializerContext, constructorInfo.copy());
608 } else { // regular method
609 method.analyseCode(scope, null, flowInfo.copy());
615 public boolean isInterface() {
617 return (modifiers & AccInterface) != 0;
621 * Access emulation for a local type force to emulation of access to direct enclosing instance. By using the initializer scope, we
622 * actually only request an argument emulation, the field is not added until actually used. However we will force allocations to
623 * be qualified with an enclosing instance. 15.9.2
625 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
627 NestedTypeBinding nestedType = (NestedTypeBinding) binding;
629 MethodScope methodScope = currentScope.methodScope();
630 if (!methodScope.isStatic && !methodScope.isConstructorCall) {
632 nestedType.addSyntheticArgumentAndField(binding.enclosingType());
634 // add superclass enclosing instance arg for anonymous types (if necessary)
635 if (binding.isAnonymousType()) {
636 ReferenceBinding superclass = binding.superclass;
637 if (superclass.enclosingType() != null && !superclass.isStatic()) {
638 if (!binding.superclass.isLocalType()
639 || ((NestedTypeBinding) binding.superclass).getSyntheticField(superclass.enclosingType(), true) != null) {
641 nestedType.addSyntheticArgument(superclass.enclosingType());
648 * Access emulation for a local member type force to emulation of access to direct enclosing instance. By using the initializer
649 * scope, we actually only request an argument emulation, the field is not added until actually used. However we will force
650 * allocations to be qualified with an enclosing instance.
652 * Local member cannot be static.
654 public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope) {
656 NestedTypeBinding nestedType = (NestedTypeBinding) binding;
657 nestedType.addSyntheticArgumentAndField(binding.enclosingType());
661 * A <clinit>will be requested as soon as static fields or assertions are present. It will be eliminated during classfile creation
662 * if no bytecode was actually produced based on some optimizations/compiler settings.
664 public final boolean needClassInitMethod() {
666 // always need a <clinit> when assertions are present
667 if ((this.bits & AddAssertionMASK) != 0)
672 return true; // fields are implicitly statics
673 for (int i = fields.length; --i >= 0;) {
674 FieldDeclaration field = fields[i];
675 //need to test the modifier directly while there is no binding yet
676 if ((field.modifiers & AccStatic) != 0)
682 public void parseMethod(UnitParser parser, CompilationUnitDeclaration unit) {
684 //connect method bodies
685 if (unit.ignoreMethodBodies)
688 // no scope were created, so cannot report further errors
689 // if (binding == null)
693 if (memberTypes != null) {
694 int length = memberTypes.length;
695 for (int i = 0; i < length; i++)
696 memberTypes[i].parseMethod(parser, unit);
700 if (methods != null) {
701 int length = methods.length;
702 for (int i = 0; i < length; i++)
703 methods[i].parseStatements(parser, unit);
707 if (fields != null) {
708 int length = fields.length;
709 for (int i = 0; i < length; i++) {
710 if (fields[i] instanceof Initializer) {
711 ((Initializer) fields[i]).parseStatements(parser, this, unit);
717 public void resolve() {
719 if (binding == null) {
720 ignoreFurtherInvestigation = true;
725 // check superclass & interfaces
726 if (binding.superclass != null) // watch out for Object ! (and other roots)
727 if (isTypeUseDeprecated(binding.superclass, scope))
728 scope.problemReporter().deprecatedType(binding.superclass, superclass);
729 if (superInterfaces != null)
730 for (int i = superInterfaces.length; --i >= 0;)
731 if (superInterfaces[i].resolvedType != null)
732 if (isTypeUseDeprecated(superInterfaces[i].resolvedType, scope))
733 scope.problemReporter().deprecatedType(superInterfaces[i].resolvedType, superInterfaces[i]);
735 int lastFieldID = -1;
736 if (fields != null) {
737 for (int i = 0, count = fields.length; i < count; i++) {
738 FieldDeclaration field = fields[i];
739 if (field.isField()) {
740 if (field.binding == null) {
741 // still discover secondary errors
742 if (field.initialization != null)
743 field.initialization.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
744 ignoreFurtherInvestigation = true;
748 lastFieldID = field.binding.id;
749 } else { // initializer
750 ((Initializer) field).lastFieldID = lastFieldID + 1;
752 field.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
755 if (memberTypes != null) {
756 for (int i = 0, count = memberTypes.length; i < count; i++) {
757 memberTypes[i].resolve(scope);
760 int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
761 int methodsLength = this.methods == null ? 0 : methods.length;
762 if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) {
763 scope.problemReporter().tooManyMethods(this);
766 if (methods != null) {
767 for (int i = 0, count = methods.length; i < count; i++) {
768 methods[i].resolve(scope);
771 } catch (AbortType e) {
772 this.ignoreFurtherInvestigation = true;
778 public void resolve(BlockScope blockScope) {
779 // local type declaration
781 // need to build its scope first and proceed with binding's creation
782 blockScope.addLocalType(this);
785 if (binding != null) {
786 // remember local types binding for innerclass emulation propagation
787 blockScope.referenceCompilationUnit().record((LocalTypeBinding) binding);
789 // binding is not set if the receiver could not be created
791 updateMaxFieldCount();
795 public void resolve(ClassScope upperScope) {
796 // member scopes are already created
797 // request the construction of a binding if local member type
799 if (binding != null && binding instanceof LocalTypeBinding) {
800 // remember local types binding for innerclass emulation propagation
801 upperScope.referenceCompilationUnit().record((LocalTypeBinding) binding);
804 updateMaxFieldCount();
807 public void resolve(CompilationUnitScope upperScope) {
808 // top level : scope are already created
811 updateMaxFieldCount();
814 public void tagAsHavingErrors() {
815 ignoreFurtherInvestigation = true;
818 public StringBuffer print(int indent, StringBuffer output) {
820 // if ((this.bits & IsAnonymousTypeMASK) == 0) {
821 printIndent(indent, output);
822 printHeader(0, output);
824 return printBody(indent, output);
827 public StringBuffer printBody(int indent, StringBuffer output) {
829 output.append(" {"); //$NON-NLS-1$
830 if (memberTypes != null) {
831 for (int i = 0; i < memberTypes.length; i++) {
832 if (memberTypes[i] != null) {
834 memberTypes[i].print(indent + 1, output);
838 if (fields != null) {
839 for (int fieldI = 0; fieldI < fields.length; fieldI++) {
840 if (fields[fieldI] != null) {
842 fields[fieldI].print(indent + 1, output);
846 if (methods != null) {
847 for (int i = 0; i < methods.length; i++) {
848 if (methods[i] != null) {
850 methods[i].print(indent + 1, output);
855 return printIndent(indent, output).append('}');
858 public StringBuffer printHeader(int indent, StringBuffer output) {
860 printModifiers(this.modifiers, output);
861 output.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
863 if (superclass != null) {
864 output.append(" extends "); //$NON-NLS-1$
865 superclass.print(0, output);
867 if (superInterfaces != null && superInterfaces.length > 0) {
868 output.append(isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
869 for (int i = 0; i < superInterfaces.length; i++) {
871 output.append(", "); //$NON-NLS-1$
872 superInterfaces[i].print(0, output);
878 public StringBuffer printStatement(int tab, StringBuffer output) {
879 return print(tab, output);
882 public String toString(int tab) {
884 return tabString(tab) + toStringHeader() + toStringBody(tab);
887 public String toStringBody(int tab) {
889 String s = " {"; //$NON-NLS-1$
890 if (memberTypes != null) {
891 for (int i = 0; i < memberTypes.length; i++) {
892 if (memberTypes[i] != null) {
893 s += "\n" + memberTypes[i].toString(tab + 1); //$NON-NLS-1$
897 if (fields != null) {
898 for (int fieldI = 0; fieldI < fields.length; fieldI++) {
899 if (fields[fieldI] != null) {
900 s += "\n" + fields[fieldI].toString(tab + 1); //$NON-NLS-1$
901 if (fields[fieldI].isField())
902 s += ";"; //$NON-NLS-1$
906 if (methods != null) {
907 for (int i = 0; i < methods.length; i++) {
908 if (methods[i] != null) {
909 s += "\n" + methods[i].toString(tab + 1); //$NON-NLS-1$
913 s += "\n" + tabString(tab) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
917 public String toStringHeader() {
919 String s = ""; //$NON-NLS-1$
920 if (modifiers != AccDefault) {
921 s += modifiersString(modifiers);
923 s += (isInterface() ? "interface " : "class ") + new String(name);//$NON-NLS-1$ //$NON-NLS-2$
924 if (superclass != null)
925 s += " extends " + superclass.toString(0); //$NON-NLS-1$
926 if (superInterfaces != null && superInterfaces.length > 0) {
927 s += (isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
928 for (int i = 0; i < superInterfaces.length; i++) {
929 s += superInterfaces[i].toString(0);
930 if (i != superInterfaces.length - 1)
931 s += ", "; //$NON-NLS-1$
940 * Iteration for a local innertype
943 public void traverse(ASTVisitor visitor, BlockScope blockScope) {
944 if (ignoreFurtherInvestigation)
947 if (visitor.visit(this, blockScope)) {
948 if (superclass != null)
949 superclass.traverse(visitor, scope);
950 if (superInterfaces != null) {
951 int superInterfaceLength = superInterfaces.length;
952 for (int i = 0; i < superInterfaceLength; i++)
953 superInterfaces[i].traverse(visitor, scope);
955 if (memberTypes != null) {
956 int memberTypesLength = memberTypes.length;
957 for (int i = 0; i < memberTypesLength; i++)
958 memberTypes[i].traverse(visitor, scope);
960 if (fields != null) {
961 int fieldsLength = fields.length;
962 for (int i = 0; i < fieldsLength; i++) {
963 FieldDeclaration field;
964 if ((field = fields[i]).isStatic()) {
965 // local type cannot have static fields
967 field.traverse(visitor, initializerScope);
971 if (methods != null) {
972 int methodsLength = methods.length;
973 for (int i = 0; i < methodsLength; i++)
974 methods[i].traverse(visitor, scope);
977 visitor.endVisit(this, blockScope);
978 } catch (AbortType e) {
984 * Iteration for a member innertype
987 public void traverse(ASTVisitor visitor, ClassScope classScope) {
988 if (ignoreFurtherInvestigation)
991 if (visitor.visit(this, classScope)) {
992 if (superclass != null)
993 superclass.traverse(visitor, scope);
994 if (superInterfaces != null) {
995 int superInterfaceLength = superInterfaces.length;
996 for (int i = 0; i < superInterfaceLength; i++)
997 superInterfaces[i].traverse(visitor, scope);
999 if (memberTypes != null) {
1000 int memberTypesLength = memberTypes.length;
1001 for (int i = 0; i < memberTypesLength; i++)
1002 memberTypes[i].traverse(visitor, scope);
1004 if (fields != null) {
1005 int fieldsLength = fields.length;
1006 for (int i = 0; i < fieldsLength; i++) {
1007 FieldDeclaration field;
1008 if ((field = fields[i]).isStatic()) {
1009 field.traverse(visitor, staticInitializerScope);
1011 field.traverse(visitor, initializerScope);
1015 if (methods != null) {
1016 int methodsLength = methods.length;
1017 for (int i = 0; i < methodsLength; i++)
1018 methods[i].traverse(visitor, scope);
1021 visitor.endVisit(this, classScope);
1022 } catch (AbortType e) {
1028 * Iteration for a package member type
1031 public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) {
1033 if (ignoreFurtherInvestigation)
1036 if (visitor.visit(this, unitScope)) {
1037 if (superclass != null)
1038 superclass.traverse(visitor, scope);
1039 if (superInterfaces != null) {
1040 int superInterfaceLength = superInterfaces.length;
1041 for (int i = 0; i < superInterfaceLength; i++)
1042 superInterfaces[i].traverse(visitor, scope);
1044 if (memberTypes != null) {
1045 int memberTypesLength = memberTypes.length;
1046 for (int i = 0; i < memberTypesLength; i++)
1047 memberTypes[i].traverse(visitor, scope);
1049 if (fields != null) {
1050 int fieldsLength = fields.length;
1051 for (int i = 0; i < fieldsLength; i++) {
1052 FieldDeclaration field;
1053 if ((field = fields[i]).isStatic()) {
1054 field.traverse(visitor, staticInitializerScope);
1056 field.traverse(visitor, initializerScope);
1060 if (methods != null) {
1061 int methodsLength = methods.length;
1062 for (int i = 0; i < methodsLength; i++)
1063 methods[i].traverse(visitor, scope);
1066 visitor.endVisit(this, unitScope);
1067 } catch (AbortType e) {
1072 * MaxFieldCount's computation is necessary so as to reserve space for the flow info field portions. It corresponds to the maximum
1073 * amount of fields this class or one of its innertypes have.
1075 * During name resolution, types are traversed, and the max field count is recorded on the outermost type. It is then propagated
1076 * down during the flow analysis.
1078 * This method is doing either up/down propagation.
1080 void updateMaxFieldCount() {
1082 if (binding == null)
1083 return; // error scenario
1084 TypeDeclaration outerMostType = scope.outerMostClassScope().referenceType();
1085 if (maxFieldCount > outerMostType.maxFieldCount) {
1086 outerMostType.maxFieldCount = maxFieldCount; // up
1088 maxFieldCount = outerMostType.maxFieldCount; // down