0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.ast;
0011:
0012: import org.eclipse.jdt.core.compiler.*;
0013: import org.eclipse.jdt.internal.compiler.*;
0014: import org.eclipse.jdt.internal.compiler.impl.*;
0015: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
0016: import org.eclipse.jdt.internal.compiler.codegen.*;
0017: import org.eclipse.jdt.internal.compiler.flow.*;
0018: import org.eclipse.jdt.internal.compiler.lookup.*;
0019: import org.eclipse.jdt.internal.compiler.parser.*;
0020: import org.eclipse.jdt.internal.compiler.problem.*;
0021:
0022: public class TypeDeclaration extends Statement implements
0023: ProblemSeverities, ReferenceContext {
0024: // Type decl kinds
0025: public static final int CLASS_DECL = 1;
0026: public static final int INTERFACE_DECL = 2;
0027: public static final int ENUM_DECL = 3;
0028: public static final int ANNOTATION_TYPE_DECL = 4;
0029:
0030: public int modifiers = ClassFileConstants.AccDefault;
0031: public int modifiersSourceStart;
0032: public Annotation[] annotations;
0033: public char[] name;
0034: public TypeReference super class;
0035: public TypeReference[] super Interfaces;
0036: public FieldDeclaration[] fields;
0037: public AbstractMethodDeclaration[] methods;
0038: public TypeDeclaration[] memberTypes;
0039: public SourceTypeBinding binding;
0040: public ClassScope scope;
0041: public MethodScope initializerScope;
0042: public MethodScope staticInitializerScope;
0043: public boolean ignoreFurtherInvestigation = false;
0044: public int maxFieldCount;
0045: public int declarationSourceStart;
0046: public int declarationSourceEnd;
0047: public int bodyStart;
0048: public int bodyEnd; // doesn't include the trailing comment if any.
0049: public CompilationResult compilationResult;
0050: public MethodDeclaration[] missingAbstractMethods;
0051: public Javadoc javadoc;
0052:
0053: public QualifiedAllocationExpression allocation; // for anonymous only
0054: public TypeDeclaration enclosingType; // for member types only
0055:
0056: public FieldBinding enumValuesSyntheticfield; // for enum
0057:
0058: // 1.5 support
0059: public TypeParameter[] typeParameters;
0060:
0061: public TypeDeclaration(CompilationResult compilationResult) {
0062: this .compilationResult = compilationResult;
0063: }
0064:
0065: /*
0066: * We cause the compilation task to abort to a given extent.
0067: */
0068: public void abort(int abortLevel, CategorizedProblem problem) {
0069: switch (abortLevel) {
0070: case AbortCompilation:
0071: throw new AbortCompilation(this .compilationResult, problem);
0072: case AbortCompilationUnit:
0073: throw new AbortCompilationUnit(this .compilationResult,
0074: problem);
0075: case AbortMethod:
0076: throw new AbortMethod(this .compilationResult, problem);
0077: default:
0078: throw new AbortType(this .compilationResult, problem);
0079: }
0080: }
0081:
0082: /**
0083: * This method is responsible for adding a <clinit> method declaration to the type method collections.
0084: * Note that this implementation is inserting it in first place (as VAJ or javac), and that this
0085: * impacts the behavior of the method ConstantPool.resetForClinit(int. int), in so far as
0086: * the latter will have to reset the constant pool state accordingly (if it was added first, it does
0087: * not need to preserve some of the method specific cached entries since this will be the first method).
0088: * inserts the clinit method declaration in the first position.
0089: *
0090: * @see org.eclipse.jdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int)
0091: */
0092: public final void addClinit() {
0093: //see comment on needClassInitMethod
0094: if (needClassInitMethod()) {
0095: int length;
0096: AbstractMethodDeclaration[] methodDeclarations;
0097: if ((methodDeclarations = this .methods) == null) {
0098: length = 0;
0099: methodDeclarations = new AbstractMethodDeclaration[1];
0100: } else {
0101: length = methodDeclarations.length;
0102: System
0103: .arraycopy(
0104: methodDeclarations,
0105: 0,
0106: (methodDeclarations = new AbstractMethodDeclaration[length + 1]),
0107: 1, length);
0108: }
0109: Clinit clinit = new Clinit(this .compilationResult);
0110: methodDeclarations[0] = clinit;
0111: // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
0112: clinit.declarationSourceStart = clinit.sourceStart = this .sourceStart;
0113: clinit.declarationSourceEnd = clinit.sourceEnd = this .sourceEnd;
0114: clinit.bodyEnd = this .sourceEnd;
0115: this .methods = methodDeclarations;
0116: }
0117: }
0118:
0119: /*
0120: * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding.
0121: * It is used to report errors for missing abstract methods.
0122: */
0123: public MethodDeclaration addMissingAbstractMethodFor(
0124: MethodBinding methodBinding) {
0125: TypeBinding[] argumentTypes = methodBinding.parameters;
0126: int argumentsLength = argumentTypes.length;
0127: //the constructor
0128: MethodDeclaration methodDeclaration = new MethodDeclaration(
0129: this .compilationResult);
0130: methodDeclaration.selector = methodBinding.selector;
0131: methodDeclaration.sourceStart = this .sourceStart;
0132: methodDeclaration.sourceEnd = this .sourceEnd;
0133: methodDeclaration.modifiers = methodBinding.getAccessFlags()
0134: & ~ClassFileConstants.AccAbstract;
0135:
0136: if (argumentsLength > 0) {
0137: String baseName = "arg";//$NON-NLS-1$
0138: Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]);
0139: for (int i = argumentsLength; --i >= 0;) {
0140: arguments[i] = new Argument((baseName + i)
0141: .toCharArray(), 0L, null /*type ref*/,
0142: ClassFileConstants.AccDefault);
0143: }
0144: }
0145:
0146: //adding the constructor in the methods list
0147: if (this .missingAbstractMethods == null) {
0148: this .missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
0149: } else {
0150: MethodDeclaration[] newMethods;
0151: System
0152: .arraycopy(
0153: this .missingAbstractMethods,
0154: 0,
0155: newMethods = new MethodDeclaration[this .missingAbstractMethods.length + 1],
0156: 1, this .missingAbstractMethods.length);
0157: newMethods[0] = methodDeclaration;
0158: this .missingAbstractMethods = newMethods;
0159: }
0160:
0161: //============BINDING UPDATE==========================
0162: methodDeclaration.binding = new MethodBinding(
0163: methodDeclaration.modifiers, //methodDeclaration
0164: methodBinding.selector, methodBinding.returnType,
0165: argumentsLength == 0 ? Binding.NO_PARAMETERS
0166: : argumentTypes, //arguments bindings
0167: methodBinding.thrownExceptions, //exceptions
0168: this .binding); //declaringClass
0169:
0170: methodDeclaration.scope = new MethodScope(this .scope,
0171: methodDeclaration, true);
0172: methodDeclaration.bindArguments();
0173:
0174: /* if (binding.methods == null) {
0175: binding.methods = new MethodBinding[] { methodDeclaration.binding };
0176: } else {
0177: MethodBinding[] newMethods;
0178: System.arraycopy(
0179: binding.methods,
0180: 0,
0181: newMethods = new MethodBinding[binding.methods.length + 1],
0182: 1,
0183: binding.methods.length);
0184: newMethods[0] = methodDeclaration.binding;
0185: binding.methods = newMethods;
0186: }*/
0187: //===================================================
0188: return methodDeclaration;
0189: }
0190:
0191: /**
0192: * Flow analysis for a local innertype
0193: *
0194: */
0195: public FlowInfo analyseCode(BlockScope currentScope,
0196: FlowContext flowContext, FlowInfo flowInfo) {
0197: if (this .ignoreFurtherInvestigation)
0198: return flowInfo;
0199: try {
0200: if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
0201: this .bits |= ASTNode.IsReachable;
0202: LocalTypeBinding localType = (LocalTypeBinding) this .binding;
0203: localType.setConstantPoolName(currentScope
0204: .compilationUnitScope()
0205: .computeConstantPoolName(localType));
0206: }
0207: manageEnclosingInstanceAccessIfNecessary(currentScope,
0208: flowInfo);
0209: updateMaxFieldCount(); // propagate down the max field count
0210: internalAnalyseCode(flowContext, flowInfo);
0211: } catch (AbortType e) {
0212: this .ignoreFurtherInvestigation = true;
0213: }
0214: return flowInfo;
0215: }
0216:
0217: /**
0218: * Flow analysis for a member innertype
0219: *
0220: */
0221: public void analyseCode(ClassScope enclosingClassScope) {
0222: if (this .ignoreFurtherInvestigation)
0223: return;
0224: try {
0225: // propagate down the max field count
0226: updateMaxFieldCount();
0227: internalAnalyseCode(null, FlowInfo
0228: .initial(this .maxFieldCount));
0229: } catch (AbortType e) {
0230: this .ignoreFurtherInvestigation = true;
0231: }
0232: }
0233:
0234: /**
0235: * Flow analysis for a local member innertype
0236: *
0237: */
0238: public void analyseCode(ClassScope currentScope,
0239: FlowContext flowContext, FlowInfo flowInfo) {
0240: if (this .ignoreFurtherInvestigation)
0241: return;
0242: try {
0243: if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
0244: this .bits |= ASTNode.IsReachable;
0245: LocalTypeBinding localType = (LocalTypeBinding) this .binding;
0246: localType.setConstantPoolName(currentScope
0247: .compilationUnitScope()
0248: .computeConstantPoolName(localType));
0249: }
0250: manageEnclosingInstanceAccessIfNecessary(currentScope,
0251: flowInfo);
0252: updateMaxFieldCount(); // propagate down the max field count
0253: internalAnalyseCode(flowContext, flowInfo);
0254: } catch (AbortType e) {
0255: this .ignoreFurtherInvestigation = true;
0256: }
0257: }
0258:
0259: /**
0260: * Flow analysis for a package member type
0261: *
0262: */
0263: public void analyseCode(CompilationUnitScope unitScope) {
0264: if (this .ignoreFurtherInvestigation)
0265: return;
0266: try {
0267: internalAnalyseCode(null, FlowInfo
0268: .initial(this .maxFieldCount));
0269: } catch (AbortType e) {
0270: this .ignoreFurtherInvestigation = true;
0271: }
0272: }
0273:
0274: /**
0275: * Check for constructor vs. method with no return type.
0276: * Answers true if at least one constructor is defined
0277: */
0278: public boolean checkConstructors(Parser parser) {
0279: //if a constructor has not the name of the type,
0280: //convert it into a method with 'null' as its return type
0281: boolean hasConstructor = false;
0282: if (this .methods != null) {
0283: for (int i = this .methods.length; --i >= 0;) {
0284: AbstractMethodDeclaration am;
0285: if ((am = this .methods[i]).isConstructor()) {
0286: if (!CharOperation.equals(am.selector, this .name)) {
0287: // the constructor was in fact a method with no return type
0288: // unless an explicit constructor call was supplied
0289: ConstructorDeclaration c = (ConstructorDeclaration) am;
0290: if (c.constructorCall == null
0291: || c.constructorCall.isImplicitSuper()) { //changed to a method
0292: MethodDeclaration m = parser
0293: .convertToMethodDeclaration(c,
0294: this .compilationResult);
0295: this .methods[i] = m;
0296: }
0297: } else {
0298: switch (kind(this .modifiers)) {
0299: case TypeDeclaration.INTERFACE_DECL:
0300: // report the problem and continue the parsing
0301: parser
0302: .problemReporter()
0303: .interfaceCannotHaveConstructors(
0304: (ConstructorDeclaration) am);
0305: break;
0306: case TypeDeclaration.ANNOTATION_TYPE_DECL:
0307: // report the problem and continue the parsing
0308: parser
0309: .problemReporter()
0310: .annotationTypeDeclarationCannotHaveConstructor(
0311: (ConstructorDeclaration) am);
0312: break;
0313:
0314: }
0315: hasConstructor = true;
0316: }
0317: }
0318: }
0319: }
0320: return hasConstructor;
0321: }
0322:
0323: public CompilationResult compilationResult() {
0324: return this .compilationResult;
0325: }
0326:
0327: public ConstructorDeclaration createDefaultConstructor(
0328: boolean needExplicitConstructorCall, boolean needToInsert) {
0329: //Add to method'set, the default constuctor that just recall the
0330: //super constructor with no arguments
0331: //The arguments' type will be positionned by the TC so just use
0332: //the default int instead of just null (consistency purpose)
0333:
0334: //the constructor
0335: ConstructorDeclaration constructor = new ConstructorDeclaration(
0336: this .compilationResult);
0337: constructor.bits |= ASTNode.IsDefaultConstructor;
0338: constructor.selector = this .name;
0339: constructor.modifiers = this .modifiers
0340: & ExtraCompilerModifiers.AccVisibilityMASK;
0341:
0342: //if you change this setting, please update the
0343: //SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
0344: constructor.declarationSourceStart = constructor.sourceStart = this .sourceStart;
0345: constructor.declarationSourceEnd = constructor.sourceEnd = constructor.bodyEnd = this .sourceEnd;
0346:
0347: //the super call inside the constructor
0348: if (needExplicitConstructorCall) {
0349: constructor.constructorCall = SuperReference
0350: .implicitSuperConstructorCall();
0351: constructor.constructorCall.sourceStart = this .sourceStart;
0352: constructor.constructorCall.sourceEnd = this .sourceEnd;
0353: }
0354:
0355: //adding the constructor in the methods list: rank is not critical since bindings will be sorted
0356: if (needToInsert) {
0357: if (this .methods == null) {
0358: this .methods = new AbstractMethodDeclaration[] { constructor };
0359: } else {
0360: AbstractMethodDeclaration[] newMethods;
0361: System
0362: .arraycopy(
0363: this .methods,
0364: 0,
0365: newMethods = new AbstractMethodDeclaration[this .methods.length + 1],
0366: 1, this .methods.length);
0367: newMethods[0] = constructor;
0368: this .methods = newMethods;
0369: }
0370: }
0371: return constructor;
0372: }
0373:
0374: // anonymous type constructor creation: rank is important since bindings already got sorted
0375: public MethodBinding createDefaultConstructorWithBinding(
0376: MethodBinding inheritedConstructorBinding) {
0377: //Add to method'set, the default constuctor that just recall the
0378: //super constructor with the same arguments
0379: String baseName = "$anonymous"; //$NON-NLS-1$
0380: TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
0381: int argumentsLength = argumentTypes.length;
0382: //the constructor
0383: ConstructorDeclaration constructor = new ConstructorDeclaration(
0384: this .compilationResult);
0385: constructor.selector = new char[] { 'x' }; //no maining
0386: constructor.sourceStart = this .sourceStart;
0387: constructor.sourceEnd = this .sourceEnd;
0388: int newModifiers = this .modifiers
0389: & ExtraCompilerModifiers.AccVisibilityMASK;
0390: if (inheritedConstructorBinding.isVarargs()) {
0391: newModifiers |= ClassFileConstants.AccVarargs;
0392: }
0393: constructor.modifiers = newModifiers;
0394: constructor.bits |= ASTNode.IsDefaultConstructor;
0395:
0396: if (argumentsLength > 0) {
0397: Argument[] arguments = (constructor.arguments = new Argument[argumentsLength]);
0398: for (int i = argumentsLength; --i >= 0;) {
0399: arguments[i] = new Argument((baseName + i)
0400: .toCharArray(), 0L, null /*type ref*/,
0401: ClassFileConstants.AccDefault);
0402: }
0403: }
0404: //the super call inside the constructor
0405: constructor.constructorCall = SuperReference
0406: .implicitSuperConstructorCall();
0407: constructor.constructorCall.sourceStart = this .sourceStart;
0408: constructor.constructorCall.sourceEnd = this .sourceEnd;
0409:
0410: if (argumentsLength > 0) {
0411: Expression[] args;
0412: args = constructor.constructorCall.arguments = new Expression[argumentsLength];
0413: for (int i = argumentsLength; --i >= 0;) {
0414: args[i] = new SingleNameReference((baseName + i)
0415: .toCharArray(), 0L);
0416: }
0417: }
0418:
0419: //adding the constructor in the methods list
0420: if (this .methods == null) {
0421: this .methods = new AbstractMethodDeclaration[] { constructor };
0422: } else {
0423: AbstractMethodDeclaration[] newMethods;
0424: System
0425: .arraycopy(
0426: this .methods,
0427: 0,
0428: newMethods = new AbstractMethodDeclaration[this .methods.length + 1],
0429: 1, this .methods.length);
0430: newMethods[0] = constructor;
0431: this .methods = newMethods;
0432: }
0433:
0434: //============BINDING UPDATE==========================
0435: SourceTypeBinding sourceType = this .binding;
0436: constructor.binding = new MethodBinding(constructor.modifiers, //methodDeclaration
0437: argumentsLength == 0 ? Binding.NO_PARAMETERS
0438: : argumentTypes, //arguments bindings
0439: inheritedConstructorBinding.thrownExceptions, //exceptions
0440: sourceType); //declaringClass
0441:
0442: constructor.binding.modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor;
0443:
0444: constructor.scope = new MethodScope(this .scope, constructor,
0445: true);
0446: constructor.bindArguments();
0447: constructor.constructorCall.resolve(constructor.scope);
0448:
0449: MethodBinding[] methodBindings = sourceType.methods(); // trigger sorting
0450: int length;
0451: System
0452: .arraycopy(
0453: methodBindings,
0454: 0,
0455: methodBindings = new MethodBinding[(length = methodBindings.length) + 1],
0456: 1, length);
0457: methodBindings[0] = constructor.binding;
0458: if (++length > 1)
0459: ReferenceBinding.sortMethods(methodBindings, 0, length); // need to resort, since could be valid methods ahead (140643) - DOM needs eager sorting
0460: sourceType.setMethods(methodBindings);
0461: //===================================================
0462:
0463: return constructor.binding;
0464: }
0465:
0466: /**
0467: * Find the matching parse node, answers null if nothing found
0468: */
0469: public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
0470: if (fieldBinding != null && this .fields != null) {
0471: for (int i = 0, max = this .fields.length; i < max; i++) {
0472: FieldDeclaration fieldDecl;
0473: if ((fieldDecl = this .fields[i]).binding == fieldBinding)
0474: return fieldDecl;
0475: }
0476: }
0477: return null;
0478: }
0479:
0480: /**
0481: * Find the matching parse node, answers null if nothing found
0482: */
0483: public TypeDeclaration declarationOf(
0484: MemberTypeBinding memberTypeBinding) {
0485: if (memberTypeBinding != null && this .memberTypes != null) {
0486: for (int i = 0, max = this .memberTypes.length; i < max; i++) {
0487: TypeDeclaration memberTypeDecl;
0488: if ((memberTypeDecl = this .memberTypes[i]).binding == memberTypeBinding)
0489: return memberTypeDecl;
0490: }
0491: }
0492: return null;
0493: }
0494:
0495: /**
0496: * Find the matching parse node, answers null if nothing found
0497: */
0498: public AbstractMethodDeclaration declarationOf(
0499: MethodBinding methodBinding) {
0500: if (methodBinding != null && this .methods != null) {
0501: for (int i = 0, max = this .methods.length; i < max; i++) {
0502: AbstractMethodDeclaration methodDecl;
0503:
0504: if ((methodDecl = this .methods[i]).binding == methodBinding)
0505: return methodDecl;
0506: }
0507: }
0508: return null;
0509: }
0510:
0511: /**
0512: * Finds the matching type amoung this type's member types.
0513: * Returns null if no type with this name is found.
0514: * The type name is a compound name relative to this type
0515: * eg. if this type is X and we're looking for Y.X.A.B
0516: * then a type name would be {X, A, B}
0517: */
0518: public TypeDeclaration declarationOfType(char[][] typeName) {
0519: int typeNameLength = typeName.length;
0520: if (typeNameLength < 1
0521: || !CharOperation.equals(typeName[0], this .name)) {
0522: return null;
0523: }
0524: if (typeNameLength == 1) {
0525: return this ;
0526: }
0527: char[][] subTypeName = new char[typeNameLength - 1][];
0528: System.arraycopy(typeName, 1, subTypeName, 0,
0529: typeNameLength - 1);
0530: for (int i = 0; i < this .memberTypes.length; i++) {
0531: TypeDeclaration typeDecl = this .memberTypes[i]
0532: .declarationOfType(subTypeName);
0533: if (typeDecl != null) {
0534: return typeDecl;
0535: }
0536: }
0537: return null;
0538: }
0539:
0540: /**
0541: * Generic bytecode generation for type
0542: */
0543: public void generateCode(ClassFile enclosingClassFile) {
0544: if ((this .bits & ASTNode.HasBeenGenerated) != 0)
0545: return;
0546: this .bits |= ASTNode.HasBeenGenerated;
0547: if (this .ignoreFurtherInvestigation) {
0548: if (this .binding == null)
0549: return;
0550: ClassFile.createProblemType(this , this .scope
0551: .referenceCompilationUnit().compilationResult);
0552: return;
0553: }
0554: try {
0555: // create the result for a compiled type
0556: ClassFile classFile = ClassFile
0557: .getNewInstance(this .binding);
0558: classFile.initialize(this .binding, enclosingClassFile,
0559: false);
0560: if (this .binding.isMemberType()) {
0561: classFile.recordInnerClasses(this .binding);
0562: } else if (this .binding.isLocalType()) {
0563: enclosingClassFile.recordInnerClasses(this .binding);
0564: classFile.recordInnerClasses(this .binding);
0565: }
0566:
0567: // generate all fiels
0568: classFile.addFieldInfos();
0569:
0570: if (this .memberTypes != null) {
0571: for (int i = 0, max = this .memberTypes.length; i < max; i++) {
0572: TypeDeclaration memberType = this .memberTypes[i];
0573: classFile.recordInnerClasses(memberType.binding);
0574: memberType.generateCode(this .scope, classFile);
0575: }
0576: }
0577: // generate all methods
0578: classFile.setForMethodInfos();
0579: if (this .methods != null) {
0580: for (int i = 0, max = this .methods.length; i < max; i++) {
0581: this .methods[i].generateCode(this .scope, classFile);
0582: }
0583: }
0584: // generate all synthetic and abstract methods
0585: classFile.addSpecialMethods();
0586:
0587: if (this .ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
0588: throw new AbortType(this .scope
0589: .referenceCompilationUnit().compilationResult,
0590: null);
0591: }
0592:
0593: // finalize the compiled type result
0594: classFile.addAttributes();
0595: this .scope.referenceCompilationUnit().compilationResult
0596: .record(this .binding.constantPoolName(), classFile);
0597: } catch (AbortType e) {
0598: if (this .binding == null)
0599: return;
0600: ClassFile.createProblemType(this , this .scope
0601: .referenceCompilationUnit().compilationResult);
0602: }
0603: }
0604:
0605: /**
0606: * Bytecode generation for a local inner type (API as a normal statement code gen)
0607: */
0608: public void generateCode(BlockScope blockScope,
0609: CodeStream codeStream) {
0610: if ((this .bits & ASTNode.IsReachable) == 0) {
0611: return;
0612: }
0613: if ((this .bits & ASTNode.HasBeenGenerated) != 0)
0614: return;
0615: int pc = codeStream.position;
0616: if (this .binding != null)
0617: ((NestedTypeBinding) this .binding)
0618: .computeSyntheticArgumentSlotSizes();
0619: generateCode(codeStream.classFile);
0620: codeStream.recordPositionsFrom(pc, this .sourceStart);
0621: }
0622:
0623: /**
0624: * Bytecode generation for a member inner type
0625: */
0626: public void generateCode(ClassScope classScope,
0627: ClassFile enclosingClassFile) {
0628: if ((this .bits & ASTNode.HasBeenGenerated) != 0)
0629: return;
0630: if (this .binding != null)
0631: ((NestedTypeBinding) this .binding)
0632: .computeSyntheticArgumentSlotSizes();
0633: generateCode(enclosingClassFile);
0634: }
0635:
0636: /**
0637: * Bytecode generation for a package member
0638: */
0639: public void generateCode(CompilationUnitScope unitScope) {
0640: generateCode((ClassFile) null);
0641: }
0642:
0643: public boolean hasErrors() {
0644: return this .ignoreFurtherInvestigation;
0645: }
0646:
0647: /**
0648: * Common flow analysis for all types
0649: */
0650: private void internalAnalyseCode(FlowContext flowContext,
0651: FlowInfo flowInfo) {
0652: if ((this .binding.isPrivate() || (this .binding.tagBits & (TagBits.IsAnonymousType | TagBits.IsLocalType)) == TagBits.IsLocalType)
0653: && !this .binding.isUsed()) {
0654: if (!this .scope.referenceCompilationUnit().compilationResult.hasSyntaxError) {
0655: this .scope.problemReporter().unusedPrivateType(this );
0656: }
0657: }
0658: InitializationFlowContext initializerContext = new InitializationFlowContext(
0659: null, this , this .initializerScope);
0660: InitializationFlowContext staticInitializerContext = new InitializationFlowContext(
0661: null, this , this .staticInitializerScope);
0662: FlowInfo nonStaticFieldInfo = flowInfo
0663: .unconditionalFieldLessCopy();
0664: FlowInfo staticFieldInfo = flowInfo
0665: .unconditionalFieldLessCopy();
0666: if (this .fields != null) {
0667: for (int i = 0, count = this .fields.length; i < count; i++) {
0668: FieldDeclaration field = this .fields[i];
0669: if (field.isStatic()) {
0670: if ((staticFieldInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
0671: field.bits &= ~ASTNode.IsReachable;
0672:
0673: /*if (field.isField()){
0674: staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
0675: } else {*/
0676: staticInitializerContext.handledExceptions = Binding.ANY_EXCEPTION; // tolerate them all, and record them
0677: /*}*/
0678: staticFieldInfo = field.analyseCode(
0679: this .staticInitializerScope,
0680: staticInitializerContext, staticFieldInfo);
0681: // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
0682: // branch, since the previous initializer already got the blame.
0683: if (staticFieldInfo == FlowInfo.DEAD_END) {
0684: this .staticInitializerScope.problemReporter()
0685: .initializerMustCompleteNormally(field);
0686: staticFieldInfo = FlowInfo.initial(
0687: this .maxFieldCount).setReachMode(
0688: FlowInfo.UNREACHABLE);
0689: }
0690: } else {
0691: if ((nonStaticFieldInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
0692: field.bits &= ~ASTNode.IsReachable;
0693:
0694: /*if (field.isField()){
0695: initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
0696: } else {*/
0697: initializerContext.handledExceptions = Binding.ANY_EXCEPTION; // tolerate them all, and record them
0698: /*}*/
0699: nonStaticFieldInfo = field.analyseCode(
0700: this .initializerScope, initializerContext,
0701: nonStaticFieldInfo);
0702: // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
0703: // branch, since the previous initializer already got the blame.
0704: if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
0705: this .initializerScope.problemReporter()
0706: .initializerMustCompleteNormally(field);
0707: nonStaticFieldInfo = FlowInfo.initial(
0708: this .maxFieldCount).setReachMode(
0709: FlowInfo.UNREACHABLE);
0710: }
0711: }
0712: }
0713: }
0714: if (this .memberTypes != null) {
0715: for (int i = 0, count = this .memberTypes.length; i < count; i++) {
0716: if (flowContext != null) { // local type
0717: this .memberTypes[i]
0718: .analyseCode(
0719: this .scope,
0720: flowContext,
0721: nonStaticFieldInfo
0722: .copy()
0723: .setReachMode(
0724: flowInfo
0725: .reachMode())); // reset reach mode in case initializers did abrupt completely
0726: } else {
0727: this .memberTypes[i].analyseCode(this .scope);
0728: }
0729: }
0730: }
0731: if (this .methods != null) {
0732: UnconditionalFlowInfo outerInfo = flowInfo
0733: .unconditionalFieldLessCopy();
0734: FlowInfo constructorInfo = nonStaticFieldInfo
0735: .unconditionalInits()
0736: .discardNonFieldInitializations()
0737: .addInitializationsFrom(outerInfo);
0738: for (int i = 0, count = this .methods.length; i < count; i++) {
0739: AbstractMethodDeclaration method = this .methods[i];
0740: if (method.ignoreFurtherInvestigation)
0741: continue;
0742: if (method.isInitializationMethod()) {
0743: if (method.isStatic()) { // <clinit>
0744: method
0745: .analyseCode(
0746: this .scope,
0747: staticInitializerContext,
0748: staticFieldInfo
0749: .unconditionalInits()
0750: .discardNonFieldInitializations()
0751: .addInitializationsFrom(
0752: outerInfo));
0753: } else { // constructor
0754: ((ConstructorDeclaration) method).analyseCode(
0755: this .scope, initializerContext,
0756: constructorInfo.copy(), flowInfo
0757: .reachMode());
0758: }
0759: } else { // regular method
0760: method.analyseCode(this .scope, null, flowInfo
0761: .copy());
0762: }
0763: }
0764: }
0765: // enable enum support ?
0766: if (this .binding.isEnum() && !this .binding.isAnonymousType()) {
0767: this .enumValuesSyntheticfield = this .binding
0768: .addSyntheticFieldForEnumValues();
0769: }
0770: }
0771:
0772: public final static int kind(int flags) {
0773: switch (flags
0774: & (ClassFileConstants.AccInterface
0775: | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) {
0776: case ClassFileConstants.AccInterface:
0777: return TypeDeclaration.INTERFACE_DECL;
0778: case ClassFileConstants.AccInterface
0779: | ClassFileConstants.AccAnnotation:
0780: return TypeDeclaration.ANNOTATION_TYPE_DECL;
0781: case ClassFileConstants.AccEnum:
0782: return TypeDeclaration.ENUM_DECL;
0783: default:
0784: return TypeDeclaration.CLASS_DECL;
0785: }
0786: }
0787:
0788: /*
0789: * Access emulation for a local type
0790: * force to emulation of access to direct enclosing instance.
0791: * By using the initializer scope, we actually only request an argument emulation, the
0792: * field is not added until actually used. However we will force allocations to be qualified
0793: * with an enclosing instance.
0794: * 15.9.2
0795: */
0796: public void manageEnclosingInstanceAccessIfNecessary(
0797: BlockScope currentScope, FlowInfo flowInfo) {
0798: if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
0799: return;
0800: NestedTypeBinding nestedType = (NestedTypeBinding) this .binding;
0801:
0802: MethodScope methodScope = currentScope.methodScope();
0803: if (!methodScope.isStatic && !methodScope.isConstructorCall) {
0804: nestedType.addSyntheticArgumentAndField(nestedType
0805: .enclosingType());
0806: }
0807: // add superclass enclosing instance arg for anonymous types (if necessary)
0808: if (nestedType.isAnonymousType()) {
0809: ReferenceBinding super classBinding = (ReferenceBinding) nestedType.super class
0810: .erasure();
0811: if (super classBinding.enclosingType() != null
0812: && !super classBinding.isStatic()) {
0813: if (!super classBinding.isLocalType()
0814: || ((NestedTypeBinding) super classBinding)
0815: .getSyntheticField(super classBinding
0816: .enclosingType(), true) != null) {
0817:
0818: nestedType.addSyntheticArgument(super classBinding
0819: .enclosingType());
0820: }
0821: }
0822: // From 1.5 on, provide access to enclosing instance synthetic constructor argument when declared inside constructor call
0823: // only for direct anonymous type
0824: //public class X {
0825: // void foo() {}
0826: // class M {
0827: // M(Object o) {}
0828: // M() { this(new Object() { void baz() { foo(); }}); } // access to #foo() indirects through constructor synthetic arg: val$this$0
0829: // }
0830: //}
0831: if (!methodScope.isStatic
0832: && methodScope.isConstructorCall
0833: && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5) {
0834: ReferenceBinding enclosing = nestedType.enclosingType();
0835: if (enclosing.isNestedType()) {
0836: NestedTypeBinding nestedEnclosing = (NestedTypeBinding) enclosing;
0837: // if (nestedEnclosing.findSuperTypeErasingTo(nestedEnclosing.enclosingType()) == null) { // only if not inheriting
0838: SyntheticArgumentBinding syntheticEnclosingInstanceArgument = nestedEnclosing
0839: .getSyntheticArgument(nestedEnclosing
0840: .enclosingType(), true);
0841: if (syntheticEnclosingInstanceArgument != null) {
0842: nestedType
0843: .addSyntheticArgumentAndField(syntheticEnclosingInstanceArgument);
0844: }
0845: }
0846: // }
0847: }
0848: }
0849: }
0850:
0851: /**
0852: * Access emulation for a local member type
0853: * force to emulation of access to direct enclosing instance.
0854: * By using the initializer scope, we actually only request an argument emulation, the
0855: * field is not added until actually used. However we will force allocations to be qualified
0856: * with an enclosing instance.
0857: *
0858: * Local member cannot be static.
0859: */
0860: public void manageEnclosingInstanceAccessIfNecessary(
0861: ClassScope currentScope, FlowInfo flowInfo) {
0862: if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
0863: NestedTypeBinding nestedType = (NestedTypeBinding) this .binding;
0864: nestedType.addSyntheticArgumentAndField(this .binding
0865: .enclosingType());
0866: }
0867: }
0868:
0869: /**
0870: * A <clinit> will be requested as soon as static fields or assertions are present. It will be eliminated during
0871: * classfile creation if no bytecode was actually produced based on some optimizations/compiler settings.
0872: */
0873: public final boolean needClassInitMethod() {
0874: // always need a <clinit> when assertions are present
0875: if ((this .bits & ASTNode.ContainsAssertion) != 0)
0876: return true;
0877:
0878: switch (kind(this .modifiers)) {
0879: case TypeDeclaration.INTERFACE_DECL:
0880: case TypeDeclaration.ANNOTATION_TYPE_DECL:
0881: return this .fields != null; // fields are implicitly statics
0882: case TypeDeclaration.ENUM_DECL:
0883: return true; // even if no enum constants, need to set $VALUES array
0884: }
0885: if (this .fields != null) {
0886: for (int i = this .fields.length; --i >= 0;) {
0887: FieldDeclaration field = this .fields[i];
0888: //need to test the modifier directly while there is no binding yet
0889: if ((field.modifiers & ClassFileConstants.AccStatic) != 0)
0890: return true; // TODO (philippe) shouldn't it check whether field is initializer or has some initial value ?
0891: }
0892: }
0893: return false;
0894: }
0895:
0896: public void parseMethod(Parser parser,
0897: CompilationUnitDeclaration unit) {
0898: //connect method bodies
0899: if (unit.ignoreMethodBodies)
0900: return;
0901:
0902: //members
0903: if (this .memberTypes != null) {
0904: int length = this .memberTypes.length;
0905: for (int i = 0; i < length; i++)
0906: this .memberTypes[i].parseMethod(parser, unit);
0907: }
0908:
0909: //methods
0910: if (this .methods != null) {
0911: int length = this .methods.length;
0912: for (int i = 0; i < length; i++) {
0913: this .methods[i].parseStatements(parser, unit);
0914: }
0915: }
0916:
0917: //initializers
0918: if (this .fields != null) {
0919: int length = this .fields.length;
0920: for (int i = 0; i < length; i++) {
0921: final FieldDeclaration fieldDeclaration = this .fields[i];
0922: switch (fieldDeclaration.getKind()) {
0923: case AbstractVariableDeclaration.INITIALIZER:
0924: ((Initializer) fieldDeclaration).parseStatements(
0925: parser, this , unit);
0926: break;
0927: }
0928: }
0929: }
0930: }
0931:
0932: public StringBuffer print(int indent, StringBuffer output) {
0933: if (this .javadoc != null) {
0934: this .javadoc.print(indent, output);
0935: }
0936: if ((this .bits & ASTNode.IsAnonymousType) == 0) {
0937: printIndent(indent, output);
0938: printHeader(0, output);
0939: }
0940: return printBody(indent, output);
0941: }
0942:
0943: public StringBuffer printBody(int indent, StringBuffer output) {
0944: output.append(" {"); //$NON-NLS-1$
0945: if (this .memberTypes != null) {
0946: for (int i = 0; i < this .memberTypes.length; i++) {
0947: if (this .memberTypes[i] != null) {
0948: output.append('\n');
0949: this .memberTypes[i].print(indent + 1, output);
0950: }
0951: }
0952: }
0953: if (this .fields != null) {
0954: for (int fieldI = 0; fieldI < this .fields.length; fieldI++) {
0955: if (this .fields[fieldI] != null) {
0956: output.append('\n');
0957: this .fields[fieldI].print(indent + 1, output);
0958: }
0959: }
0960: }
0961: if (this .methods != null) {
0962: for (int i = 0; i < this .methods.length; i++) {
0963: if (this .methods[i] != null) {
0964: output.append('\n');
0965: this .methods[i].print(indent + 1, output);
0966: }
0967: }
0968: }
0969: output.append('\n');
0970: return printIndent(indent, output).append('}');
0971: }
0972:
0973: public StringBuffer printHeader(int indent, StringBuffer output) {
0974: printModifiers(this .modifiers, output);
0975: if (this .annotations != null)
0976: printAnnotations(this .annotations, output);
0977:
0978: switch (kind(this .modifiers)) {
0979: case TypeDeclaration.CLASS_DECL:
0980: output.append("class "); //$NON-NLS-1$
0981: break;
0982: case TypeDeclaration.INTERFACE_DECL:
0983: output.append("interface "); //$NON-NLS-1$
0984: break;
0985: case TypeDeclaration.ENUM_DECL:
0986: output.append("enum "); //$NON-NLS-1$
0987: break;
0988: case TypeDeclaration.ANNOTATION_TYPE_DECL:
0989: output.append("@interface "); //$NON-NLS-1$
0990: break;
0991: }
0992: output.append(this .name);
0993: if (this .typeParameters != null) {
0994: output.append("<");//$NON-NLS-1$
0995: for (int i = 0; i < this .typeParameters.length; i++) {
0996: if (i > 0)
0997: output.append(", "); //$NON-NLS-1$
0998: this .typeParameters[i].print(0, output);
0999: }
1000: output.append(">");//$NON-NLS-1$
1001: }
1002: if (this .super class != null) {
1003: output.append(" extends "); //$NON-NLS-1$
1004: this .super class.print(0, output);
1005: }
1006: if (this .super Interfaces != null
1007: && this .super Interfaces.length > 0) {
1008: switch (kind(this .modifiers)) {
1009: case TypeDeclaration.CLASS_DECL:
1010: case TypeDeclaration.ENUM_DECL:
1011: output.append(" implements "); //$NON-NLS-1$
1012: break;
1013: case TypeDeclaration.INTERFACE_DECL:
1014: case TypeDeclaration.ANNOTATION_TYPE_DECL:
1015: output.append(" extends "); //$NON-NLS-1$
1016: break;
1017: }
1018: for (int i = 0; i < this .super Interfaces.length; i++) {
1019: if (i > 0)
1020: output.append(", "); //$NON-NLS-1$
1021: this .super Interfaces[i].print(0, output);
1022: }
1023: }
1024: return output;
1025: }
1026:
1027: public StringBuffer printStatement(int tab, StringBuffer output) {
1028: return print(tab, output);
1029: }
1030:
1031: public void resolve() {
1032: SourceTypeBinding sourceType = this .binding;
1033: if (sourceType == null) {
1034: this .ignoreFurtherInvestigation = true;
1035: return;
1036: }
1037: try {
1038: boolean old = this .staticInitializerScope.insideTypeAnnotation;
1039: try {
1040: this .staticInitializerScope.insideTypeAnnotation = true;
1041: resolveAnnotations(this .staticInitializerScope,
1042: this .annotations, sourceType);
1043: } finally {
1044: this .staticInitializerScope.insideTypeAnnotation = old;
1045: }
1046: // check @Deprecated annotation
1047: if ((sourceType.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0
1048: && (sourceType.modifiers & ClassFileConstants.AccDeprecated) != 0
1049: && this .scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
1050: this .scope.problemReporter()
1051: .missingDeprecatedAnnotationForType(this );
1052: }
1053: if ((this .bits & ASTNode.UndocumentedEmptyBlock) != 0) {
1054: this .scope.problemReporter().undocumentedEmptyBlock(
1055: this .bodyStart - 1, this .bodyEnd);
1056: }
1057: boolean needSerialVersion = this .scope.compilerOptions()
1058: .getSeverity(CompilerOptions.MissingSerialVersion) != ProblemSeverities.Ignore
1059: && sourceType.isClass()
1060: && sourceType
1061: .findSuperTypeErasingTo(
1062: TypeIds.T_JavaIoExternalizable,
1063: false /*Serializable is not a class*/) == null
1064: && sourceType
1065: .findSuperTypeErasingTo(
1066: TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null;
1067:
1068: if (needSerialVersion) {
1069: // if Object writeReplace() throws java.io.ObjectStreamException is present, then no serialVersionUID is needed
1070: // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=101476
1071: CompilationUnitScope compilationUnitScope = this .scope
1072: .compilationUnitScope();
1073: MethodBinding methodBinding = sourceType
1074: .getExactMethod(TypeConstants.WRITEREPLACE,
1075: new TypeBinding[0],
1076: compilationUnitScope);
1077: ReferenceBinding[] throwsExceptions;
1078: needSerialVersion = methodBinding == null
1079: || !methodBinding.isValidBinding()
1080: || methodBinding.returnType.id != TypeIds.T_JavaLangObject
1081: || (throwsExceptions = methodBinding.thrownExceptions).length != 1
1082: || throwsExceptions[0].id != TypeIds.T_JavaIoObjectStreamException;
1083: if (needSerialVersion) {
1084: // check the presence of an implementation of the methods
1085: // private void writeObject(java.io.ObjectOutputStream out) throws IOException
1086: // private void readObject(java.io.ObjectInputStream out) throws IOException
1087: boolean hasWriteObjectMethod = false;
1088: boolean hasReadObjectMethod = false;
1089: TypeBinding argumentTypeBinding = this .scope
1090: .getType(
1091: TypeConstants.JAVA_IO_OBJECTOUTPUTSTREAM,
1092: 3);
1093: if (argumentTypeBinding.isValidBinding()) {
1094: methodBinding = sourceType
1095: .getExactMethod(
1096: TypeConstants.WRITEOBJECT,
1097: new TypeBinding[] { argumentTypeBinding },
1098: compilationUnitScope);
1099: hasWriteObjectMethod = methodBinding != null
1100: && methodBinding.isValidBinding()
1101: && methodBinding.modifiers == ClassFileConstants.AccPrivate
1102: && methodBinding.returnType == TypeBinding.VOID
1103: && (throwsExceptions = methodBinding.thrownExceptions).length == 1
1104: && throwsExceptions[0].id == TypeIds.T_JavaIoException;
1105: }
1106: argumentTypeBinding = this .scope.getType(
1107: TypeConstants.JAVA_IO_OBJECTINPUTSTREAM, 3);
1108: if (argumentTypeBinding.isValidBinding()) {
1109: methodBinding = sourceType
1110: .getExactMethod(
1111: TypeConstants.READOBJECT,
1112: new TypeBinding[] { argumentTypeBinding },
1113: compilationUnitScope);
1114: hasReadObjectMethod = methodBinding != null
1115: && methodBinding.isValidBinding()
1116: && methodBinding.modifiers == ClassFileConstants.AccPrivate
1117: && methodBinding.returnType == TypeBinding.VOID
1118: && (throwsExceptions = methodBinding.thrownExceptions).length == 1
1119: && throwsExceptions[0].id == TypeIds.T_JavaIoException;
1120: }
1121: needSerialVersion = !hasWriteObjectMethod
1122: || !hasReadObjectMethod;
1123: }
1124: }
1125: // generics (and non static generic members) cannot extend Throwable
1126: if (sourceType.findSuperTypeErasingTo(
1127: TypeIds.T_JavaLangThrowable, true) != null) {
1128: ReferenceBinding current = sourceType;
1129: checkEnclosedInGeneric: do {
1130: if (current.isGenericType()) {
1131: this .scope.problemReporter()
1132: .genericTypeCannotExtendThrowable(this );
1133: break checkEnclosedInGeneric;
1134: }
1135: if (current.isStatic())
1136: break checkEnclosedInGeneric;
1137: if (current.isLocalType()) {
1138: NestedTypeBinding nestedType = (NestedTypeBinding) current
1139: .erasure();
1140: if (nestedType.scope.methodScope().isStatic)
1141: break checkEnclosedInGeneric;
1142: }
1143: } while ((current = current.enclosingType()) != null);
1144: }
1145: this .maxFieldCount = 0;
1146: int lastVisibleFieldID = -1;
1147: boolean hasEnumConstants = false;
1148: boolean hasEnumConstantsWithoutBody = false;
1149:
1150: if (this .typeParameters != null) {
1151: for (int i = 0, count = this .typeParameters.length; i < count; i++) {
1152: this .typeParameters[i].resolve(this .scope);
1153: }
1154: }
1155: if (this .memberTypes != null) {
1156: for (int i = 0, count = this .memberTypes.length; i < count; i++) {
1157: this .memberTypes[i].resolve(this .scope);
1158: }
1159: }
1160: if (this .fields != null) {
1161: for (int i = 0, count = this .fields.length; i < count; i++) {
1162: FieldDeclaration field = this .fields[i];
1163: switch (field.getKind()) {
1164: case AbstractVariableDeclaration.ENUM_CONSTANT:
1165: hasEnumConstants = true;
1166: if (!(field.initialization instanceof QualifiedAllocationExpression))
1167: hasEnumConstantsWithoutBody = true;
1168: case AbstractVariableDeclaration.FIELD:
1169: FieldBinding fieldBinding = field.binding;
1170: if (fieldBinding == null) {
1171: // still discover secondary errors
1172: if (field.initialization != null)
1173: field.initialization
1174: .resolve(field.isStatic() ? this .staticInitializerScope
1175: : this .initializerScope);
1176: this .ignoreFurtherInvestigation = true;
1177: continue;
1178: }
1179: if (needSerialVersion
1180: && ((fieldBinding.modifiers & (ClassFileConstants.AccStatic | ClassFileConstants.AccFinal)) == (ClassFileConstants.AccStatic | ClassFileConstants.AccFinal))
1181: && CharOperation.equals(
1182: TypeConstants.SERIALVERSIONUID,
1183: fieldBinding.name)
1184: && TypeBinding.LONG == fieldBinding.type) {
1185: needSerialVersion = false;
1186: }
1187: this .maxFieldCount++;
1188: lastVisibleFieldID = field.binding.id;
1189: break;
1190:
1191: case AbstractVariableDeclaration.INITIALIZER:
1192: ((Initializer) field).lastVisibleFieldID = lastVisibleFieldID + 1;
1193: break;
1194: }
1195: field
1196: .resolve(field.isStatic() ? this .staticInitializerScope
1197: : this .initializerScope);
1198: }
1199: }
1200: if (needSerialVersion) {
1201: this .scope.problemReporter().missingSerialVersion(this );
1202: }
1203: // check extends/implements for annotation type
1204: switch (kind(this .modifiers)) {
1205: case TypeDeclaration.ANNOTATION_TYPE_DECL:
1206: if (this .super class != null) {
1207: this .scope
1208: .problemReporter()
1209: .annotationTypeDeclarationCannotHaveSuperclass(
1210: this );
1211: }
1212: if (this .super Interfaces != null) {
1213: this .scope
1214: .problemReporter()
1215: .annotationTypeDeclarationCannotHaveSuperinterfaces(
1216: this );
1217: }
1218: break;
1219: case TypeDeclaration.ENUM_DECL:
1220: // check enum abstract methods
1221: if (this .binding.isAbstract()) {
1222: if (!hasEnumConstants
1223: || hasEnumConstantsWithoutBody) {
1224: for (int i = 0, count = this .methods.length; i < count; i++) {
1225: final AbstractMethodDeclaration methodDeclaration = this .methods[i];
1226: if (methodDeclaration.isAbstract()
1227: && methodDeclaration.binding != null) {
1228: this .scope
1229: .problemReporter()
1230: .enumAbstractMethodMustBeImplemented(
1231: methodDeclaration);
1232: }
1233: }
1234: }
1235: }
1236: break;
1237: }
1238:
1239: int missingAbstractMethodslength = this .missingAbstractMethods == null ? 0
1240: : this .missingAbstractMethods.length;
1241: int methodsLength = this .methods == null ? 0
1242: : this .methods.length;
1243: if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) {
1244: this .scope.problemReporter().tooManyMethods(this );
1245: }
1246: if (this .methods != null) {
1247: for (int i = 0, count = this .methods.length; i < count; i++) {
1248: this .methods[i].resolve(this .scope);
1249: }
1250: }
1251: // Resolve javadoc
1252: if (this .javadoc != null) {
1253: if (this .scope != null
1254: && (this .name != TypeConstants.PACKAGE_INFO_NAME)) {
1255: // if the type is package-info, the javadoc was resolved as part of the compilation unit javadoc
1256: this .javadoc.resolve(this .scope);
1257: }
1258: } else if (sourceType != null && !sourceType.isLocalType()) {
1259: this .scope.problemReporter().javadocMissing(
1260: this .sourceStart, this .sourceEnd,
1261: sourceType.modifiers);
1262: }
1263:
1264: } catch (AbortType e) {
1265: this .ignoreFurtherInvestigation = true;
1266: return;
1267: }
1268: }
1269:
1270: /**
1271: * Resolve a local type declaration
1272: */
1273: public void resolve(BlockScope blockScope) {
1274:
1275: // need to build its scope first and proceed with binding's creation
1276: if ((this .bits & ASTNode.IsAnonymousType) == 0) {
1277: // check collision scenarii
1278: Binding existing = blockScope.getType(this .name);
1279: if (existing instanceof ReferenceBinding
1280: && existing != this .binding
1281: && existing.isValidBinding()) {
1282: ReferenceBinding existingType = (ReferenceBinding) existing;
1283: if (existingType instanceof TypeVariableBinding) {
1284: blockScope.problemReporter().typeHiding(this ,
1285: (TypeVariableBinding) existingType);
1286: } else if (existingType instanceof LocalTypeBinding
1287: && ((LocalTypeBinding) existingType).scope
1288: .methodScope() == blockScope
1289: .methodScope()) {
1290: // dup in same method
1291: blockScope.problemReporter().duplicateNestedType(
1292: this );
1293: } else if (blockScope.isDefinedInType(existingType)) {
1294: // collision with enclosing type
1295: blockScope.problemReporter()
1296: .typeCollidesWithEnclosingType(this );
1297: } else if (blockScope.isDefinedInSameUnit(existingType)) { // only consider hiding inside same unit
1298: // hiding sibling
1299: blockScope.problemReporter().typeHiding(this ,
1300: existingType);
1301: }
1302: }
1303: blockScope.addLocalType(this );
1304: }
1305:
1306: if (this .binding != null) {
1307: // remember local types binding for innerclass emulation propagation
1308: blockScope.referenceCompilationUnit().record(
1309: (LocalTypeBinding) this .binding);
1310:
1311: // binding is not set if the receiver could not be created
1312: resolve();
1313: updateMaxFieldCount();
1314: }
1315: }
1316:
1317: /**
1318: * Resolve a member type declaration (can be a local member)
1319: */
1320: public void resolve(ClassScope upperScope) {
1321: // member scopes are already created
1322: // request the construction of a binding if local member type
1323:
1324: if (this .binding != null
1325: && this .binding instanceof LocalTypeBinding) {
1326: // remember local types binding for innerclass emulation propagation
1327: upperScope.referenceCompilationUnit().record(
1328: (LocalTypeBinding) this .binding);
1329: }
1330: resolve();
1331: updateMaxFieldCount();
1332: }
1333:
1334: /**
1335: * Resolve a top level type declaration
1336: */
1337: public void resolve(CompilationUnitScope upperScope) {
1338: // top level : scope are already created
1339: resolve();
1340: updateMaxFieldCount();
1341: }
1342:
1343: public void tagAsHavingErrors() {
1344: this .ignoreFurtherInvestigation = true;
1345: }
1346:
1347: /**
1348: * Iteration for a package member type
1349: *
1350: */
1351: public void traverse(ASTVisitor visitor,
1352: CompilationUnitScope unitScope) {
1353:
1354: if (this .ignoreFurtherInvestigation)
1355: return;
1356: try {
1357: if (visitor.visit(this , unitScope)) {
1358: if (this .javadoc != null) {
1359: this .javadoc.traverse(visitor, this .scope);
1360: }
1361: if (this .annotations != null) {
1362: int annotationsLength = this .annotations.length;
1363: for (int i = 0; i < annotationsLength; i++)
1364: this .annotations[i].traverse(visitor,
1365: this .staticInitializerScope);
1366: }
1367: if (this .super class != null)
1368: this .super class.traverse(visitor, this .scope);
1369: if (this .super Interfaces != null) {
1370: int length = this .super Interfaces.length;
1371: for (int i = 0; i < length; i++)
1372: this .super Interfaces[i].traverse(visitor,
1373: this .scope);
1374: }
1375: if (this .typeParameters != null) {
1376: int length = this .typeParameters.length;
1377: for (int i = 0; i < length; i++) {
1378: this .typeParameters[i].traverse(visitor,
1379: this .scope);
1380: }
1381: }
1382: if (this .memberTypes != null) {
1383: int length = this .memberTypes.length;
1384: for (int i = 0; i < length; i++)
1385: this .memberTypes[i].traverse(visitor,
1386: this .scope);
1387: }
1388: if (this .fields != null) {
1389: int length = this .fields.length;
1390: for (int i = 0; i < length; i++) {
1391: FieldDeclaration field;
1392: if ((field = this .fields[i]).isStatic()) {
1393: field.traverse(visitor,
1394: this .staticInitializerScope);
1395: } else {
1396: field.traverse(visitor,
1397: this .initializerScope);
1398: }
1399: }
1400: }
1401: if (this .methods != null) {
1402: int length = this .methods.length;
1403: for (int i = 0; i < length; i++)
1404: this .methods[i].traverse(visitor, this .scope);
1405: }
1406: }
1407: visitor.endVisit(this , unitScope);
1408: } catch (AbortType e) {
1409: // silent abort
1410: }
1411: }
1412:
1413: /**
1414: * Iteration for a local innertype
1415: */
1416: public void traverse(ASTVisitor visitor, BlockScope blockScope) {
1417: if (this .ignoreFurtherInvestigation)
1418: return;
1419: try {
1420: if (visitor.visit(this , blockScope)) {
1421: if (this .javadoc != null) {
1422: this .javadoc.traverse(visitor, this .scope);
1423: }
1424: if (this .annotations != null) {
1425: int annotationsLength = this .annotations.length;
1426: for (int i = 0; i < annotationsLength; i++)
1427: this .annotations[i].traverse(visitor,
1428: this .staticInitializerScope);
1429: }
1430: if (this .super class != null)
1431: this .super class.traverse(visitor, this .scope);
1432: if (this .super Interfaces != null) {
1433: int length = this .super Interfaces.length;
1434: for (int i = 0; i < length; i++)
1435: this .super Interfaces[i].traverse(visitor,
1436: this .scope);
1437: }
1438: if (this .typeParameters != null) {
1439: int length = this .typeParameters.length;
1440: for (int i = 0; i < length; i++) {
1441: this .typeParameters[i].traverse(visitor,
1442: this .scope);
1443: }
1444: }
1445: if (this .memberTypes != null) {
1446: int length = this .memberTypes.length;
1447: for (int i = 0; i < length; i++)
1448: this .memberTypes[i].traverse(visitor,
1449: this .scope);
1450: }
1451: if (this .fields != null) {
1452: int length = this .fields.length;
1453: for (int i = 0; i < length; i++) {
1454: FieldDeclaration field;
1455: if ((field = this .fields[i]).isStatic()) {
1456: // local type cannot have static fields
1457: } else {
1458: field.traverse(visitor,
1459: this .initializerScope);
1460: }
1461: }
1462: }
1463: if (this .methods != null) {
1464: int length = this .methods.length;
1465: for (int i = 0; i < length; i++)
1466: this .methods[i].traverse(visitor, this .scope);
1467: }
1468: }
1469: visitor.endVisit(this , blockScope);
1470: } catch (AbortType e) {
1471: // silent abort
1472: }
1473: }
1474:
1475: /**
1476: * Iteration for a member innertype
1477: *
1478: */
1479: public void traverse(ASTVisitor visitor, ClassScope classScope) {
1480: if (this .ignoreFurtherInvestigation)
1481: return;
1482: try {
1483: if (visitor.visit(this , classScope)) {
1484: if (this .javadoc != null) {
1485: this .javadoc.traverse(visitor, scope);
1486: }
1487: if (this .annotations != null) {
1488: int annotationsLength = this .annotations.length;
1489: for (int i = 0; i < annotationsLength; i++)
1490: this .annotations[i].traverse(visitor,
1491: this .staticInitializerScope);
1492: }
1493: if (this .super class != null)
1494: this .super class.traverse(visitor, this .scope);
1495: if (this .super Interfaces != null) {
1496: int length = this .super Interfaces.length;
1497: for (int i = 0; i < length; i++)
1498: this .super Interfaces[i].traverse(visitor,
1499: this .scope);
1500: }
1501: if (this .typeParameters != null) {
1502: int length = this .typeParameters.length;
1503: for (int i = 0; i < length; i++) {
1504: this .typeParameters[i].traverse(visitor,
1505: this .scope);
1506: }
1507: }
1508: if (this .memberTypes != null) {
1509: int length = this .memberTypes.length;
1510: for (int i = 0; i < length; i++)
1511: this .memberTypes[i].traverse(visitor,
1512: this .scope);
1513: }
1514: if (this .fields != null) {
1515: int length = this .fields.length;
1516: for (int i = 0; i < length; i++) {
1517: FieldDeclaration field;
1518: if ((field = this .fields[i]).isStatic()) {
1519: field.traverse(visitor,
1520: this .staticInitializerScope);
1521: } else {
1522: field.traverse(visitor,
1523: this .initializerScope);
1524: }
1525: }
1526: }
1527: if (this .methods != null) {
1528: int length = this .methods.length;
1529: for (int i = 0; i < length; i++)
1530: this .methods[i].traverse(visitor, this .scope);
1531: }
1532: }
1533: visitor.endVisit(this , classScope);
1534: } catch (AbortType e) {
1535: // silent abort
1536: }
1537: }
1538:
1539: /**
1540: * MaxFieldCount's computation is necessary so as to reserve space for
1541: * the flow info field portions. It corresponds to the maximum amount of
1542: * fields this class or one of its innertypes have.
1543: *
1544: * During name resolution, types are traversed, and the max field count is recorded
1545: * on the outermost type. It is then propagated down during the flow analysis.
1546: *
1547: * This method is doing either up/down propagation.
1548: */
1549: void updateMaxFieldCount() {
1550: if (this .binding == null)
1551: return; // error scenario
1552: TypeDeclaration outerMostType = this .scope
1553: .outerMostClassScope().referenceType();
1554: if (this .maxFieldCount > outerMostType.maxFieldCount) {
1555: outerMostType.maxFieldCount = this .maxFieldCount; // up
1556: } else {
1557: this .maxFieldCount = outerMostType.maxFieldCount; // down
1558: }
1559: }
1560:
1561: /**
1562: * Returns whether the type is a secondary one or not.
1563: */
1564: public boolean isSecondary() {
1565: return (this .bits & ASTNode.IsSecondaryType) != 0;
1566: }
1567: }
|