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.lookup;
0011:
0012: import java.util.HashMap;
0013: import java.util.Hashtable;
0014: import java.util.Iterator;
0015:
0016: import org.eclipse.jdt.core.compiler.CharOperation;
0017: import org.eclipse.jdt.internal.compiler.ast.ASTNode;
0018: import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
0019: import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
0020: import org.eclipse.jdt.internal.compiler.ast.Argument;
0021: import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
0022: import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
0023: import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
0024: import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
0025: import org.eclipse.jdt.internal.compiler.ast.TypeReference;
0026: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
0027: import org.eclipse.jdt.internal.compiler.impl.Constant;
0028: import org.eclipse.jdt.internal.compiler.util.Util;
0029: import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
0030:
0031: public class SourceTypeBinding extends ReferenceBinding {
0032: public ReferenceBinding super class;
0033: public ReferenceBinding[] super Interfaces;
0034: private FieldBinding[] fields;
0035: private MethodBinding[] methods;
0036: public ReferenceBinding[] memberTypes;
0037: public TypeVariableBinding[] typeVariables;
0038:
0039: public ClassScope scope;
0040:
0041: // Synthetics are separated into 5 categories: methods, super methods, fields, class literals, changed declaring type bindings and bridge methods
0042: public final static int METHOD_EMUL = 0;
0043: public final static int FIELD_EMUL = 1;
0044: public final static int CLASS_LITERAL_EMUL = 2;
0045: public final static int RECEIVER_TYPE_EMUL = 3;
0046: HashMap[] synthetics;
0047: char[] genericReferenceTypeSignature;
0048:
0049: private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
0050:
0051: public SourceTypeBinding(char[][] compoundName,
0052: PackageBinding fPackage, ClassScope scope) {
0053: this .compoundName = compoundName;
0054: this .fPackage = fPackage;
0055: this .fileName = scope.referenceCompilationUnit().getFileName();
0056: this .modifiers = scope.referenceContext.modifiers;
0057: this .sourceName = scope.referenceContext.name;
0058: this .scope = scope;
0059:
0060: // expect the fields & methods to be initialized correctly later
0061: this .fields = Binding.NO_FIELDS;
0062: this .methods = Binding.NO_METHODS;
0063:
0064: computeId();
0065: }
0066:
0067: private void addDefaultAbstractMethods() {
0068: if ((this .tagBits & TagBits.KnowsDefaultAbstractMethods) != 0)
0069: return;
0070:
0071: this .tagBits |= TagBits.KnowsDefaultAbstractMethods;
0072: if (isClass() && isAbstract()) {
0073: if (this .scope.compilerOptions().targetJDK >= ClassFileConstants.JDK1_2)
0074: return; // no longer added for post 1.2 targets
0075:
0076: ReferenceBinding[] itsInterfaces = super Interfaces();
0077: if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
0078: MethodBinding[] defaultAbstracts = null;
0079: int defaultAbstractsCount = 0;
0080: ReferenceBinding[] interfacesToVisit = itsInterfaces;
0081: int nextPosition = interfacesToVisit.length;
0082: for (int i = 0; i < nextPosition; i++) {
0083: ReferenceBinding super Type = interfacesToVisit[i];
0084: if (super Type.isValidBinding()) {
0085: MethodBinding[] super Methods = super Type
0086: .methods();
0087: nextAbstractMethod: for (int m = super Methods.length; --m >= 0;) {
0088: MethodBinding method = super Methods[m];
0089: // explicitly implemented ?
0090: if (implements Method(method))
0091: continue nextAbstractMethod;
0092: if (defaultAbstractsCount == 0) {
0093: defaultAbstracts = new MethodBinding[5];
0094: } else {
0095: // already added as default abstract ?
0096: for (int k = 0; k < defaultAbstractsCount; k++) {
0097: MethodBinding alreadyAdded = defaultAbstracts[k];
0098: if (CharOperation.equals(
0099: alreadyAdded.selector,
0100: method.selector)
0101: && alreadyAdded
0102: .areParametersEqual(method))
0103: continue nextAbstractMethod;
0104: }
0105: }
0106: MethodBinding defaultAbstract = new MethodBinding(
0107: method.modifiers
0108: | ExtraCompilerModifiers.AccDefaultAbstract,
0109: method.selector, method.returnType,
0110: method.parameters,
0111: method.thrownExceptions, this );
0112: if (defaultAbstractsCount == defaultAbstracts.length)
0113: System
0114: .arraycopy(
0115: defaultAbstracts,
0116: 0,
0117: defaultAbstracts = new MethodBinding[2 * defaultAbstractsCount],
0118: 0,
0119: defaultAbstractsCount);
0120: defaultAbstracts[defaultAbstractsCount++] = defaultAbstract;
0121: }
0122:
0123: if ((itsInterfaces = super Type
0124: .super Interfaces()) != Binding.NO_SUPERINTERFACES) {
0125: int itsLength = itsInterfaces.length;
0126: if (nextPosition + itsLength >= interfacesToVisit.length)
0127: System
0128: .arraycopy(
0129: interfacesToVisit,
0130: 0,
0131: interfacesToVisit = new ReferenceBinding[nextPosition
0132: + itsLength + 5],
0133: 0, nextPosition);
0134: nextInterface: for (int a = 0; a < itsLength; a++) {
0135: ReferenceBinding next = itsInterfaces[a];
0136: for (int b = 0; b < nextPosition; b++)
0137: if (next == interfacesToVisit[b])
0138: continue nextInterface;
0139: interfacesToVisit[nextPosition++] = next;
0140: }
0141: }
0142: }
0143: }
0144: if (defaultAbstractsCount > 0) {
0145: int length = this .methods.length;
0146: System
0147: .arraycopy(
0148: this .methods,
0149: 0,
0150: this .methods = new MethodBinding[length
0151: + defaultAbstractsCount],
0152: 0, length);
0153: System.arraycopy(defaultAbstracts, 0, this .methods,
0154: length, defaultAbstractsCount);
0155: // re-sort methods
0156: length = length + defaultAbstractsCount;
0157: if (length > 1)
0158: ReferenceBinding.sortMethods(this .methods, 0,
0159: length);
0160: // this.tagBits |= TagBits.AreMethodsSorted; -- already set in #methods()
0161: }
0162: }
0163: }
0164: }
0165:
0166: /* Add a new synthetic field for <actualOuterLocalVariable>.
0167: * Answer the new field or the existing field if one already existed.
0168: */
0169: public FieldBinding addSyntheticFieldForInnerclass(
0170: LocalVariableBinding actualOuterLocalVariable) {
0171: if (this .synthetics == null)
0172: this .synthetics = new HashMap[4];
0173: if (this .synthetics[SourceTypeBinding.FIELD_EMUL] == null)
0174: this .synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(
0175: 5);
0176:
0177: FieldBinding synthField = (FieldBinding) this .synthetics[SourceTypeBinding.FIELD_EMUL]
0178: .get(actualOuterLocalVariable);
0179: if (synthField == null) {
0180: synthField = new SyntheticFieldBinding(CharOperation
0181: .concat(TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX,
0182: actualOuterLocalVariable.name),
0183: actualOuterLocalVariable.type,
0184: ClassFileConstants.AccPrivate
0185: | ClassFileConstants.AccFinal
0186: | ClassFileConstants.AccSynthetic, this ,
0187: Constant.NotAConstant,
0188: this .synthetics[SourceTypeBinding.FIELD_EMUL]
0189: .size());
0190: this .synthetics[SourceTypeBinding.FIELD_EMUL].put(
0191: actualOuterLocalVariable, synthField);
0192: }
0193:
0194: // ensure there is not already such a field defined by the user
0195: boolean needRecheck;
0196: int index = 1;
0197: do {
0198: needRecheck = false;
0199: FieldBinding existingField;
0200: if ((existingField = this
0201: .getField(synthField.name, true /*resolve*/)) != null) {
0202: TypeDeclaration typeDecl = this .scope.referenceContext;
0203: for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
0204: FieldDeclaration fieldDecl = typeDecl.fields[i];
0205: if (fieldDecl.binding == existingField) {
0206: synthField.name = CharOperation
0207: .concat(
0208: TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX,
0209: actualOuterLocalVariable.name,
0210: ("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
0211: needRecheck = true;
0212: break;
0213: }
0214: }
0215: }
0216: } while (needRecheck);
0217: return synthField;
0218: }
0219:
0220: /* Add a new synthetic field for <enclosingType>.
0221: * Answer the new field or the existing field if one already existed.
0222: */
0223: public FieldBinding addSyntheticFieldForInnerclass(
0224: ReferenceBinding enclosingType) {
0225: if (this .synthetics == null)
0226: this .synthetics = new HashMap[4];
0227: if (this .synthetics[SourceTypeBinding.FIELD_EMUL] == null)
0228: this .synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(
0229: 5);
0230:
0231: FieldBinding synthField = (FieldBinding) this .synthetics[SourceTypeBinding.FIELD_EMUL]
0232: .get(enclosingType);
0233: if (synthField == null) {
0234: synthField = new SyntheticFieldBinding(
0235: CharOperation
0236: .concat(
0237: TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX,
0238: String.valueOf(
0239: enclosingType.depth())
0240: .toCharArray()),
0241: enclosingType, ClassFileConstants.AccDefault
0242: | ClassFileConstants.AccFinal
0243: | ClassFileConstants.AccSynthetic, this ,
0244: Constant.NotAConstant,
0245: this .synthetics[SourceTypeBinding.FIELD_EMUL]
0246: .size());
0247: this .synthetics[SourceTypeBinding.FIELD_EMUL].put(
0248: enclosingType, synthField);
0249: }
0250: // ensure there is not already such a field defined by the user
0251: boolean needRecheck;
0252: do {
0253: needRecheck = false;
0254: FieldBinding existingField;
0255: if ((existingField = this
0256: .getField(synthField.name, true /*resolve*/)) != null) {
0257: TypeDeclaration typeDecl = this .scope.referenceContext;
0258: for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
0259: FieldDeclaration fieldDecl = typeDecl.fields[i];
0260: if (fieldDecl.binding == existingField) {
0261: if (this .scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5) {
0262: synthField.name = CharOperation.concat(
0263: synthField.name, "$".toCharArray()); //$NON-NLS-1$
0264: needRecheck = true;
0265: } else {
0266: this .scope.problemReporter()
0267: .duplicateFieldInType(this ,
0268: fieldDecl);
0269: }
0270: break;
0271: }
0272: }
0273: }
0274: } while (needRecheck);
0275: return synthField;
0276: }
0277:
0278: /* Add a new synthetic field for a class literal access.
0279: * Answer the new field or the existing field if one already existed.
0280: */
0281: public FieldBinding addSyntheticFieldForClassLiteral(
0282: TypeBinding targetType, BlockScope blockScope) {
0283: if (this .synthetics == null)
0284: this .synthetics = new HashMap[4];
0285: if (this .synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] == null)
0286: this .synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] = new HashMap(
0287: 5);
0288:
0289: // use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
0290: FieldBinding synthField = (FieldBinding) this .synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL]
0291: .get(targetType);
0292: if (synthField == null) {
0293: synthField = new SyntheticFieldBinding(
0294: CharOperation
0295: .concat(
0296: TypeConstants.SYNTHETIC_CLASS,
0297: String
0298: .valueOf(
0299: this .synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL]
0300: .size())
0301: .toCharArray()),
0302: blockScope.getJavaLangClass(),
0303: ClassFileConstants.AccDefault
0304: | ClassFileConstants.AccStatic
0305: | ClassFileConstants.AccSynthetic,
0306: this ,
0307: Constant.NotAConstant,
0308: this .synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL]
0309: .size());
0310: this .synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].put(
0311: targetType, synthField);
0312: }
0313: // ensure there is not already such a field defined by the user
0314: FieldBinding existingField;
0315: if ((existingField = this
0316: .getField(synthField.name, true /*resolve*/)) != null) {
0317: TypeDeclaration typeDecl = blockScope.referenceType();
0318: for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
0319: FieldDeclaration fieldDecl = typeDecl.fields[i];
0320: if (fieldDecl.binding == existingField) {
0321: blockScope.problemReporter().duplicateFieldInType(
0322: this , fieldDecl);
0323: break;
0324: }
0325: }
0326: }
0327: return synthField;
0328: }
0329:
0330: /* Add a new synthetic field for the emulation of the assert statement.
0331: * Answer the new field or the existing field if one already existed.
0332: */
0333: public FieldBinding addSyntheticFieldForAssert(BlockScope blockScope) {
0334: if (this .synthetics == null)
0335: this .synthetics = new HashMap[4];
0336: if (this .synthetics[SourceTypeBinding.FIELD_EMUL] == null)
0337: this .synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(
0338: 5);
0339:
0340: FieldBinding synthField = (FieldBinding) this .synthetics[SourceTypeBinding.FIELD_EMUL]
0341: .get("assertionEmulation"); //$NON-NLS-1$
0342: if (synthField == null) {
0343: synthField = new SyntheticFieldBinding(
0344: TypeConstants.SYNTHETIC_ASSERT_DISABLED,
0345: TypeBinding.BOOLEAN, ClassFileConstants.AccDefault
0346: | ClassFileConstants.AccStatic
0347: | ClassFileConstants.AccSynthetic
0348: | ClassFileConstants.AccFinal, this ,
0349: Constant.NotAConstant,
0350: this .synthetics[SourceTypeBinding.FIELD_EMUL]
0351: .size());
0352: this .synthetics[SourceTypeBinding.FIELD_EMUL].put(
0353: "assertionEmulation", synthField); //$NON-NLS-1$
0354: }
0355: // ensure there is not already such a field defined by the user
0356: // ensure there is not already such a field defined by the user
0357: boolean needRecheck;
0358: int index = 0;
0359: do {
0360: needRecheck = false;
0361: FieldBinding existingField;
0362: if ((existingField = this
0363: .getField(synthField.name, true /*resolve*/)) != null) {
0364: TypeDeclaration typeDecl = this .scope.referenceContext;
0365: for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
0366: FieldDeclaration fieldDecl = typeDecl.fields[i];
0367: if (fieldDecl.binding == existingField) {
0368: synthField.name = CharOperation
0369: .concat(
0370: TypeConstants.SYNTHETIC_ASSERT_DISABLED,
0371: ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
0372: needRecheck = true;
0373: break;
0374: }
0375: }
0376: }
0377: } while (needRecheck);
0378: return synthField;
0379: }
0380:
0381: /* Add a new synthetic field for recording all enum constant values
0382: * Answer the new field or the existing field if one already existed.
0383: */
0384: public FieldBinding addSyntheticFieldForEnumValues() {
0385: if (this .synthetics == null)
0386: this .synthetics = new HashMap[4];
0387: if (this .synthetics[SourceTypeBinding.FIELD_EMUL] == null)
0388: this .synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(
0389: 5);
0390:
0391: FieldBinding synthField = (FieldBinding) this .synthetics[SourceTypeBinding.FIELD_EMUL]
0392: .get("enumConstantValues"); //$NON-NLS-1$
0393: if (synthField == null) {
0394: synthField = new SyntheticFieldBinding(
0395: TypeConstants.SYNTHETIC_ENUM_VALUES, this .scope
0396: .createArrayType(this , 1),
0397: ClassFileConstants.AccPrivate
0398: | ClassFileConstants.AccStatic
0399: | ClassFileConstants.AccSynthetic
0400: | ClassFileConstants.AccFinal, this ,
0401: Constant.NotAConstant,
0402: this .synthetics[SourceTypeBinding.FIELD_EMUL]
0403: .size());
0404: this .synthetics[SourceTypeBinding.FIELD_EMUL].put(
0405: "enumConstantValues", synthField); //$NON-NLS-1$
0406: }
0407: // ensure there is not already such a field defined by the user
0408: // ensure there is not already such a field defined by the user
0409: boolean needRecheck;
0410: int index = 0;
0411: do {
0412: needRecheck = false;
0413: FieldBinding existingField;
0414: if ((existingField = this
0415: .getField(synthField.name, true /*resolve*/)) != null) {
0416: TypeDeclaration typeDecl = this .scope.referenceContext;
0417: for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
0418: FieldDeclaration fieldDecl = typeDecl.fields[i];
0419: if (fieldDecl.binding == existingField) {
0420: synthField.name = CharOperation
0421: .concat(
0422: TypeConstants.SYNTHETIC_ENUM_VALUES,
0423: ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
0424: needRecheck = true;
0425: break;
0426: }
0427: }
0428: }
0429: } while (needRecheck);
0430: return synthField;
0431: }
0432:
0433: /* Add a new synthetic access method for read/write access to <targetField>.
0434: Answer the new method or the existing method if one already existed.
0435: */
0436: public SyntheticMethodBinding addSyntheticMethod(
0437: FieldBinding targetField, boolean isReadAccess) {
0438: if (this .synthetics == null)
0439: this .synthetics = new HashMap[4];
0440: if (this .synthetics[SourceTypeBinding.METHOD_EMUL] == null)
0441: this .synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(
0442: 5);
0443:
0444: SyntheticMethodBinding accessMethod = null;
0445: SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this .synthetics[SourceTypeBinding.METHOD_EMUL]
0446: .get(targetField);
0447: if (accessors == null) {
0448: accessMethod = new SyntheticMethodBinding(targetField,
0449: isReadAccess, this );
0450: this .synthetics[SourceTypeBinding.METHOD_EMUL].put(
0451: targetField,
0452: accessors = new SyntheticMethodBinding[2]);
0453: accessors[isReadAccess ? 0 : 1] = accessMethod;
0454: } else {
0455: if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
0456: accessMethod = new SyntheticMethodBinding(targetField,
0457: isReadAccess, this );
0458: accessors[isReadAccess ? 0 : 1] = accessMethod;
0459: }
0460: }
0461: return accessMethod;
0462: }
0463:
0464: /* Add a new synthetic method the enum type. Selector can either be 'values' or 'valueOf'.
0465: * char[] constants from TypeConstants must be used: TypeConstants.VALUES/VALUEOF
0466: */
0467: public SyntheticMethodBinding addSyntheticEnumMethod(char[] selector) {
0468: if (this .synthetics == null)
0469: this .synthetics = new HashMap[4];
0470: if (this .synthetics[SourceTypeBinding.METHOD_EMUL] == null)
0471: this .synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(
0472: 5);
0473:
0474: SyntheticMethodBinding accessMethod = null;
0475: SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this .synthetics[SourceTypeBinding.METHOD_EMUL]
0476: .get(selector);
0477: if (accessors == null) {
0478: accessMethod = new SyntheticMethodBinding(this , selector);
0479: this .synthetics[SourceTypeBinding.METHOD_EMUL]
0480: .put(selector,
0481: accessors = new SyntheticMethodBinding[2]);
0482: accessors[0] = accessMethod;
0483: } else {
0484: if ((accessMethod = accessors[0]) == null) {
0485: accessMethod = new SyntheticMethodBinding(this ,
0486: selector);
0487: accessors[0] = accessMethod;
0488: }
0489: }
0490: return accessMethod;
0491: }
0492:
0493: /*
0494: * Add a synthetic field to handle the cache of the switch translation table for the corresponding enum type
0495: */
0496: public SyntheticFieldBinding addSyntheticFieldForSwitchEnum(
0497: char[] fieldName, String key) {
0498: if (this .synthetics == null)
0499: this .synthetics = new HashMap[4];
0500: if (this .synthetics[SourceTypeBinding.FIELD_EMUL] == null)
0501: this .synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(
0502: 5);
0503:
0504: SyntheticFieldBinding synthField = (SyntheticFieldBinding) this .synthetics[SourceTypeBinding.FIELD_EMUL]
0505: .get(key);
0506: if (synthField == null) {
0507: synthField = new SyntheticFieldBinding(fieldName,
0508: this .scope.createArrayType(TypeBinding.INT, 1),
0509: ClassFileConstants.AccPrivate
0510: | ClassFileConstants.AccStatic
0511: | ClassFileConstants.AccSynthetic, this ,
0512: Constant.NotAConstant,
0513: this .synthetics[SourceTypeBinding.FIELD_EMUL]
0514: .size());
0515: this .synthetics[SourceTypeBinding.FIELD_EMUL].put(key,
0516: synthField);
0517: }
0518: // ensure there is not already such a field defined by the user
0519: boolean needRecheck;
0520: int index = 0;
0521: do {
0522: needRecheck = false;
0523: FieldBinding existingField;
0524: if ((existingField = this
0525: .getField(synthField.name, true /*resolve*/)) != null) {
0526: TypeDeclaration typeDecl = this .scope.referenceContext;
0527: for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
0528: FieldDeclaration fieldDecl = typeDecl.fields[i];
0529: if (fieldDecl.binding == existingField) {
0530: synthField.name = CharOperation
0531: .concat(
0532: fieldName,
0533: ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
0534: needRecheck = true;
0535: break;
0536: }
0537: }
0538: }
0539: } while (needRecheck);
0540: return synthField;
0541: }
0542:
0543: /* Add a new synthetic method the enum type. Selector can either be 'values' or 'valueOf'.
0544: * char[] constants from TypeConstants must be used: TypeConstants.VALUES/VALUEOF
0545: */
0546: public SyntheticMethodBinding addSyntheticMethodForSwitchEnum(
0547: TypeBinding enumBinding) {
0548: if (this .synthetics == null)
0549: this .synthetics = new HashMap[4];
0550: if (this .synthetics[SourceTypeBinding.METHOD_EMUL] == null)
0551: this .synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(
0552: 5);
0553:
0554: SyntheticMethodBinding accessMethod = null;
0555: char[] selector = CharOperation.concat(
0556: TypeConstants.SYNTHETIC_SWITCH_ENUM_TABLE, enumBinding
0557: .constantPoolName());
0558: CharOperation.replace(selector, '/', '$');
0559: final String key = new String(selector);
0560: SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this .synthetics[SourceTypeBinding.METHOD_EMUL]
0561: .get(key);
0562: // first add the corresponding synthetic field
0563: if (accessors == null) {
0564: // then create the synthetic method
0565: final SyntheticFieldBinding fieldBinding = this
0566: .addSyntheticFieldForSwitchEnum(selector, key);
0567: accessMethod = new SyntheticMethodBinding(fieldBinding,
0568: this , enumBinding, selector);
0569: this .synthetics[SourceTypeBinding.METHOD_EMUL].put(key,
0570: accessors = new SyntheticMethodBinding[2]);
0571: accessors[0] = accessMethod;
0572: } else {
0573: if ((accessMethod = accessors[0]) == null) {
0574: final SyntheticFieldBinding fieldBinding = this
0575: .addSyntheticFieldForSwitchEnum(selector, key);
0576: accessMethod = new SyntheticMethodBinding(fieldBinding,
0577: this , enumBinding, selector);
0578: accessors[0] = accessMethod;
0579: }
0580: }
0581: return accessMethod;
0582: }
0583:
0584: /* Add a new synthetic access method for access to <targetMethod>.
0585: * Must distinguish access method used for super access from others (need to use invokespecial bytecode)
0586: Answer the new method or the existing method if one already existed.
0587: */
0588: public SyntheticMethodBinding addSyntheticMethod(
0589: MethodBinding targetMethod, boolean isSuperAccess) {
0590: if (this .synthetics == null)
0591: this .synthetics = new HashMap[4];
0592: if (this .synthetics[SourceTypeBinding.METHOD_EMUL] == null)
0593: this .synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(
0594: 5);
0595:
0596: SyntheticMethodBinding accessMethod = null;
0597: SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this .synthetics[SourceTypeBinding.METHOD_EMUL]
0598: .get(targetMethod);
0599: if (accessors == null) {
0600: accessMethod = new SyntheticMethodBinding(targetMethod,
0601: isSuperAccess, this );
0602: this .synthetics[SourceTypeBinding.METHOD_EMUL].put(
0603: targetMethod,
0604: accessors = new SyntheticMethodBinding[2]);
0605: accessors[isSuperAccess ? 0 : 1] = accessMethod;
0606: } else {
0607: if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
0608: accessMethod = new SyntheticMethodBinding(targetMethod,
0609: isSuperAccess, this );
0610: accessors[isSuperAccess ? 0 : 1] = accessMethod;
0611: }
0612: }
0613: return accessMethod;
0614: }
0615:
0616: /*
0617: * Record the fact that bridge methods need to be generated to override certain inherited methods
0618: */
0619: public SyntheticMethodBinding addSyntheticBridgeMethod(
0620: MethodBinding inheritedMethodToBridge,
0621: MethodBinding targetMethod) {
0622: if (isInterface())
0623: return null; // only classes & enums get bridge methods
0624: // targetMethod may be inherited
0625: if (inheritedMethodToBridge.returnType.erasure() == targetMethod.returnType
0626: .erasure()
0627: && inheritedMethodToBridge
0628: .areParameterErasuresEqual(targetMethod)) {
0629: return null; // do not need bridge method
0630: }
0631: if (this .synthetics == null)
0632: this .synthetics = new HashMap[4];
0633: if (this .synthetics[SourceTypeBinding.METHOD_EMUL] == null) {
0634: this .synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(
0635: 5);
0636: } else {
0637: // check to see if there is another equivalent inheritedMethod already added
0638: Iterator synthMethods = this .synthetics[SourceTypeBinding.METHOD_EMUL]
0639: .keySet().iterator();
0640: while (synthMethods.hasNext()) {
0641: Object synthetic = synthMethods.next();
0642: if (synthetic instanceof MethodBinding) {
0643: MethodBinding method = (MethodBinding) synthetic;
0644: if (CharOperation.equals(
0645: inheritedMethodToBridge.selector,
0646: method.selector)
0647: && inheritedMethodToBridge.returnType
0648: .erasure() == method.returnType
0649: .erasure()
0650: && inheritedMethodToBridge
0651: .areParameterErasuresEqual(method)) {
0652: return null;
0653: }
0654: }
0655: }
0656: }
0657:
0658: SyntheticMethodBinding accessMethod = null;
0659: SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this .synthetics[SourceTypeBinding.METHOD_EMUL]
0660: .get(inheritedMethodToBridge);
0661: if (accessors == null) {
0662: accessMethod = new SyntheticMethodBinding(
0663: inheritedMethodToBridge, targetMethod, this );
0664: this .synthetics[SourceTypeBinding.METHOD_EMUL].put(
0665: inheritedMethodToBridge,
0666: accessors = new SyntheticMethodBinding[2]);
0667: accessors[1] = accessMethod;
0668: } else {
0669: if ((accessMethod = accessors[1]) == null) {
0670: accessMethod = new SyntheticMethodBinding(
0671: inheritedMethodToBridge, targetMethod, this );
0672: accessors[1] = accessMethod;
0673: }
0674: }
0675: return accessMethod;
0676: }
0677:
0678: public int kind() {
0679: if (this .typeVariables != Binding.NO_TYPE_VARIABLES)
0680: return Binding.GENERIC_TYPE;
0681: return Binding.TYPE;
0682: }
0683:
0684: public char[] computeUniqueKey(boolean isLeaf) {
0685: char[] uniqueKey = super .computeUniqueKey(isLeaf);
0686: if (uniqueKey.length == 2)
0687: return uniqueKey; // problem type's unique key is "L;"
0688: if (Util.isClassFileName(this .fileName))
0689: return uniqueKey; // no need to insert compilation unit name for a .class file
0690:
0691: // insert compilation unit name if the type name is not the main type name
0692: int end = CharOperation.lastIndexOf('.', this .fileName);
0693: if (end != -1) {
0694: int start = CharOperation.lastIndexOf('/', this .fileName) + 1;
0695: char[] mainTypeName = CharOperation.subarray(this .fileName,
0696: start, end);
0697: start = CharOperation.lastIndexOf('/', uniqueKey) + 1;
0698: if (start == 0)
0699: start = 1; // start after L
0700: end = CharOperation.indexOf('$', uniqueKey, start);
0701: if (end == -1)
0702: end = CharOperation.indexOf('<', uniqueKey, start);
0703: if (end == -1)
0704: end = CharOperation.indexOf(';', uniqueKey, start);
0705: char[] topLevelType = CharOperation.subarray(uniqueKey,
0706: start, end);
0707: if (!CharOperation.equals(topLevelType, mainTypeName)) {
0708: StringBuffer buffer = new StringBuffer();
0709: buffer.append(uniqueKey, 0, start);
0710: buffer.append(mainTypeName);
0711: buffer.append('~');
0712: buffer.append(topLevelType);
0713: buffer.append(uniqueKey, end, uniqueKey.length - end);
0714: int length = buffer.length();
0715: uniqueKey = new char[length];
0716: buffer.getChars(0, length, uniqueKey, 0);
0717: return uniqueKey;
0718: }
0719: }
0720: return uniqueKey;
0721: }
0722:
0723: void faultInTypesForFieldsAndMethods() {
0724: // check @Deprecated annotation
0725: getAnnotationTagBits(); // marks as deprecated by side effect
0726: ReferenceBinding enclosingType = this .enclosingType();
0727: if (enclosingType != null
0728: && enclosingType.isViewedAsDeprecated()
0729: && !this .isDeprecated())
0730: this .modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
0731: fields();
0732: methods();
0733:
0734: for (int i = 0, length = this .memberTypes.length; i < length; i++)
0735: ((SourceTypeBinding) this .memberTypes[i])
0736: .faultInTypesForFieldsAndMethods();
0737: }
0738:
0739: // NOTE: the type of each field of a source type is resolved when needed
0740: public FieldBinding[] fields() {
0741: if ((this .tagBits & TagBits.AreFieldsComplete) != 0)
0742: return this .fields;
0743:
0744: int failed = 0;
0745: FieldBinding[] resolvedFields = this .fields;
0746: try {
0747: // lazily sort fields
0748: if ((this .tagBits & TagBits.AreFieldsSorted) == 0) {
0749: int length = this .fields.length;
0750: if (length > 1)
0751: ReferenceBinding.sortFields(this .fields, 0, length);
0752: this .tagBits |= TagBits.AreFieldsSorted;
0753: }
0754: for (int i = 0, length = this .fields.length; i < length; i++) {
0755: if (resolveTypeFor(this .fields[i]) == null) {
0756: // do not alter original field array until resolution is over, due to reentrance (143259)
0757: if (resolvedFields == this .fields) {
0758: System
0759: .arraycopy(
0760: this .fields,
0761: 0,
0762: resolvedFields = new FieldBinding[length],
0763: 0, length);
0764: }
0765: resolvedFields[i] = null;
0766: failed++;
0767: }
0768: }
0769: } finally {
0770: if (failed > 0) {
0771: // ensure fields are consistent reqardless of the error
0772: int newSize = resolvedFields.length - failed;
0773: if (newSize == 0)
0774: return this .fields = Binding.NO_FIELDS;
0775:
0776: FieldBinding[] newFields = new FieldBinding[newSize];
0777: for (int i = 0, j = 0, length = resolvedFields.length; i < length; i++) {
0778: if (resolvedFields[i] != null)
0779: newFields[j++] = resolvedFields[i];
0780: }
0781: this .fields = newFields;
0782: }
0783: }
0784: this .tagBits |= TagBits.AreFieldsComplete;
0785: return this .fields;
0786: }
0787:
0788: /**
0789: * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#genericTypeSignature()
0790: */
0791: public char[] genericTypeSignature() {
0792: if (this .genericReferenceTypeSignature == null)
0793: this .genericReferenceTypeSignature = computeGenericTypeSignature(this .typeVariables);
0794: return this .genericReferenceTypeSignature;
0795: }
0796:
0797: /**
0798: * <param1 ... paramN>superclass superinterface1 ... superinterfaceN
0799: * <T:LY<TT;>;U:Ljava/lang/Object;V::Ljava/lang/Runnable;:Ljava/lang/Cloneable;:Ljava/util/Map;>Ljava/lang/Exception;Ljava/lang/Runnable;
0800: */
0801: public char[] genericSignature() {
0802: StringBuffer sig = null;
0803: if (this .typeVariables != Binding.NO_TYPE_VARIABLES) {
0804: sig = new StringBuffer(10);
0805: sig.append('<');
0806: for (int i = 0, length = this .typeVariables.length; i < length; i++)
0807: sig.append(this .typeVariables[i].genericSignature());
0808: sig.append('>');
0809: } else {
0810: // could still need a signature if any of supertypes is parameterized
0811: noSignature: if (this .super class == null
0812: || !this .super class.isParameterizedType()) {
0813: for (int i = 0, length = this .super Interfaces.length; i < length; i++)
0814: if (this .super Interfaces[i].isParameterizedType())
0815: break noSignature;
0816: return null;
0817: }
0818: sig = new StringBuffer(10);
0819: }
0820: if (this .super class != null)
0821: sig.append(this .super class.genericTypeSignature());
0822: else
0823: // interface scenario only (as Object cannot be generic) - 65953
0824: sig.append(this .scope.getJavaLangObject()
0825: .genericTypeSignature());
0826: for (int i = 0, length = this .super Interfaces.length; i < length; i++)
0827: sig.append(this .super Interfaces[i].genericTypeSignature());
0828: return sig.toString().toCharArray();
0829: }
0830:
0831: /**
0832: * Compute the tagbits for standard annotations. For source types, these could require
0833: * lazily resolving corresponding annotation nodes, in case of forward references.
0834: * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
0835: */
0836: public long getAnnotationTagBits() {
0837: if ((this .tagBits & TagBits.AnnotationResolved) == 0
0838: && this .scope != null) {
0839: TypeDeclaration typeDecl = this .scope.referenceContext;
0840: boolean old = typeDecl.staticInitializerScope.insideTypeAnnotation;
0841: try {
0842: typeDecl.staticInitializerScope.insideTypeAnnotation = true;
0843: ASTNode.resolveAnnotations(
0844: typeDecl.staticInitializerScope,
0845: typeDecl.annotations, this );
0846: } finally {
0847: typeDecl.staticInitializerScope.insideTypeAnnotation = old;
0848: }
0849: if ((this .tagBits & TagBits.AnnotationDeprecated) != 0)
0850: this .modifiers |= ClassFileConstants.AccDeprecated;
0851: }
0852: return this .tagBits;
0853: }
0854:
0855: public MethodBinding[] getDefaultAbstractMethods() {
0856: int count = 0;
0857: for (int i = this .methods.length; --i >= 0;)
0858: if (this .methods[i].isDefaultAbstract())
0859: count++;
0860: if (count == 0)
0861: return Binding.NO_METHODS;
0862:
0863: MethodBinding[] result = new MethodBinding[count];
0864: count = 0;
0865: for (int i = this .methods.length; --i >= 0;)
0866: if (this .methods[i].isDefaultAbstract())
0867: result[count++] = this .methods[i];
0868: return result;
0869: }
0870:
0871: // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
0872: public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
0873: int argCount = argumentTypes.length;
0874: if ((this .tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods
0875: long range;
0876: if ((range = ReferenceBinding.binarySearch(
0877: TypeConstants.INIT, this .methods)) >= 0) {
0878: nextMethod: for (int imethod = (int) range, end = (int) (range >> 32); imethod <= end; imethod++) {
0879: MethodBinding method = this .methods[imethod];
0880: if (method.parameters.length == argCount) {
0881: TypeBinding[] toMatch = method.parameters;
0882: for (int iarg = 0; iarg < argCount; iarg++)
0883: if (toMatch[iarg] != argumentTypes[iarg])
0884: continue nextMethod;
0885: return method;
0886: }
0887: }
0888: }
0889: } else {
0890: // lazily sort methods
0891: if ((this .tagBits & TagBits.AreMethodsSorted) == 0) {
0892: int length = this .methods.length;
0893: if (length > 1)
0894: ReferenceBinding.sortMethods(this .methods, 0,
0895: length);
0896: this .tagBits |= TagBits.AreMethodsSorted;
0897: }
0898: long range;
0899: if ((range = ReferenceBinding.binarySearch(
0900: TypeConstants.INIT, this .methods)) >= 0) {
0901: nextMethod: for (int imethod = (int) range, end = (int) (range >> 32); imethod <= end; imethod++) {
0902: MethodBinding method = this .methods[imethod];
0903: if (resolveTypesFor(method) == null
0904: || method.returnType == null) {
0905: methods();
0906: return getExactConstructor(argumentTypes); // try again since the problem methods have been removed
0907: }
0908: if (method.parameters.length == argCount) {
0909: TypeBinding[] toMatch = method.parameters;
0910: for (int iarg = 0; iarg < argCount; iarg++)
0911: if (toMatch[iarg] != argumentTypes[iarg])
0912: continue nextMethod;
0913: return method;
0914: }
0915: }
0916: }
0917: }
0918: return null;
0919: }
0920:
0921: //NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
0922: //searches up the hierarchy as long as no potential (but not exact) match was found.
0923: public MethodBinding getExactMethod(char[] selector,
0924: TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
0925: // sender from refScope calls recordTypeReference(this)
0926: int argCount = argumentTypes.length;
0927: boolean foundNothing = true;
0928:
0929: if ((this .tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods
0930: long range;
0931: if ((range = ReferenceBinding.binarySearch(selector,
0932: this .methods)) >= 0) {
0933: nextMethod: for (int imethod = (int) range, end = (int) (range >> 32); imethod <= end; imethod++) {
0934: MethodBinding method = this .methods[imethod];
0935: foundNothing = false; // inner type lookups must know that a method with this name exists
0936: if (method.parameters.length == argCount) {
0937: TypeBinding[] toMatch = method.parameters;
0938: for (int iarg = 0; iarg < argCount; iarg++)
0939: if (toMatch[iarg] != argumentTypes[iarg])
0940: continue nextMethod;
0941: return method;
0942: }
0943: }
0944: }
0945: } else {
0946: // lazily sort methods
0947: if ((this .tagBits & TagBits.AreMethodsSorted) == 0) {
0948: int length = this .methods.length;
0949: if (length > 1)
0950: ReferenceBinding.sortMethods(this .methods, 0,
0951: length);
0952: this .tagBits |= TagBits.AreMethodsSorted;
0953: }
0954:
0955: long range;
0956: if ((range = ReferenceBinding.binarySearch(selector,
0957: this .methods)) >= 0) {
0958: // check unresolved method
0959: int start = (int) range, end = (int) (range >> 32);
0960: for (int imethod = start; imethod <= end; imethod++) {
0961: MethodBinding method = this .methods[imethod];
0962: if (resolveTypesFor(method) == null
0963: || method.returnType == null) {
0964: methods();
0965: return getExactMethod(selector, argumentTypes,
0966: refScope); // try again since the problem methods have been removed
0967: }
0968: }
0969: // check dup collisions
0970: boolean isSource15 = this .scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
0971: for (int i = start; i <= end; i++) {
0972: MethodBinding method1 = this .methods[i];
0973: for (int j = end; j > i; j--) {
0974: MethodBinding method2 = this .methods[j];
0975: boolean paramsMatch = isSource15 ? method1
0976: .areParameterErasuresEqual(method2)
0977: : method1.areParametersEqual(method2);
0978: if (paramsMatch) {
0979: methods();
0980: return getExactMethod(selector,
0981: argumentTypes, refScope); // try again since the problem methods have been removed
0982: }
0983: }
0984: }
0985: nextMethod: for (int imethod = start; imethod <= end; imethod++) {
0986: MethodBinding method = this .methods[imethod];
0987: TypeBinding[] toMatch = method.parameters;
0988: if (toMatch.length == argCount) {
0989: for (int iarg = 0; iarg < argCount; iarg++)
0990: if (toMatch[iarg] != argumentTypes[iarg])
0991: continue nextMethod;
0992: return method;
0993: }
0994: }
0995: }
0996: }
0997:
0998: if (foundNothing) {
0999: if (isInterface()) {
1000: if (this .super Interfaces.length == 1) {
1001: if (refScope != null)
1002: refScope
1003: .recordTypeReference(this .super Interfaces[0]);
1004: return this .super Interfaces[0].getExactMethod(
1005: selector, argumentTypes, refScope);
1006: }
1007: } else if (this .super class != null) {
1008: if (refScope != null)
1009: refScope.recordTypeReference(this .super class);
1010: return this .super class.getExactMethod(selector,
1011: argumentTypes, refScope);
1012: }
1013: }
1014: return null;
1015: }
1016:
1017: //NOTE: the type of a field of a source type is resolved when needed
1018: public FieldBinding getField(char[] fieldName, boolean needResolve) {
1019:
1020: if ((this .tagBits & TagBits.AreFieldsComplete) != 0)
1021: return ReferenceBinding
1022: .binarySearch(fieldName, this .fields);
1023:
1024: // lazily sort fields
1025: if ((this .tagBits & TagBits.AreFieldsSorted) == 0) {
1026: int length = this .fields.length;
1027: if (length > 1)
1028: ReferenceBinding.sortFields(this .fields, 0, length);
1029: this .tagBits |= TagBits.AreFieldsSorted;
1030: }
1031: // always resolve anyway on source types
1032: FieldBinding field = ReferenceBinding.binarySearch(fieldName,
1033: this .fields);
1034: if (field != null) {
1035: FieldBinding result = null;
1036: try {
1037: result = resolveTypeFor(field);
1038: return result;
1039: } finally {
1040: if (result == null) {
1041: // ensure fields are consistent reqardless of the error
1042: int newSize = this .fields.length - 1;
1043: if (newSize == 0) {
1044: this .fields = Binding.NO_FIELDS;
1045: } else {
1046: FieldBinding[] newFields = new FieldBinding[newSize];
1047: int index = 0;
1048: for (int i = 0, length = this .fields.length; i < length; i++) {
1049: FieldBinding f = this .fields[i];
1050: if (f == field)
1051: continue;
1052: newFields[index++] = f;
1053: }
1054: this .fields = newFields;
1055: }
1056: }
1057: }
1058: }
1059: return null;
1060: }
1061:
1062: // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
1063: public MethodBinding[] getMethods(char[] selector) {
1064: if ((this .tagBits & TagBits.AreMethodsComplete) != 0) {
1065: long range;
1066: if ((range = ReferenceBinding.binarySearch(selector,
1067: this .methods)) >= 0) {
1068: int start = (int) range, end = (int) (range >> 32);
1069: int length = end - start + 1;
1070: MethodBinding[] result;
1071: System.arraycopy(this .methods, start,
1072: result = new MethodBinding[length], 0, length);
1073: return result;
1074: } else {
1075: return Binding.NO_METHODS;
1076: }
1077: }
1078: // lazily sort methods
1079: if ((this .tagBits & TagBits.AreMethodsSorted) == 0) {
1080: int length = this .methods.length;
1081: if (length > 1)
1082: ReferenceBinding.sortMethods(this .methods, 0, length);
1083: this .tagBits |= TagBits.AreMethodsSorted;
1084: }
1085: MethodBinding[] result;
1086: long range;
1087: if ((range = ReferenceBinding.binarySearch(selector,
1088: this .methods)) >= 0) {
1089: int start = (int) range, end = (int) (range >> 32);
1090: for (int i = start; i <= end; i++) {
1091: MethodBinding method = this .methods[i];
1092: if (resolveTypesFor(method) == null
1093: || method.returnType == null) {
1094: methods();
1095: return getMethods(selector); // try again since the problem methods have been removed
1096: }
1097: }
1098: int length = end - start + 1;
1099: System.arraycopy(this .methods, start,
1100: result = new MethodBinding[length], 0, length);
1101: } else {
1102: return Binding.NO_METHODS;
1103: }
1104: boolean isSource15 = this .scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
1105: for (int i = 0, length = result.length - 1; i < length; i++) {
1106: MethodBinding method = result[i];
1107: for (int j = length; j > i; j--) {
1108: boolean paramsMatch = isSource15 ? method
1109: .areParameterErasuresEqual(result[j]) : method
1110: .areParametersEqual(result[j]);
1111: if (paramsMatch) {
1112: methods();
1113: return getMethods(selector); // try again since the duplicate methods have been removed
1114: }
1115: }
1116: }
1117: return result;
1118: }
1119:
1120: /* Answer the synthetic field for <actualOuterLocalVariable>
1121: * or null if one does not exist.
1122: */
1123: public FieldBinding getSyntheticField(
1124: LocalVariableBinding actualOuterLocalVariable) {
1125: if (this .synthetics == null
1126: || this .synthetics[SourceTypeBinding.FIELD_EMUL] == null)
1127: return null;
1128: return (FieldBinding) this .synthetics[SourceTypeBinding.FIELD_EMUL]
1129: .get(actualOuterLocalVariable);
1130: }
1131:
1132: /* Answer the synthetic field for <targetEnclosingType>
1133: * or null if one does not exist.
1134: */
1135: public FieldBinding getSyntheticField(
1136: ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
1137:
1138: if (this .synthetics == null
1139: || this .synthetics[SourceTypeBinding.FIELD_EMUL] == null)
1140: return null;
1141: FieldBinding field = (FieldBinding) this .synthetics[SourceTypeBinding.FIELD_EMUL]
1142: .get(targetEnclosingType);
1143: if (field != null)
1144: return field;
1145:
1146: // type compatibility : to handle cases such as
1147: // class T { class M{}}
1148: // class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
1149: if (!onlyExactMatch) {
1150: Iterator accessFields = this .synthetics[SourceTypeBinding.FIELD_EMUL]
1151: .values().iterator();
1152: while (accessFields.hasNext()) {
1153: field = (FieldBinding) accessFields.next();
1154: if (CharOperation
1155: .prefixEquals(
1156: TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX,
1157: field.name)
1158: && field.type
1159: .findSuperTypeWithSameErasure(targetEnclosingType) != null)
1160: return field;
1161: }
1162: }
1163: return null;
1164: }
1165:
1166: /*
1167: * Answer the bridge method associated for an inherited methods or null if one does not exist
1168: */
1169: public SyntheticMethodBinding getSyntheticBridgeMethod(
1170: MethodBinding inheritedMethodToBridge) {
1171: if (this .synthetics == null)
1172: return null;
1173: if (this .synthetics[SourceTypeBinding.METHOD_EMUL] == null)
1174: return null;
1175: SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this .synthetics[SourceTypeBinding.METHOD_EMUL]
1176: .get(inheritedMethodToBridge);
1177: if (accessors == null)
1178: return null;
1179: return accessors[1];
1180: }
1181:
1182: /**
1183: * @see org.eclipse.jdt.internal.compiler.lookup.Binding#initializeDeprecatedAnnotationTagBits()
1184: */
1185: public void initializeDeprecatedAnnotationTagBits() {
1186: if ((this .tagBits & TagBits.DeprecatedAnnotationResolved) == 0) {
1187: TypeDeclaration typeDecl = this .scope.referenceContext;
1188: boolean old = typeDecl.staticInitializerScope.insideTypeAnnotation;
1189: try {
1190: typeDecl.staticInitializerScope.insideTypeAnnotation = true;
1191: ASTNode.resolveDeprecatedAnnotations(
1192: typeDecl.staticInitializerScope,
1193: typeDecl.annotations, this );
1194: this .tagBits |= TagBits.DeprecatedAnnotationResolved;
1195: } finally {
1196: typeDecl.staticInitializerScope.insideTypeAnnotation = old;
1197: }
1198: if ((this .tagBits & TagBits.AnnotationDeprecated) != 0) {
1199: this .modifiers |= ClassFileConstants.AccDeprecated;
1200: }
1201: }
1202: }
1203:
1204: /**
1205: * Returns true if a type is identical to another one,
1206: * or for generic types, true if compared to its raw type.
1207: */
1208: public boolean isEquivalentTo(TypeBinding otherType) {
1209:
1210: if (this == otherType)
1211: return true;
1212: if (otherType == null)
1213: return false;
1214: switch (otherType.kind()) {
1215:
1216: case Binding.WILDCARD_TYPE:
1217: return ((WildcardBinding) otherType).boundCheck(this );
1218:
1219: case Binding.PARAMETERIZED_TYPE:
1220: if ((otherType.tagBits & TagBits.HasDirectWildcard) == 0
1221: && (!this .isMemberType() || !otherType
1222: .isMemberType()))
1223: return false; // should have been identical
1224: ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
1225: if (this != otherParamType.genericType())
1226: return false;
1227: if (!isStatic()) { // static member types do not compare their enclosing
1228: ReferenceBinding enclosing = enclosingType();
1229: if (enclosing != null) {
1230: ReferenceBinding otherEnclosing = otherParamType
1231: .enclosingType();
1232: if (otherEnclosing == null)
1233: return false;
1234: if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) {
1235: if (enclosing != otherEnclosing)
1236: return false;
1237: } else {
1238: if (!enclosing.isEquivalentTo(otherParamType
1239: .enclosingType()))
1240: return false;
1241: }
1242: }
1243: }
1244: int length = this .typeVariables == null ? 0
1245: : this .typeVariables.length;
1246: TypeBinding[] otherArguments = otherParamType.arguments;
1247: int otherLength = otherArguments == null ? 0
1248: : otherArguments.length;
1249: if (otherLength != length)
1250: return false;
1251: for (int i = 0; i < length; i++)
1252: if (!this .typeVariables[i]
1253: .isTypeArgumentContainedBy(otherArguments[i]))
1254: return false;
1255: return true;
1256:
1257: case Binding.RAW_TYPE:
1258: return otherType.erasure() == this ;
1259: }
1260: return false;
1261: }
1262:
1263: public boolean isGenericType() {
1264: return this .typeVariables != Binding.NO_TYPE_VARIABLES;
1265: }
1266:
1267: public ReferenceBinding[] memberTypes() {
1268: return this .memberTypes;
1269: }
1270:
1271: public FieldBinding getUpdatedFieldBinding(
1272: FieldBinding targetField, ReferenceBinding newDeclaringClass) {
1273: if (this .synthetics == null)
1274: this .synthetics = new HashMap[4];
1275: if (this .synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] == null)
1276: this .synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] = new HashMap(
1277: 5);
1278:
1279: Hashtable fieldMap = (Hashtable) this .synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL]
1280: .get(targetField);
1281: if (fieldMap == null) {
1282: fieldMap = new Hashtable(5);
1283: this .synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].put(
1284: targetField, fieldMap);
1285: }
1286: FieldBinding updatedField = (FieldBinding) fieldMap
1287: .get(newDeclaringClass);
1288: if (updatedField == null) {
1289: updatedField = new FieldBinding(targetField,
1290: newDeclaringClass);
1291: fieldMap.put(newDeclaringClass, updatedField);
1292: }
1293: return updatedField;
1294: }
1295:
1296: public MethodBinding getUpdatedMethodBinding(
1297: MethodBinding targetMethod,
1298: ReferenceBinding newDeclaringClass) {
1299: if (this .synthetics == null)
1300: this .synthetics = new HashMap[4];
1301: if (this .synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] == null)
1302: this .synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] = new HashMap(
1303: 5);
1304:
1305: Hashtable methodMap = (Hashtable) this .synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL]
1306: .get(targetMethod);
1307: if (methodMap == null) {
1308: methodMap = new Hashtable(5);
1309: this .synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].put(
1310: targetMethod, methodMap);
1311: }
1312: MethodBinding updatedMethod = (MethodBinding) methodMap
1313: .get(newDeclaringClass);
1314: if (updatedMethod == null) {
1315: updatedMethod = new MethodBinding(targetMethod,
1316: newDeclaringClass);
1317: methodMap.put(newDeclaringClass, updatedMethod);
1318: }
1319: return updatedMethod;
1320: }
1321:
1322: public boolean hasMemberTypes() {
1323: return this .memberTypes.length > 0;
1324: }
1325:
1326: // NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
1327: public MethodBinding[] methods() {
1328: if ((this .tagBits & TagBits.AreMethodsComplete) != 0)
1329: return this .methods;
1330:
1331: // lazily sort methods
1332: if ((this .tagBits & TagBits.AreMethodsSorted) == 0) {
1333: int length = this .methods.length;
1334: if (length > 1)
1335: ReferenceBinding.sortMethods(this .methods, 0, length);
1336: this .tagBits |= TagBits.AreMethodsSorted;
1337: }
1338:
1339: int failed = 0;
1340: MethodBinding[] resolvedMethods = this .methods;
1341: try {
1342: for (int i = 0, length = this .methods.length; i < length; i++) {
1343: if (resolveTypesFor(this .methods[i]) == null) {
1344: // do not alter original method array until resolution is over, due to reentrance (143259)
1345: if (resolvedMethods == this .methods) {
1346: System
1347: .arraycopy(
1348: this .methods,
1349: 0,
1350: resolvedMethods = new MethodBinding[length],
1351: 0, length);
1352: }
1353: resolvedMethods[i] = null; // unable to resolve parameters
1354: failed++;
1355: }
1356: }
1357:
1358: // find & report collision cases
1359: boolean complyTo15 = this .scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
1360: for (int i = 0, length = this .methods.length; i < length; i++) {
1361: MethodBinding method = resolvedMethods[i];
1362: if (method == null)
1363: continue;
1364: char[] selector = method.selector;
1365: AbstractMethodDeclaration methodDecl = null;
1366: nextSibling: for (int j = i + 1; j < length; j++) {
1367: MethodBinding method2 = resolvedMethods[j];
1368: if (method2 == null)
1369: continue nextSibling;
1370: if (!CharOperation.equals(selector,
1371: method2.selector))
1372: break nextSibling; // methods with same selector are contiguous
1373:
1374: if (complyTo15 && method.returnType != null
1375: && method2.returnType != null) {
1376: // 8.4.2, for collision to be detected between m1 and m2:
1377: // signature(m1) == signature(m2) i.e. same arity, same type parameter count, can be substituted
1378: // signature(m1) == erasure(signature(m2)) or erasure(signature(m1)) == signature(m2)
1379: TypeBinding[] params1 = method.parameters;
1380: TypeBinding[] params2 = method2.parameters;
1381: int pLength = params1.length;
1382: if (pLength != params2.length)
1383: continue nextSibling;
1384:
1385: TypeVariableBinding[] vars = method.typeVariables;
1386: TypeVariableBinding[] vars2 = method2.typeVariables;
1387: boolean equalTypeVars = vars == vars2;
1388: MethodBinding subMethod = method2;
1389: if (!equalTypeVars) {
1390: MethodBinding temp = method
1391: .computeSubstitutedMethod(method2,
1392: this .scope.environment());
1393: if (temp != null) {
1394: equalTypeVars = true;
1395: subMethod = temp;
1396: }
1397: }
1398: boolean equalParams = method
1399: .areParametersEqual(subMethod);
1400: if (equalParams && equalTypeVars) {
1401: // duplicates regardless of return types
1402: } else if (method.returnType.erasure() == subMethod.returnType
1403: .erasure()
1404: && (equalParams || method
1405: .areParameterErasuresEqual(method2))) {
1406: // name clash for sure if not duplicates, report as duplicates
1407: } else if (!equalTypeVars
1408: && vars != Binding.NO_TYPE_VARIABLES
1409: && vars2 != Binding.NO_TYPE_VARIABLES) {
1410: // type variables are different so we can distinguish between methods
1411: continue nextSibling;
1412: } else if (pLength > 0) {
1413: // check to see if the erasure of either method is equal to the other
1414: int index = pLength;
1415: for (; --index >= 0;) {
1416: if (params1[index] != params2[index]
1417: .erasure())
1418: break;
1419: if (params1[index] == params2[index]) {
1420: TypeBinding type = params1[index]
1421: .leafComponentType();
1422: if (type instanceof SourceTypeBinding
1423: && type.typeVariables() != Binding.NO_TYPE_VARIABLES) {
1424: index = pLength; // handle comparing identical source types like X<T>... its erasure is itself BUT we need to answer false
1425: break;
1426: }
1427: }
1428: }
1429: if (index >= 0 && index < pLength) {
1430: for (index = pLength; --index >= 0;)
1431: if (params1[index].erasure() != params2[index])
1432: break;
1433: }
1434: if (index >= 0)
1435: continue nextSibling;
1436: }
1437: } else if (!method.areParametersEqual(method2)) { // prior to 1.5, parameter identity meant a collision case
1438: continue nextSibling;
1439: }
1440: boolean isEnumSpecialMethod = isEnum()
1441: && (CharOperation.equals(selector,
1442: TypeConstants.VALUEOF) || CharOperation
1443: .equals(selector,
1444: TypeConstants.VALUES));
1445: // report duplicate
1446: if (methodDecl == null) {
1447: methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost & may still be null if method is special
1448: if (methodDecl != null
1449: && methodDecl.binding != null) { // ensure its a valid user defined method
1450: if (isEnumSpecialMethod) {
1451: this .scope.problemReporter()
1452: .duplicateEnumSpecialMethod(
1453: this , methodDecl);
1454: } else {
1455: this .scope.problemReporter()
1456: .duplicateMethodInType(this ,
1457: methodDecl);
1458: }
1459: methodDecl.binding = null;
1460: // do not alter original method array until resolution is over, due to reentrance (143259)
1461: if (resolvedMethods == this .methods) {
1462: System
1463: .arraycopy(
1464: this .methods,
1465: 0,
1466: resolvedMethods = new MethodBinding[length],
1467: 0, length);
1468: }
1469: resolvedMethods[i] = null;
1470: failed++;
1471: }
1472: }
1473: AbstractMethodDeclaration method2Decl = method2
1474: .sourceMethod();
1475: if (method2Decl != null
1476: && method2Decl.binding != null) { // ensure its a valid user defined method
1477: if (isEnumSpecialMethod) {
1478: this .scope.problemReporter()
1479: .duplicateEnumSpecialMethod(this ,
1480: method2Decl);
1481: } else {
1482: this .scope.problemReporter()
1483: .duplicateMethodInType(this ,
1484: method2Decl);
1485: }
1486: method2Decl.binding = null;
1487: // do not alter original method array until resolution is over, due to reentrance (143259)
1488: if (resolvedMethods == this .methods) {
1489: System
1490: .arraycopy(
1491: this .methods,
1492: 0,
1493: resolvedMethods = new MethodBinding[length],
1494: 0, length);
1495: }
1496: resolvedMethods[j] = null;
1497: failed++;
1498: }
1499: }
1500: if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
1501: methodDecl = method.sourceMethod();
1502: if (methodDecl != null) {
1503: methodDecl.binding = null;
1504: }
1505: // do not alter original method array until resolution is over, due to reentrance (143259)
1506: if (resolvedMethods == this .methods) {
1507: System
1508: .arraycopy(
1509: this .methods,
1510: 0,
1511: resolvedMethods = new MethodBinding[length],
1512: 0, length);
1513: }
1514: resolvedMethods[i] = null;
1515: failed++;
1516: }
1517: }
1518: } finally {
1519: if (failed > 0) {
1520: int newSize = resolvedMethods.length - failed;
1521: if (newSize == 0) {
1522: this .methods = Binding.NO_METHODS;
1523: } else {
1524: MethodBinding[] newMethods = new MethodBinding[newSize];
1525: for (int i = 0, j = 0, length = resolvedMethods.length; i < length; i++)
1526: if (resolvedMethods[i] != null)
1527: newMethods[j++] = resolvedMethods[i];
1528: this .methods = newMethods;
1529: }
1530: }
1531:
1532: // handle forward references to potential default abstract methods
1533: addDefaultAbstractMethods();
1534: this .tagBits |= TagBits.AreMethodsComplete;
1535: }
1536: return this .methods;
1537: }
1538:
1539: private FieldBinding resolveTypeFor(FieldBinding field) {
1540: if ((field.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
1541: return field;
1542:
1543: if (this .scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
1544: if ((field.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0)
1545: field.modifiers |= ClassFileConstants.AccDeprecated;
1546: }
1547: if (isViewedAsDeprecated() && !field.isDeprecated())
1548: field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
1549: if (hasRestrictedAccess())
1550: field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
1551: FieldDeclaration[] fieldDecls = this .scope.referenceContext.fields;
1552: for (int f = 0, length = fieldDecls.length; f < length; f++) {
1553: if (fieldDecls[f].binding != field)
1554: continue;
1555:
1556: MethodScope initializationScope = field.isStatic() ? this .scope.referenceContext.staticInitializerScope
1557: : this .scope.referenceContext.initializerScope;
1558: FieldBinding previousField = initializationScope.initializedField;
1559: try {
1560: initializationScope.initializedField = field;
1561: FieldDeclaration fieldDecl = fieldDecls[f];
1562: TypeBinding fieldType = fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT ? initializationScope
1563: .environment().convertToRawType(this ) // enum constant is implicitly of declaring enum type
1564: : fieldDecl.type
1565: .resolveType(initializationScope, true /* check bounds*/);
1566: field.type = fieldType;
1567: field.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
1568: if (fieldType == null) {
1569: fieldDecl.binding = null;
1570: return null;
1571: }
1572: if (fieldType == TypeBinding.VOID) {
1573: this .scope.problemReporter()
1574: .variableTypeCannotBeVoid(fieldDecl);
1575: fieldDecl.binding = null;
1576: return null;
1577: }
1578: if (fieldType.isArrayType()
1579: && ((ArrayBinding) fieldType).leafComponentType == TypeBinding.VOID) {
1580: this .scope.problemReporter()
1581: .variableTypeCannotBeVoidArray(fieldDecl);
1582: fieldDecl.binding = null;
1583: return null;
1584: }
1585: TypeBinding leafType = fieldType.leafComponentType();
1586: if (leafType instanceof ReferenceBinding
1587: && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) {
1588: field.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
1589: }
1590: } finally {
1591: initializationScope.initializedField = previousField;
1592: }
1593: return field;
1594: }
1595: return null; // should never reach this point
1596: }
1597:
1598: public MethodBinding resolveTypesFor(MethodBinding method) {
1599: if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
1600: return method;
1601:
1602: if (this .scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
1603: if ((method.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0)
1604: method.modifiers |= ClassFileConstants.AccDeprecated;
1605: }
1606: if (isViewedAsDeprecated() && !method.isDeprecated())
1607: method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
1608: if (hasRestrictedAccess())
1609: method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
1610:
1611: AbstractMethodDeclaration methodDecl = method.sourceMethod();
1612: if (methodDecl == null)
1613: return null; // method could not be resolved in previous iteration
1614:
1615: TypeParameter[] typeParameters = methodDecl.typeParameters();
1616: if (typeParameters != null) {
1617: methodDecl.scope.connectTypeVariables(typeParameters, true);
1618: // Perform deferred bound checks for type variables (only done after type variable hierarchy is connected)
1619: for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++)
1620: typeParameters[i].checkBounds(methodDecl.scope);
1621: }
1622: TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
1623: if (exceptionTypes != null) {
1624: int size = exceptionTypes.length;
1625: method.thrownExceptions = new ReferenceBinding[size];
1626: int count = 0;
1627: ReferenceBinding resolvedExceptionType;
1628: for (int i = 0; i < size; i++) {
1629: resolvedExceptionType = (ReferenceBinding) exceptionTypes[i]
1630: .resolveType(methodDecl.scope, true /* check bounds*/);
1631: if (resolvedExceptionType == null)
1632: continue;
1633: if (resolvedExceptionType.isBoundParameterizedType()) {
1634: methodDecl.scope.problemReporter()
1635: .invalidParameterizedExceptionType(
1636: resolvedExceptionType,
1637: exceptionTypes[i]);
1638: continue;
1639: }
1640: if (resolvedExceptionType.findSuperTypeErasingTo(
1641: TypeIds.T_JavaLangThrowable, true) == null) {
1642: methodDecl.scope.problemReporter().cannotThrowType(
1643: exceptionTypes[i], resolvedExceptionType);
1644: continue;
1645: }
1646: if ((resolvedExceptionType.modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
1647: method.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
1648: method.thrownExceptions[count++] = resolvedExceptionType;
1649: }
1650: if (count < size)
1651: System
1652: .arraycopy(
1653: method.thrownExceptions,
1654: 0,
1655: method.thrownExceptions = new ReferenceBinding[count],
1656: 0, count);
1657: }
1658:
1659: boolean foundArgProblem = false;
1660: Argument[] arguments = methodDecl.arguments;
1661: if (arguments != null) {
1662: int size = arguments.length;
1663: method.parameters = Binding.NO_PARAMETERS;
1664: TypeBinding[] newParameters = new TypeBinding[size];
1665: for (int i = 0; i < size; i++) {
1666: Argument arg = arguments[i];
1667: TypeBinding parameterType = arg.type.resolveType(
1668: methodDecl.scope, true /* check bounds*/);
1669: if (parameterType == null) {
1670: foundArgProblem = true;
1671: } else if (parameterType == TypeBinding.VOID) {
1672: methodDecl.scope.problemReporter()
1673: .argumentTypeCannotBeVoid(this , methodDecl,
1674: arg);
1675: foundArgProblem = true;
1676: } else {
1677: TypeBinding leafType = parameterType
1678: .leafComponentType();
1679: if (leafType instanceof ReferenceBinding
1680: && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
1681: method.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
1682: newParameters[i] = parameterType;
1683: arg.binding = new LocalVariableBinding(arg,
1684: parameterType, arg.modifiers, true);
1685: }
1686: }
1687: // only assign parameters if no problems are found
1688: if (!foundArgProblem) {
1689: method.parameters = newParameters;
1690: }
1691: }
1692:
1693: boolean foundReturnTypeProblem = false;
1694: if (!method.isConstructor()) {
1695: TypeReference returnType = methodDecl instanceof MethodDeclaration ? ((MethodDeclaration) methodDecl).returnType
1696: : null;
1697: if (returnType == null) {
1698: methodDecl.scope.problemReporter().missingReturnType(
1699: methodDecl);
1700: method.returnType = null;
1701: foundReturnTypeProblem = true;
1702: } else {
1703: TypeBinding methodType = returnType.resolveType(
1704: methodDecl.scope, true /* check bounds*/);
1705: if (methodType == null) {
1706: foundReturnTypeProblem = true;
1707: } else if (methodType.isArrayType()
1708: && ((ArrayBinding) methodType).leafComponentType == TypeBinding.VOID) {
1709: methodDecl.scope.problemReporter()
1710: .returnTypeCannotBeVoidArray(
1711: (MethodDeclaration) methodDecl);
1712: foundReturnTypeProblem = true;
1713: } else {
1714: method.returnType = methodType;
1715: TypeBinding leafType = methodType
1716: .leafComponentType();
1717: if (leafType instanceof ReferenceBinding
1718: && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
1719: method.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
1720: }
1721: }
1722: }
1723: if (foundArgProblem) {
1724: methodDecl.binding = null;
1725: method.parameters = Binding.NO_PARAMETERS; // see 107004
1726: // nullify type parameter bindings as well as they have a backpointer to the method binding
1727: // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=81134)
1728: if (typeParameters != null)
1729: for (int i = 0, length = typeParameters.length; i < length; i++)
1730: typeParameters[i].binding = null;
1731: return null;
1732: }
1733: if (foundReturnTypeProblem)
1734: return method; // but its still unresolved with a null return type & is still connected to its method declaration
1735:
1736: method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
1737: return method;
1738: }
1739:
1740: public AnnotationHolder retrieveAnnotationHolder(Binding binding,
1741: boolean forceInitialization) {
1742: if (forceInitialization)
1743: binding.getAnnotationTagBits(); // ensure annotations are up to date
1744: return super .retrieveAnnotationHolder(binding, false);
1745: }
1746:
1747: public void setFields(FieldBinding[] fields) {
1748: this .fields = fields;
1749: }
1750:
1751: public void setMethods(MethodBinding[] methods) {
1752: this .methods = methods;
1753: }
1754:
1755: public final int sourceEnd() {
1756: return this .scope.referenceContext.sourceEnd;
1757: }
1758:
1759: public final int sourceStart() {
1760: return this .scope.referenceContext.sourceStart;
1761: }
1762:
1763: SimpleLookupTable storedAnnotations(boolean forceInitialize) {
1764: if (forceInitialize && this .storedAnnotations == null
1765: && this .scope != null) { // scope null when no annotation cached, and type got processed fully (159631)
1766: this .scope.referenceCompilationUnit().compilationResult.hasAnnotations = true;
1767: if (!this .scope.environment().globalOptions.storeAnnotations)
1768: return null; // not supported during this compile
1769: this .storedAnnotations = new SimpleLookupTable(3);
1770: }
1771: return this .storedAnnotations;
1772: }
1773:
1774: public ReferenceBinding super class() {
1775: return this .super class;
1776: }
1777:
1778: public ReferenceBinding[] super Interfaces() {
1779: return this .super Interfaces;
1780: }
1781:
1782: // TODO (philippe) could be a performance issue since some senders are building the list just to count them
1783: public SyntheticMethodBinding[] syntheticMethods() {
1784:
1785: if (this .synthetics == null
1786: || this .synthetics[SourceTypeBinding.METHOD_EMUL] == null
1787: || this .synthetics[SourceTypeBinding.METHOD_EMUL]
1788: .size() == 0)
1789: return null;
1790:
1791: // difficult to compute size up front because of the embedded arrays so assume there is only 1
1792: int index = 0;
1793: SyntheticMethodBinding[] bindings = new SyntheticMethodBinding[1];
1794: Iterator fieldsOrMethods = this .synthetics[SourceTypeBinding.METHOD_EMUL]
1795: .keySet().iterator();
1796: while (fieldsOrMethods.hasNext()) {
1797:
1798: Object fieldOrMethod = fieldsOrMethods.next();
1799:
1800: if (fieldOrMethod instanceof MethodBinding) {
1801:
1802: SyntheticMethodBinding[] methodAccessors = (SyntheticMethodBinding[]) this .synthetics[SourceTypeBinding.METHOD_EMUL]
1803: .get(fieldOrMethod);
1804: int numberOfAccessors = 0;
1805: if (methodAccessors[0] != null)
1806: numberOfAccessors++;
1807: if (methodAccessors[1] != null)
1808: numberOfAccessors++;
1809: if (index + numberOfAccessors > bindings.length)
1810: System
1811: .arraycopy(
1812: bindings,
1813: 0,
1814: (bindings = new SyntheticMethodBinding[index
1815: + numberOfAccessors]), 0,
1816: index);
1817: if (methodAccessors[0] != null)
1818: bindings[index++] = methodAccessors[0]; // super access
1819: if (methodAccessors[1] != null)
1820: bindings[index++] = methodAccessors[1]; // normal access or bridge
1821:
1822: } else {
1823:
1824: SyntheticMethodBinding[] fieldAccessors = (SyntheticMethodBinding[]) this .synthetics[SourceTypeBinding.METHOD_EMUL]
1825: .get(fieldOrMethod);
1826: int numberOfAccessors = 0;
1827: if (fieldAccessors[0] != null)
1828: numberOfAccessors++;
1829: if (fieldAccessors[1] != null)
1830: numberOfAccessors++;
1831: if (index + numberOfAccessors > bindings.length)
1832: System
1833: .arraycopy(
1834: bindings,
1835: 0,
1836: (bindings = new SyntheticMethodBinding[index
1837: + numberOfAccessors]), 0,
1838: index);
1839: if (fieldAccessors[0] != null)
1840: bindings[index++] = fieldAccessors[0]; // read access
1841: if (fieldAccessors[1] != null)
1842: bindings[index++] = fieldAccessors[1]; // write access
1843: }
1844: }
1845:
1846: // sort them in according to their own indexes
1847: int length;
1848: SyntheticMethodBinding[] sortedBindings = new SyntheticMethodBinding[length = bindings.length];
1849: for (int i = 0; i < length; i++) {
1850: SyntheticMethodBinding binding = bindings[i];
1851: sortedBindings[binding.index] = binding;
1852: }
1853: return sortedBindings;
1854: }
1855:
1856: /**
1857: * Answer the collection of synthetic fields to append into the classfile
1858: */
1859: public FieldBinding[] syntheticFields() {
1860:
1861: if (this .synthetics == null)
1862: return null;
1863:
1864: int fieldSize = this .synthetics[SourceTypeBinding.FIELD_EMUL] == null ? 0
1865: : this .synthetics[SourceTypeBinding.FIELD_EMUL].size();
1866: int literalSize = this .synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] == null ? 0
1867: : this .synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL]
1868: .size();
1869: int totalSize = fieldSize + literalSize;
1870: if (totalSize == 0)
1871: return null;
1872: FieldBinding[] bindings = new FieldBinding[totalSize];
1873:
1874: // add innerclass synthetics
1875: if (this .synthetics[SourceTypeBinding.FIELD_EMUL] != null) {
1876: Iterator elements = this .synthetics[SourceTypeBinding.FIELD_EMUL]
1877: .values().iterator();
1878: for (int i = 0; i < fieldSize; i++) {
1879: SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements
1880: .next();
1881: bindings[synthBinding.index] = synthBinding;
1882: }
1883: }
1884: // add class literal synthetics
1885: if (this .synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] != null) {
1886: Iterator elements = this .synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL]
1887: .values().iterator();
1888: for (int i = 0; i < literalSize; i++) {
1889: SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements
1890: .next();
1891: bindings[fieldSize + synthBinding.index] = synthBinding;
1892: }
1893: }
1894: return bindings;
1895: }
1896:
1897: public String toString() {
1898: StringBuffer buffer = new StringBuffer(30);
1899: buffer.append("(id="); //$NON-NLS-1$
1900: if (this .id == TypeIds.NoId)
1901: buffer.append("NoId"); //$NON-NLS-1$
1902: else
1903: buffer.append(this .id);
1904: buffer.append(")\n"); //$NON-NLS-1$
1905: if (isDeprecated())
1906: buffer.append("deprecated "); //$NON-NLS-1$
1907: if (isPublic())
1908: buffer.append("public "); //$NON-NLS-1$
1909: if (isProtected())
1910: buffer.append("protected "); //$NON-NLS-1$
1911: if (isPrivate())
1912: buffer.append("private "); //$NON-NLS-1$
1913: if (isAbstract() && isClass())
1914: buffer.append("abstract "); //$NON-NLS-1$
1915: if (isStatic() && isNestedType())
1916: buffer.append("static "); //$NON-NLS-1$
1917: if (isFinal())
1918: buffer.append("final "); //$NON-NLS-1$
1919:
1920: if (isEnum())
1921: buffer.append("enum "); //$NON-NLS-1$
1922: else if (isAnnotationType())
1923: buffer.append("@interface "); //$NON-NLS-1$
1924: else if (isClass())
1925: buffer.append("class "); //$NON-NLS-1$
1926: else
1927: buffer.append("interface "); //$NON-NLS-1$
1928: buffer.append((this .compoundName != null) ? CharOperation
1929: .toString(this .compoundName) : "UNNAMED TYPE"); //$NON-NLS-1$
1930:
1931: if (this .typeVariables == null) {
1932: buffer.append("<NULL TYPE VARIABLES>"); //$NON-NLS-1$
1933: } else if (this .typeVariables != Binding.NO_TYPE_VARIABLES) {
1934: buffer.append("\n\t<"); //$NON-NLS-1$
1935: for (int i = 0, length = this .typeVariables.length; i < length; i++) {
1936: if (i > 0)
1937: buffer.append(", "); //$NON-NLS-1$
1938: buffer
1939: .append((this .typeVariables[i] != null) ? this .typeVariables[i]
1940: .toString()
1941: : "NULL TYPE VARIABLE"); //$NON-NLS-1$
1942: }
1943: buffer.append(">"); //$NON-NLS-1$
1944: }
1945: buffer.append("\n\textends "); //$NON-NLS-1$
1946: buffer.append((this .super class != null) ? this .super class
1947: .debugName() : "NULL TYPE"); //$NON-NLS-1$
1948:
1949: if (this .super Interfaces != null) {
1950: if (this .super Interfaces != Binding.NO_SUPERINTERFACES) {
1951: buffer.append("\n\timplements : "); //$NON-NLS-1$
1952: for (int i = 0, length = this .super Interfaces.length; i < length; i++) {
1953: if (i > 0)
1954: buffer.append(", "); //$NON-NLS-1$
1955: buffer
1956: .append((this .super Interfaces[i] != null) ? this .super Interfaces[i]
1957: .debugName()
1958: : "NULL TYPE"); //$NON-NLS-1$
1959: }
1960: }
1961: } else {
1962: buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$
1963: }
1964:
1965: if (enclosingType() != null) {
1966: buffer.append("\n\tenclosing type : "); //$NON-NLS-1$
1967: buffer.append(enclosingType().debugName());
1968: }
1969:
1970: if (this .fields != null) {
1971: if (this .fields != Binding.NO_FIELDS) {
1972: buffer.append("\n/* fields */"); //$NON-NLS-1$
1973: for (int i = 0, length = this .fields.length; i < length; i++)
1974: buffer.append('\n').append(
1975: (this .fields[i] != null) ? this .fields[i]
1976: .toString() : "NULL FIELD"); //$NON-NLS-1$
1977: }
1978: } else {
1979: buffer.append("NULL FIELDS"); //$NON-NLS-1$
1980: }
1981:
1982: if (this .methods != null) {
1983: if (this .methods != Binding.NO_METHODS) {
1984: buffer.append("\n/* methods */"); //$NON-NLS-1$
1985: for (int i = 0, length = this .methods.length; i < length; i++)
1986: buffer.append('\n').append(
1987: (this .methods[i] != null) ? this .methods[i]
1988: .toString() : "NULL METHOD"); //$NON-NLS-1$
1989: }
1990: } else {
1991: buffer.append("NULL METHODS"); //$NON-NLS-1$
1992: }
1993:
1994: if (this .memberTypes != null) {
1995: if (this .memberTypes != Binding.NO_MEMBER_TYPES) {
1996: buffer.append("\n/* members */"); //$NON-NLS-1$
1997: for (int i = 0, length = this .memberTypes.length; i < length; i++)
1998: buffer
1999: .append('\n')
2000: .append(
2001: (this .memberTypes[i] != null) ? this .memberTypes[i]
2002: .toString()
2003: : "NULL TYPE"); //$NON-NLS-1$
2004: }
2005: } else {
2006: buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$
2007: }
2008:
2009: buffer.append("\n\n"); //$NON-NLS-1$
2010: return buffer.toString();
2011: }
2012:
2013: public TypeVariableBinding[] typeVariables() {
2014: return this .typeVariables;
2015: }
2016:
2017: void verifyMethods(MethodVerifier verifier) {
2018: verifier.verify(this );
2019:
2020: for (int i = this .memberTypes.length; --i >= 0;)
2021: ((SourceTypeBinding) this.memberTypes[i])
2022: .verifyMethods(verifier);
2023: }
2024: }
|