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 org.eclipse.jdt.core.compiler.CharOperation;
0013: import org.eclipse.jdt.internal.compiler.ClassFile;
0014: import org.eclipse.jdt.internal.compiler.ast.ASTNode;
0015: import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
0016: import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
0017: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
0018: import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
0019:
0020: public class MethodBinding extends Binding {
0021:
0022: public int modifiers;
0023: public char[] selector;
0024: public TypeBinding returnType;
0025: public TypeBinding[] parameters;
0026: public ReferenceBinding[] thrownExceptions;
0027: public ReferenceBinding declaringClass;
0028: public TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES;
0029: char[] signature;
0030: public long tagBits;
0031:
0032: protected MethodBinding() {
0033: // for creating problem or synthetic method
0034: }
0035:
0036: public MethodBinding(int modifiers, char[] selector,
0037: TypeBinding returnType, TypeBinding[] parameters,
0038: ReferenceBinding[] thrownExceptions,
0039: ReferenceBinding declaringClass) {
0040: this .modifiers = modifiers;
0041: this .selector = selector;
0042: this .returnType = returnType;
0043: this .parameters = (parameters == null || parameters.length == 0) ? Binding.NO_PARAMETERS
0044: : parameters;
0045: this .thrownExceptions = (thrownExceptions == null || thrownExceptions.length == 0) ? Binding.NO_EXCEPTIONS
0046: : thrownExceptions;
0047: this .declaringClass = declaringClass;
0048:
0049: // propagate the strictfp & deprecated modifiers
0050: if (this .declaringClass != null) {
0051: if (this .declaringClass.isStrictfp())
0052: if (!(isNative() || isAbstract()))
0053: this .modifiers |= ClassFileConstants.AccStrictfp;
0054: }
0055: }
0056:
0057: public MethodBinding(int modifiers, TypeBinding[] parameters,
0058: ReferenceBinding[] thrownExceptions,
0059: ReferenceBinding declaringClass) {
0060: this (modifiers, TypeConstants.INIT, TypeBinding.VOID,
0061: parameters, thrownExceptions, declaringClass);
0062: }
0063:
0064: // special API used to change method declaring class for runtime visibility check
0065: public MethodBinding(MethodBinding initialMethodBinding,
0066: ReferenceBinding declaringClass) {
0067: this .modifiers = initialMethodBinding.modifiers;
0068: this .selector = initialMethodBinding.selector;
0069: this .returnType = initialMethodBinding.returnType;
0070: this .parameters = initialMethodBinding.parameters;
0071: this .thrownExceptions = initialMethodBinding.thrownExceptions;
0072: this .declaringClass = declaringClass;
0073: declaringClass.storeAnnotationHolder(this ,
0074: initialMethodBinding.declaringClass
0075: .retrieveAnnotationHolder(initialMethodBinding,
0076: true));
0077: }
0078:
0079: /* Answer true if the argument types & the receiver's parameters have the same erasure
0080: */
0081: public final boolean areParameterErasuresEqual(MethodBinding method) {
0082: TypeBinding[] args = method.parameters;
0083: if (parameters == args)
0084: return true;
0085:
0086: int length = parameters.length;
0087: if (length != args.length)
0088: return false;
0089:
0090: for (int i = 0; i < length; i++)
0091: if (parameters[i] != args[i]
0092: && parameters[i].erasure() != args[i].erasure())
0093: return false;
0094: return true;
0095: }
0096:
0097: /* Answer true if the argument types & the receiver's parameters are equal
0098: */
0099: public final boolean areParametersEqual(MethodBinding method) {
0100: TypeBinding[] args = method.parameters;
0101: if (parameters == args)
0102: return true;
0103:
0104: int length = parameters.length;
0105: if (length != args.length)
0106: return false;
0107:
0108: for (int i = 0; i < length; i++)
0109: if (parameters[i] != args[i])
0110: return false;
0111: return true;
0112: }
0113:
0114: /*
0115: * Returns true if given parameters are compatible with this method parameters.
0116: * Callers to this method should first check that the number of TypeBindings
0117: * passed as argument matches this MethodBinding number of parameters
0118: */
0119: public final boolean areParametersCompatibleWith(
0120: TypeBinding[] arguments) {
0121: int paramLength = this .parameters.length;
0122: int argLength = arguments.length;
0123: int lastIndex = argLength;
0124: if (isVarargs()) {
0125: lastIndex = paramLength - 1;
0126: if (paramLength == argLength) { // accept X[] but not X or X[][]
0127: TypeBinding varArgType = parameters[lastIndex]; // is an ArrayBinding by definition
0128: TypeBinding lastArgument = arguments[lastIndex];
0129: if (varArgType != lastArgument
0130: && !lastArgument.isCompatibleWith(varArgType))
0131: return false;
0132: } else if (paramLength < argLength) { // all remainig argument types must be compatible with the elementsType of varArgType
0133: TypeBinding varArgType = ((ArrayBinding) parameters[lastIndex])
0134: .elementsType();
0135: for (int i = lastIndex; i < argLength; i++)
0136: if (varArgType != arguments[i]
0137: && !arguments[i]
0138: .isCompatibleWith(varArgType))
0139: return false;
0140: } else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo();
0141: return false;
0142: }
0143: // now compare standard arguments from 0 to lastIndex
0144: }
0145: for (int i = 0; i < lastIndex; i++)
0146: if (parameters[i] != arguments[i]
0147: && !arguments[i].isCompatibleWith(parameters[i]))
0148: return false;
0149: return true;
0150: }
0151:
0152: /* API
0153: * Answer the receiver's binding type from Binding.BindingID.
0154: */
0155:
0156: public final int kind() {
0157: return Binding.METHOD;
0158: }
0159:
0160: /* Answer true if the receiver is visible to the invocationPackage.
0161: */
0162:
0163: public final boolean canBeSeenBy(PackageBinding invocationPackage) {
0164: if (isPublic())
0165: return true;
0166: if (isPrivate())
0167: return false;
0168:
0169: // isProtected() or isDefault()
0170: return invocationPackage == declaringClass.getPackage();
0171: }
0172:
0173: /* Answer true if the type variables have the same erasure
0174: */
0175: public final boolean areTypeVariableErasuresEqual(
0176: MethodBinding method) {
0177: TypeVariableBinding[] vars = method.typeVariables;
0178: if (this .typeVariables == vars)
0179: return true;
0180:
0181: int length = this .typeVariables.length;
0182: if (length != vars.length)
0183: return false;
0184:
0185: for (int i = 0; i < length; i++)
0186: if (this .typeVariables[i] != vars[i]
0187: && this .typeVariables[i].erasure() != vars[i]
0188: .erasure())
0189: return false;
0190: return true;
0191: }
0192:
0193: /* Answer true if the receiver is visible to the type provided by the scope.
0194: * InvocationSite implements isSuperAccess() to provide additional information
0195: * if the receiver is protected.
0196: *
0197: * NOTE: This method should ONLY be sent if the receiver is a constructor.
0198: *
0199: * NOTE: Cannot invoke this method with a compilation unit scope.
0200: */
0201:
0202: public final boolean canBeSeenBy(InvocationSite invocationSite,
0203: Scope scope) {
0204: if (isPublic())
0205: return true;
0206:
0207: SourceTypeBinding invocationType = scope.enclosingSourceType();
0208: if (invocationType == declaringClass)
0209: return true;
0210:
0211: if (isProtected()) {
0212: // answer true if the receiver is in the same package as the invocationType
0213: if (invocationType.fPackage == declaringClass.fPackage)
0214: return true;
0215: return invocationSite.isSuperAccess();
0216: }
0217:
0218: if (isPrivate()) {
0219: // answer true if the invocationType and the declaringClass have a common enclosingType
0220: // already know they are not the identical type
0221: ReferenceBinding outerInvocationType = invocationType;
0222: ReferenceBinding temp = outerInvocationType.enclosingType();
0223: while (temp != null) {
0224: outerInvocationType = temp;
0225: temp = temp.enclosingType();
0226: }
0227:
0228: ReferenceBinding outerDeclaringClass = (ReferenceBinding) declaringClass
0229: .erasure();
0230: temp = outerDeclaringClass.enclosingType();
0231: while (temp != null) {
0232: outerDeclaringClass = temp;
0233: temp = temp.enclosingType();
0234: }
0235: return outerInvocationType == outerDeclaringClass;
0236: }
0237:
0238: // isDefault()
0239: return invocationType.fPackage == declaringClass.fPackage;
0240: }
0241:
0242: /* Answer true if the receiver is visible to the type provided by the scope.
0243: * InvocationSite implements isSuperAccess() to provide additional information
0244: * if the receiver is protected.
0245: *
0246: * NOTE: Cannot invoke this method with a compilation unit scope.
0247: */
0248: public final boolean canBeSeenBy(TypeBinding receiverType,
0249: InvocationSite invocationSite, Scope scope) {
0250: if (isPublic())
0251: return true;
0252:
0253: SourceTypeBinding invocationType = scope.enclosingSourceType();
0254: if (invocationType == declaringClass
0255: && invocationType == receiverType)
0256: return true;
0257:
0258: if (invocationType == null) // static import call
0259: return !isPrivate()
0260: && scope.getCurrentPackage() == declaringClass.fPackage;
0261:
0262: if (isProtected()) {
0263: // answer true if the invocationType is the declaringClass or they are in the same package
0264: // OR the invocationType is a subclass of the declaringClass
0265: // AND the receiverType is the invocationType or its subclass
0266: // OR the method is a static method accessed directly through a type
0267: // OR previous assertions are true for one of the enclosing type
0268: if (invocationType == declaringClass)
0269: return true;
0270: if (invocationType.fPackage == declaringClass.fPackage)
0271: return true;
0272:
0273: ReferenceBinding currentType = invocationType;
0274: TypeBinding receiverErasure = receiverType.erasure();
0275: ReferenceBinding declaringErasure = (ReferenceBinding) declaringClass
0276: .erasure();
0277: int depth = 0;
0278: do {
0279: if (currentType
0280: .findSuperTypeWithSameErasure(declaringErasure) != null) {
0281: if (invocationSite.isSuperAccess())
0282: return true;
0283: // receiverType can be an array binding in one case... see if you can change it
0284: if (receiverType instanceof ArrayBinding)
0285: return false;
0286: if (isStatic()) {
0287: if (depth > 0)
0288: invocationSite.setDepth(depth);
0289: return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
0290: }
0291: if (currentType == receiverErasure
0292: || receiverErasure
0293: .findSuperTypeWithSameErasure(currentType) != null) {
0294: if (depth > 0)
0295: invocationSite.setDepth(depth);
0296: return true;
0297: }
0298: }
0299: depth++;
0300: currentType = currentType.enclosingType();
0301: } while (currentType != null);
0302: return false;
0303: }
0304:
0305: if (isPrivate()) {
0306: // answer true if the receiverType is the declaringClass
0307: // AND the invocationType and the declaringClass have a common enclosingType
0308: receiverCheck: {
0309: if (receiverType != declaringClass) {
0310: // special tolerance for type variable direct bounds
0311: if (receiverType.isTypeVariable()
0312: && ((TypeVariableBinding) receiverType)
0313: .isErasureBoundTo(declaringClass
0314: .erasure()))
0315: break receiverCheck;
0316: return false;
0317: }
0318: }
0319:
0320: if (invocationType != declaringClass) {
0321: ReferenceBinding outerInvocationType = invocationType;
0322: ReferenceBinding temp = outerInvocationType
0323: .enclosingType();
0324: while (temp != null) {
0325: outerInvocationType = temp;
0326: temp = temp.enclosingType();
0327: }
0328:
0329: ReferenceBinding outerDeclaringClass = (ReferenceBinding) declaringClass
0330: .erasure();
0331: temp = outerDeclaringClass.enclosingType();
0332: while (temp != null) {
0333: outerDeclaringClass = temp;
0334: temp = temp.enclosingType();
0335: }
0336: if (outerInvocationType != outerDeclaringClass)
0337: return false;
0338: }
0339: return true;
0340: }
0341:
0342: // isDefault()
0343: PackageBinding declaringPackage = declaringClass.fPackage;
0344: if (invocationType.fPackage != declaringPackage)
0345: return false;
0346:
0347: // receiverType can be an array binding in one case... see if you can change it
0348: if (receiverType instanceof ArrayBinding)
0349: return false;
0350: ReferenceBinding currentType = (ReferenceBinding) receiverType;
0351: do {
0352: if (declaringClass == currentType)
0353: return true;
0354: PackageBinding currentPackage = currentType.fPackage;
0355: // package could be null for wildcards/intersection types, ignore and recurse in superclass
0356: if (currentPackage != null
0357: && currentPackage != declaringPackage)
0358: return false;
0359: } while ((currentType = currentType.super class()) != null);
0360: return false;
0361: }
0362:
0363: MethodBinding computeSubstitutedMethod(MethodBinding method,
0364: LookupEnvironment env) {
0365: int length = this .typeVariables.length;
0366: TypeVariableBinding[] vars = method.typeVariables;
0367: if (length != vars.length)
0368: return null;
0369:
0370: // must substitute to detect cases like:
0371: // <T1 extends X<T1>> void dup() {}
0372: // <T2 extends X<T2>> Object dup() {return null;}
0373: ParameterizedGenericMethodBinding substitute = env
0374: .createParameterizedGenericMethod(method,
0375: this .typeVariables);
0376: for (int i = 0; i < length; i++)
0377: if (!this .typeVariables[i].isInterchangeableWith(vars[i],
0378: substitute))
0379: return null;
0380: return substitute;
0381: }
0382:
0383: /*
0384: * declaringUniqueKey dot selector genericSignature
0385: * p.X { <T> void bar(X<T> t) } --> Lp/X;.bar<T:Ljava/lang/Object;>(LX<TT;>;)V
0386: */
0387: public char[] computeUniqueKey(boolean isLeaf) {
0388: // declaring class
0389: char[] declaringKey = this .declaringClass
0390: .computeUniqueKey(false/*not a leaf*/);
0391: int declaringLength = declaringKey.length;
0392:
0393: // selector
0394: int selectorLength = this .selector == TypeConstants.INIT ? 0
0395: : this .selector.length;
0396:
0397: // generic signature
0398: char[] sig = genericSignature();
0399: boolean isGeneric = sig != null;
0400: if (!isGeneric)
0401: sig = signature();
0402: int signatureLength = sig.length;
0403:
0404: // thrown exceptions
0405: int thrownExceptionsLength = this .thrownExceptions.length;
0406: int thrownExceptionsSignatureLength = 0;
0407: char[][] thrownExceptionsSignatures = null;
0408: boolean addThrownExceptions = thrownExceptionsLength > 0
0409: && (!isGeneric || CharOperation.lastIndexOf('^', sig) < 0);
0410: if (addThrownExceptions) {
0411: thrownExceptionsSignatures = new char[thrownExceptionsLength][];
0412: for (int i = 0; i < thrownExceptionsLength; i++) {
0413: if (this .thrownExceptions[i] != null) {
0414: thrownExceptionsSignatures[i] = this .thrownExceptions[i]
0415: .signature();
0416: thrownExceptionsSignatureLength += thrownExceptionsSignatures[i].length + 1; // add one char for separator
0417: }
0418: }
0419: }
0420:
0421: char[] uniqueKey = new char[declaringLength + 1
0422: + selectorLength + signatureLength
0423: + thrownExceptionsSignatureLength];
0424: int index = 0;
0425: System.arraycopy(declaringKey, 0, uniqueKey, index,
0426: declaringLength);
0427: index = declaringLength;
0428: uniqueKey[index++] = '.';
0429: System.arraycopy(this .selector, 0, uniqueKey, index,
0430: selectorLength);
0431: index += selectorLength;
0432: System.arraycopy(sig, 0, uniqueKey, index, signatureLength);
0433: if (thrownExceptionsSignatureLength > 0) {
0434: index += signatureLength;
0435: for (int i = 0; i < thrownExceptionsLength; i++) {
0436: char[] thrownExceptionSignature = thrownExceptionsSignatures[i];
0437: if (thrownExceptionSignature != null) {
0438: uniqueKey[index++] = '|';
0439: int length = thrownExceptionSignature.length;
0440: System.arraycopy(thrownExceptionSignature, 0,
0441: uniqueKey, index, length);
0442: index += length;
0443: }
0444: }
0445: }
0446:
0447: return uniqueKey;
0448: }
0449:
0450: /*
0451: * Answer the declaring class to use in the constant pool
0452: * may not be a reference binding (see subtypes)
0453: */
0454: public TypeBinding constantPoolDeclaringClass() {
0455: return this .declaringClass;
0456: }
0457:
0458: /* Answer the receiver's constant pool name.
0459: *
0460: * <init> for constructors
0461: * <clinit> for clinit methods
0462: * or the source name of the method
0463: */
0464: public final char[] constantPoolName() {
0465: return selector;
0466: }
0467:
0468: /**
0469: *<typeParam1 ... typeParamM>(param1 ... paramN)returnType thrownException1 ... thrownExceptionP
0470: * T foo(T t) throws X<T> ---> (TT;)TT;LX<TT;>;
0471: * void bar(X<T> t) --> (LX<TT;>;)V
0472: * <T> void bar(X<T> t) --> <T:Ljava.lang.Object;>(LX<TT;>;)V
0473: */
0474: public char[] genericSignature() {
0475: if ((this .modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0)
0476: return null;
0477: StringBuffer sig = new StringBuffer(10);
0478: if (this .typeVariables != Binding.NO_TYPE_VARIABLES) {
0479: sig.append('<');
0480: for (int i = 0, length = this .typeVariables.length; i < length; i++) {
0481: sig.append(this .typeVariables[i].genericSignature());
0482: }
0483: sig.append('>');
0484: }
0485: sig.append('(');
0486: for (int i = 0, length = this .parameters.length; i < length; i++) {
0487: sig.append(this .parameters[i].genericTypeSignature());
0488: }
0489: sig.append(')');
0490: if (this .returnType != null)
0491: sig.append(this .returnType.genericTypeSignature());
0492:
0493: // only append thrown exceptions if any is generic/parameterized
0494: boolean needExceptionSignatures = false;
0495: int length = this .thrownExceptions.length;
0496: for (int i = 0; i < length; i++) {
0497: if ((this .thrownExceptions[i].modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) {
0498: needExceptionSignatures = true;
0499: break;
0500: }
0501: }
0502: if (needExceptionSignatures) {
0503: for (int i = 0; i < length; i++) {
0504: sig.append('^');
0505: sig.append(this .thrownExceptions[i]
0506: .genericTypeSignature());
0507: }
0508: }
0509: int sigLength = sig.length();
0510: char[] genericSignature = new char[sigLength];
0511: sig.getChars(0, sigLength, genericSignature, 0);
0512: return genericSignature;
0513: }
0514:
0515: public AnnotationBinding[] getAnnotations() {
0516: MethodBinding originalMethod = this .original();
0517: return originalMethod.declaringClass
0518: .retrieveAnnotations(originalMethod);
0519: }
0520:
0521: /**
0522: * @param index the index of the parameter of interest
0523: * @return the annotations on the <code>index</code>th parameter
0524: * @throws ArrayIndexOutOfBoundsException when <code>index</code> is not valid
0525: */
0526: public AnnotationBinding[] getParameterAnnotations(int index) {
0527: MethodBinding originalMethod = this .original();
0528: AnnotationHolder holder = originalMethod.declaringClass
0529: .retrieveAnnotationHolder(originalMethod, true);
0530: return holder == null ? Binding.NO_ANNOTATIONS : holder
0531: .getParameterAnnotations(index);
0532: }
0533:
0534: public final int getAccessFlags() {
0535: return modifiers & ExtraCompilerModifiers.AccJustFlag;
0536: }
0537:
0538: /**
0539: * Compute the tagbits for standard annotations. For source types, these could require
0540: * lazily resolving corresponding annotation nodes, in case of forward references.
0541: * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
0542: */
0543: public long getAnnotationTagBits() {
0544: MethodBinding originalMethod = this .original();
0545: if ((originalMethod.tagBits & TagBits.AnnotationResolved) == 0
0546: && originalMethod.declaringClass instanceof SourceTypeBinding) {
0547: ClassScope scope = ((SourceTypeBinding) originalMethod.declaringClass).scope;
0548: if (scope != null) {
0549: TypeDeclaration typeDecl = scope.referenceContext;
0550: AbstractMethodDeclaration methodDecl = typeDecl
0551: .declarationOf(originalMethod);
0552: if (methodDecl != null)
0553: ASTNode.resolveAnnotations(methodDecl.scope,
0554: methodDecl.annotations, originalMethod);
0555: }
0556: }
0557: return originalMethod.tagBits;
0558: }
0559:
0560: /**
0561: * @return the default value for this annotation method or <code>null</code> if there is no default value
0562: */
0563: public Object getDefaultValue() {
0564: MethodBinding originalMethod = this .original();
0565: if ((originalMethod.tagBits & TagBits.DefaultValueResolved) == 0) {
0566: //The method has not been resolved nor has its class been resolved.
0567: //It can only be from a source type within compilation units to process.
0568: if (originalMethod.declaringClass instanceof SourceTypeBinding) {
0569: SourceTypeBinding sourceType = (SourceTypeBinding) originalMethod.declaringClass;
0570: if (sourceType.scope != null) {
0571: AbstractMethodDeclaration methodDeclaration = originalMethod
0572: .sourceMethod();
0573: if (methodDeclaration != null
0574: && methodDeclaration.isAnnotationMethod()) {
0575: methodDeclaration.resolve(sourceType.scope);
0576: }
0577: }
0578: }
0579: originalMethod.tagBits |= TagBits.DefaultValueResolved;
0580: }
0581: AnnotationHolder holder = originalMethod.declaringClass
0582: .retrieveAnnotationHolder(originalMethod, true);
0583: return holder == null ? null : holder.getDefaultValue();
0584: }
0585:
0586: public TypeVariableBinding getTypeVariable(char[] variableName) {
0587: for (int i = this .typeVariables.length; --i >= 0;)
0588: if (CharOperation.equals(this .typeVariables[i].sourceName,
0589: variableName))
0590: return this .typeVariables[i];
0591: return null;
0592: }
0593:
0594: /**
0595: * Returns true if method got substituted parameter types
0596: * (see ParameterizedMethodBinding)
0597: */
0598: public boolean hasSubstitutedParameters() {
0599: return false;
0600: }
0601:
0602: /* Answer true if the return type got substituted.
0603: */
0604: public boolean hasSubstitutedReturnType() {
0605: return false;
0606: }
0607:
0608: /* Answer true if the receiver is an abstract method
0609: */
0610: public final boolean isAbstract() {
0611: return (modifiers & ClassFileConstants.AccAbstract) != 0;
0612: }
0613:
0614: /* Answer true if the receiver is a bridge method
0615: */
0616: public final boolean isBridge() {
0617: return (modifiers & ClassFileConstants.AccBridge) != 0;
0618: }
0619:
0620: /* Answer true if the receiver is a constructor
0621: */
0622: public final boolean isConstructor() {
0623: return selector == TypeConstants.INIT;
0624: }
0625:
0626: /* Answer true if the receiver has default visibility
0627: */
0628: public final boolean isDefault() {
0629: return !isPublic() && !isProtected() && !isPrivate();
0630: }
0631:
0632: /* Answer true if the receiver is a system generated default abstract method
0633: */
0634: public final boolean isDefaultAbstract() {
0635: return (modifiers & ExtraCompilerModifiers.AccDefaultAbstract) != 0;
0636: }
0637:
0638: /* Answer true if the receiver is a deprecated method
0639: */
0640: public final boolean isDeprecated() {
0641: return (modifiers & ClassFileConstants.AccDeprecated) != 0;
0642: }
0643:
0644: /* Answer true if the receiver is final and cannot be overridden
0645: */
0646: public final boolean isFinal() {
0647: return (modifiers & ClassFileConstants.AccFinal) != 0;
0648: }
0649:
0650: /* Answer true if the receiver is implementing another method
0651: * in other words, it is overriding and concrete, and overriden method is abstract
0652: * Only set for source methods
0653: */
0654: public final boolean isImplementing() {
0655: return (modifiers & ExtraCompilerModifiers.AccImplementing) != 0;
0656: }
0657:
0658: /* Answer true if the receiver is a native method
0659: */
0660: public final boolean isNative() {
0661: return (modifiers & ClassFileConstants.AccNative) != 0;
0662: }
0663:
0664: /* Answer true if the receiver is overriding another method
0665: * Only set for source methods
0666: */
0667: public final boolean isOverriding() {
0668: return (modifiers & ExtraCompilerModifiers.AccOverriding) != 0;
0669: }
0670:
0671: /*
0672: * Answer true if the receiver is a "public static void main(String[])" method
0673: */
0674: public final boolean isMain() {
0675: if (this .selector.length == 4
0676: && CharOperation.equals(this .selector,
0677: TypeConstants.MAIN)
0678: && ((this .modifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccStatic)) != 0)
0679: && TypeBinding.VOID == this .returnType
0680: && this .parameters.length == 1) {
0681: TypeBinding paramType = this .parameters[0];
0682: if (paramType.dimensions() == 1
0683: && paramType.leafComponentType().id == TypeIds.T_JavaLangString) {
0684: return true;
0685: }
0686: }
0687: return false;
0688: }
0689:
0690: /* Answer true if the receiver has private visibility
0691: */
0692: public final boolean isPrivate() {
0693: return (modifiers & ClassFileConstants.AccPrivate) != 0;
0694: }
0695:
0696: /* Answer true if the receiver has private visibility and is used locally
0697: */
0698: public final boolean isUsed() {
0699: return (modifiers & ExtraCompilerModifiers.AccLocallyUsed) != 0;
0700: }
0701:
0702: /* Answer true if the receiver has protected visibility
0703: */
0704: public final boolean isProtected() {
0705: return (modifiers & ClassFileConstants.AccProtected) != 0;
0706: }
0707:
0708: /* Answer true if the receiver has public visibility
0709: */
0710: public final boolean isPublic() {
0711: return (modifiers & ClassFileConstants.AccPublic) != 0;
0712: }
0713:
0714: /* Answer true if the receiver is a static method
0715: */
0716: public final boolean isStatic() {
0717: return (modifiers & ClassFileConstants.AccStatic) != 0;
0718: }
0719:
0720: /* Answer true if all float operations must adher to IEEE 754 float/double rules
0721: */
0722: public final boolean isStrictfp() {
0723: return (modifiers & ClassFileConstants.AccStrictfp) != 0;
0724: }
0725:
0726: /* Answer true if the receiver is a synchronized method
0727: */
0728: public final boolean isSynchronized() {
0729: return (modifiers & ClassFileConstants.AccSynchronized) != 0;
0730: }
0731:
0732: /* Answer true if the receiver has public visibility
0733: */
0734: public final boolean isSynthetic() {
0735: return (modifiers & ClassFileConstants.AccSynthetic) != 0;
0736: }
0737:
0738: /* Answer true if the receiver method has varargs
0739: */
0740: public final boolean isVarargs() {
0741: return (modifiers & ClassFileConstants.AccVarargs) != 0;
0742: }
0743:
0744: /* Answer true if the receiver's declaring type is deprecated (or any of its enclosing types)
0745: */
0746: public final boolean isViewedAsDeprecated() {
0747: return (modifiers & (ClassFileConstants.AccDeprecated | ExtraCompilerModifiers.AccDeprecatedImplicitly)) != 0;
0748: }
0749:
0750: /**
0751: * Returns the original method (as opposed to parameterized instances)
0752: */
0753: public MethodBinding original() {
0754: return this ;
0755: }
0756:
0757: public char[] readableName() /* foo(int, Thread) */{
0758: StringBuffer buffer = new StringBuffer(
0759: parameters.length + 1 * 20);
0760: if (isConstructor())
0761: buffer.append(declaringClass.sourceName());
0762: else
0763: buffer.append(selector);
0764: buffer.append('(');
0765: if (parameters != Binding.NO_PARAMETERS) {
0766: for (int i = 0, length = parameters.length; i < length; i++) {
0767: if (i > 0)
0768: buffer.append(", "); //$NON-NLS-1$
0769: buffer.append(parameters[i].sourceName());
0770: }
0771: }
0772: buffer.append(')');
0773: return buffer.toString().toCharArray();
0774: }
0775:
0776: public void setAnnotations(AnnotationBinding[] annotations) {
0777: this .declaringClass.storeAnnotations(this , annotations);
0778: }
0779:
0780: public void setAnnotations(AnnotationBinding[] annotations,
0781: AnnotationBinding[][] parameterAnnotations,
0782: Object defaultValue) {
0783: this .declaringClass.storeAnnotationHolder(this ,
0784: AnnotationHolder.storeAnnotations(annotations,
0785: parameterAnnotations, defaultValue));
0786: }
0787:
0788: public void setDefaultValue(Object defaultValue) {
0789: MethodBinding originalMethod = this .original();
0790: originalMethod.tagBits |= TagBits.DefaultValueResolved;
0791:
0792: AnnotationHolder holder = this .declaringClass
0793: .retrieveAnnotationHolder(this , false);
0794: if (holder == null)
0795: setAnnotations(null, null, defaultValue);
0796: else
0797: setAnnotations(holder.getAnnotations(), holder
0798: .getParameterAnnotations(), defaultValue);
0799: }
0800:
0801: public void setParameterAnnotations(
0802: AnnotationBinding[][] parameterAnnotations) {
0803: AnnotationHolder holder = this .declaringClass
0804: .retrieveAnnotationHolder(this , false);
0805: if (holder == null)
0806: setAnnotations(null, parameterAnnotations, null);
0807: else
0808: setAnnotations(holder.getAnnotations(),
0809: parameterAnnotations, holder.getDefaultValue());
0810: }
0811:
0812: /**
0813: * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
0814: */
0815: public char[] shortReadableName() {
0816: StringBuffer buffer = new StringBuffer(
0817: parameters.length + 1 * 20);
0818: if (isConstructor())
0819: buffer.append(declaringClass.shortReadableName());
0820: else
0821: buffer.append(selector);
0822: buffer.append('(');
0823: if (parameters != Binding.NO_PARAMETERS) {
0824: for (int i = 0, length = parameters.length; i < length; i++) {
0825: if (i > 0)
0826: buffer.append(", "); //$NON-NLS-1$
0827: buffer.append(parameters[i].shortReadableName());
0828: }
0829: }
0830: buffer.append(')');
0831: int nameLength = buffer.length();
0832: char[] shortReadableName = new char[nameLength];
0833: buffer.getChars(0, nameLength, shortReadableName, 0);
0834: return shortReadableName;
0835: }
0836:
0837: protected final void setSelector(char[] selector) {
0838: this .selector = selector;
0839: this .signature = null;
0840: }
0841:
0842: /* Answer the receiver's signature.
0843: *
0844: * NOTE: This method should only be used during/after code gen.
0845: * The signature is cached so if the signature of the return type or any parameter
0846: * type changes, the cached state is invalid.
0847: */
0848: public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */{
0849: if (signature != null)
0850: return signature;
0851:
0852: StringBuffer buffer = new StringBuffer(
0853: parameters.length + 1 * 20);
0854: buffer.append('(');
0855:
0856: TypeBinding[] targetParameters = this .parameters;
0857: boolean isConstructor = isConstructor();
0858: if (isConstructor && declaringClass.isEnum()) { // insert String name,int ordinal
0859: buffer.append(ConstantPool.JavaLangStringSignature);
0860: buffer.append(TypeBinding.INT.signature());
0861: }
0862: boolean needSynthetics = isConstructor
0863: && declaringClass.isNestedType();
0864: if (needSynthetics) {
0865: // take into account the synthetic argument type signatures as well
0866: ReferenceBinding[] syntheticArgumentTypes = declaringClass
0867: .syntheticEnclosingInstanceTypes();
0868: if (syntheticArgumentTypes != null) {
0869: for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) {
0870: buffer
0871: .append(syntheticArgumentTypes[i]
0872: .signature());
0873: }
0874: }
0875:
0876: if (this instanceof SyntheticMethodBinding) {
0877: targetParameters = ((SyntheticMethodBinding) this ).targetMethod.parameters;
0878: }
0879: }
0880:
0881: if (targetParameters != Binding.NO_PARAMETERS) {
0882: for (int i = 0; i < targetParameters.length; i++) {
0883: buffer.append(targetParameters[i].signature());
0884: }
0885: }
0886: if (needSynthetics) {
0887: SyntheticArgumentBinding[] syntheticOuterArguments = declaringClass
0888: .syntheticOuterLocalVariables();
0889: int count = syntheticOuterArguments == null ? 0
0890: : syntheticOuterArguments.length;
0891: for (int i = 0; i < count; i++) {
0892: buffer.append(syntheticOuterArguments[i].type
0893: .signature());
0894: }
0895: // move the extra padding arguments of the synthetic constructor invocation to the end
0896: for (int i = targetParameters.length, extraLength = parameters.length; i < extraLength; i++) {
0897: buffer.append(parameters[i].signature());
0898: }
0899: }
0900: buffer.append(')');
0901: if (this .returnType != null)
0902: buffer.append(this .returnType.signature());
0903: int nameLength = buffer.length();
0904: signature = new char[nameLength];
0905: buffer.getChars(0, nameLength, signature, 0);
0906:
0907: return signature;
0908: }
0909:
0910: /*
0911: * This method is used to record references to nested types inside the method signature.
0912: * This is the one that must be used during code generation.
0913: *
0914: * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=171184
0915: */
0916: public final char[] signature(ClassFile classFile) {
0917: if (signature != null) {
0918: if ((this .tagBits & TagBits.ContainsNestedTypesInSignature) != 0) {
0919: // we need to record inner classes references
0920: boolean isConstructor = isConstructor();
0921: TypeBinding[] targetParameters = this .parameters;
0922: boolean needSynthetics = isConstructor
0923: && declaringClass.isNestedType();
0924: if (needSynthetics) {
0925: // take into account the synthetic argument type signatures as well
0926: ReferenceBinding[] syntheticArgumentTypes = declaringClass
0927: .syntheticEnclosingInstanceTypes();
0928: if (syntheticArgumentTypes != null) {
0929: for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) {
0930: ReferenceBinding syntheticArgumentType = syntheticArgumentTypes[i];
0931: if (syntheticArgumentType.isNestedType()) {
0932: classFile
0933: .recordInnerClasses(syntheticArgumentType);
0934: }
0935: }
0936: }
0937: if (this instanceof SyntheticMethodBinding) {
0938: targetParameters = ((SyntheticMethodBinding) this ).targetMethod.parameters;
0939: }
0940: }
0941:
0942: if (targetParameters != Binding.NO_PARAMETERS) {
0943: for (int i = 0; i < targetParameters.length; i++) {
0944: TypeBinding targetParameter = targetParameters[i];
0945: TypeBinding leafTargetParameterType = targetParameter
0946: .leafComponentType();
0947: if (leafTargetParameterType.isNestedType()) {
0948: classFile
0949: .recordInnerClasses(leafTargetParameterType);
0950: }
0951: }
0952: }
0953: if (needSynthetics) {
0954: // move the extra padding arguments of the synthetic constructor invocation to the end
0955: for (int i = targetParameters.length, extraLength = parameters.length; i < extraLength; i++) {
0956: TypeBinding parameter = parameters[i];
0957: TypeBinding leafParameterType = parameter
0958: .leafComponentType();
0959: if (leafParameterType.isNestedType()) {
0960: classFile
0961: .recordInnerClasses(leafParameterType);
0962: }
0963: }
0964: }
0965: if (this .returnType != null) {
0966: TypeBinding ret = this .returnType
0967: .leafComponentType();
0968: if (ret.isNestedType()) {
0969: classFile.recordInnerClasses(ret);
0970: }
0971: }
0972: }
0973: return signature;
0974: }
0975:
0976: StringBuffer buffer = new StringBuffer(
0977: parameters.length + 1 * 20);
0978: buffer.append('(');
0979:
0980: TypeBinding[] targetParameters = this .parameters;
0981: boolean isConstructor = isConstructor();
0982: if (isConstructor && declaringClass.isEnum()) { // insert String name,int ordinal
0983: buffer.append(ConstantPool.JavaLangStringSignature);
0984: buffer.append(TypeBinding.INT.signature());
0985: }
0986: boolean needSynthetics = isConstructor
0987: && declaringClass.isNestedType();
0988: if (needSynthetics) {
0989: // take into account the synthetic argument type signatures as well
0990: ReferenceBinding[] syntheticArgumentTypes = declaringClass
0991: .syntheticEnclosingInstanceTypes();
0992: if (syntheticArgumentTypes != null) {
0993: for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) {
0994: ReferenceBinding syntheticArgumentType = syntheticArgumentTypes[i];
0995: if (syntheticArgumentType.isNestedType()) {
0996: this .tagBits |= TagBits.ContainsNestedTypesInSignature;
0997: classFile
0998: .recordInnerClasses(syntheticArgumentType);
0999: }
1000: buffer.append(syntheticArgumentType.signature());
1001: }
1002: }
1003:
1004: if (this instanceof SyntheticMethodBinding) {
1005: targetParameters = ((SyntheticMethodBinding) this ).targetMethod.parameters;
1006: }
1007: }
1008:
1009: if (targetParameters != Binding.NO_PARAMETERS) {
1010: for (int i = 0; i < targetParameters.length; i++) {
1011: TypeBinding targetParameter = targetParameters[i];
1012: TypeBinding leafTargetParameterType = targetParameter
1013: .leafComponentType();
1014: if (leafTargetParameterType.isNestedType()) {
1015: this .tagBits |= TagBits.ContainsNestedTypesInSignature;
1016: classFile
1017: .recordInnerClasses(leafTargetParameterType);
1018: }
1019: buffer.append(targetParameter.signature());
1020: }
1021: }
1022: if (needSynthetics) {
1023: SyntheticArgumentBinding[] syntheticOuterArguments = declaringClass
1024: .syntheticOuterLocalVariables();
1025: int count = syntheticOuterArguments == null ? 0
1026: : syntheticOuterArguments.length;
1027: for (int i = 0; i < count; i++) {
1028: buffer.append(syntheticOuterArguments[i].type
1029: .signature());
1030: }
1031: // move the extra padding arguments of the synthetic constructor invocation to the end
1032: for (int i = targetParameters.length, extraLength = parameters.length; i < extraLength; i++) {
1033: TypeBinding parameter = parameters[i];
1034: TypeBinding leafParameterType = parameter
1035: .leafComponentType();
1036: if (leafParameterType.isNestedType()) {
1037: this .tagBits |= TagBits.ContainsNestedTypesInSignature;
1038: classFile.recordInnerClasses(leafParameterType);
1039: }
1040: buffer.append(parameter.signature());
1041: }
1042: }
1043: buffer.append(')');
1044: if (this .returnType != null) {
1045: TypeBinding ret = this .returnType.leafComponentType();
1046: if (ret.isNestedType()) {
1047: this .tagBits |= TagBits.ContainsNestedTypesInSignature;
1048: classFile.recordInnerClasses(ret);
1049: }
1050: buffer.append(this .returnType.signature());
1051: }
1052: int nameLength = buffer.length();
1053: signature = new char[nameLength];
1054: buffer.getChars(0, nameLength, signature, 0);
1055:
1056: return signature;
1057: }
1058:
1059: public final int sourceEnd() {
1060: AbstractMethodDeclaration method = sourceMethod();
1061: if (method == null) {
1062: if (this .declaringClass instanceof SourceTypeBinding)
1063: return ((SourceTypeBinding) this .declaringClass)
1064: .sourceEnd();
1065: return 0;
1066: }
1067: return method.sourceEnd;
1068: }
1069:
1070: public AbstractMethodDeclaration sourceMethod() {
1071: SourceTypeBinding sourceType;
1072: try {
1073: sourceType = (SourceTypeBinding) declaringClass;
1074: } catch (ClassCastException e) {
1075: return null;
1076: }
1077:
1078: AbstractMethodDeclaration[] methods = sourceType.scope.referenceContext.methods;
1079: for (int i = methods.length; --i >= 0;)
1080: if (this == methods[i].binding)
1081: return methods[i];
1082: return null;
1083: }
1084:
1085: public final int sourceStart() {
1086: AbstractMethodDeclaration method = sourceMethod();
1087: if (method == null) {
1088: if (this .declaringClass instanceof SourceTypeBinding)
1089: return ((SourceTypeBinding) this .declaringClass)
1090: .sourceStart();
1091: return 0;
1092: }
1093: return method.sourceStart;
1094: }
1095:
1096: public String toString() {
1097: String s = (returnType != null) ? returnType.debugName()
1098: : "NULL TYPE"; //$NON-NLS-1$
1099: s += " "; //$NON-NLS-1$
1100: s += (selector != null) ? new String(selector)
1101: : "UNNAMED METHOD"; //$NON-NLS-1$
1102:
1103: s += "("; //$NON-NLS-1$
1104: if (parameters != null) {
1105: if (parameters != Binding.NO_PARAMETERS) {
1106: for (int i = 0, length = parameters.length; i < length; i++) {
1107: if (i > 0)
1108: s += ", "; //$NON-NLS-1$
1109: s += (parameters[i] != null) ? parameters[i]
1110: .debugName() : "NULL TYPE"; //$NON-NLS-1$
1111: }
1112: }
1113: } else {
1114: s += "NULL PARAMETERS"; //$NON-NLS-1$
1115: }
1116: s += ") "; //$NON-NLS-1$
1117:
1118: if (thrownExceptions != null) {
1119: if (thrownExceptions != Binding.NO_EXCEPTIONS) {
1120: s += "throws "; //$NON-NLS-1$
1121: for (int i = 0, length = thrownExceptions.length; i < length; i++) {
1122: if (i > 0)
1123: s += ", "; //$NON-NLS-1$
1124: s += (thrownExceptions[i] != null) ? thrownExceptions[i]
1125: .debugName()
1126: : "NULL TYPE"; //$NON-NLS-1$
1127: }
1128: }
1129: } else {
1130: s += "NULL THROWN EXCEPTIONS"; //$NON-NLS-1$
1131: }
1132: return s;
1133: }
1134:
1135: /**
1136: * Returns the method to use during tiebreak (usually the method itself).
1137: * For generic method invocations, tiebreak needs to use generic method with erasure substitutes.
1138: */
1139: public MethodBinding tiebreakMethod() {
1140: return this ;
1141: }
1142:
1143: public TypeVariableBinding[] typeVariables() {
1144: return this.typeVariables;
1145: }
1146: }
|