1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
13 import net.sourceforge.phpdt.core.compiler.CharOperation;
14 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
15 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
17 public class MethodBinding extends Binding implements BaseTypes, TypeConstants {
20 public char[] selector;
22 public TypeBinding returnType;
24 public TypeBinding[] parameters;
26 public ReferenceBinding[] thrownExceptions;
28 public ReferenceBinding declaringClass;
32 protected MethodBinding() {
35 public MethodBinding(int modifiers, char[] selector,
36 TypeBinding returnType, TypeBinding[] args,
37 ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
38 this.modifiers = modifiers;
39 this.selector = selector;
40 this.returnType = returnType;
41 this.parameters = (args == null || args.length == 0) ? NoParameters
43 this.thrownExceptions = (exceptions == null || exceptions.length == 0) ? NoExceptions
45 this.declaringClass = declaringClass;
47 // propagate the strictfp & deprecated modifiers
48 if (this.declaringClass != null) {
49 // if (this.declaringClass.isStrictfp())
50 // if (!(isNative() || isAbstract()))
51 // this.modifiers |= AccStrictfp;
52 if (this.declaringClass.isViewedAsDeprecated() && !isDeprecated())
53 this.modifiers |= AccDeprecatedImplicitly;
57 public MethodBinding(int modifiers, TypeBinding[] args,
58 ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
59 this(modifiers, ConstructorDeclaration.ConstantPoolName, VoidBinding,
60 args, exceptions, declaringClass);
63 // special API used to change method declaring class for runtime visibility
65 public MethodBinding(MethodBinding initialMethodBinding,
66 ReferenceBinding declaringClass) {
67 this.modifiers = initialMethodBinding.modifiers;
68 this.selector = initialMethodBinding.selector;
69 this.returnType = initialMethodBinding.returnType;
70 this.parameters = initialMethodBinding.parameters;
71 this.thrownExceptions = initialMethodBinding.thrownExceptions;
72 this.declaringClass = declaringClass;
76 * Answer true if the argument types & the receiver's parameters are equal
79 public final boolean areParametersEqual(MethodBinding method) {
80 TypeBinding[] args = method.parameters;
81 if (parameters == args)
84 int length = parameters.length;
85 if (length != args.length)
88 for (int i = 0; i < length; i++)
89 if (parameters[i] != args[i])
95 * API Answer the receiver's binding type from Binding.BindingID.
98 public final int bindingType() {
103 * Answer true if the receiver is visible to the type provided by the scope.
104 * InvocationSite implements isSuperAccess() to provide additional
105 * information if the receiver is protected.
107 * NOTE: This method should ONLY be sent if the receiver is a constructor.
109 * NOTE: Cannot invoke this method with a compilation unit scope.
112 public final boolean canBeSeenBy(InvocationSite invocationSite, Scope scope) {
116 SourceTypeBinding invocationType = scope.enclosingSourceType();
117 if (invocationType == declaringClass)
121 // answer true if the receiver is in the same package as the
123 if (invocationType.fPackage == declaringClass.fPackage)
125 return invocationSite.isSuperAccess();
129 // answer true if the invocationType and the declaringClass have a
130 // common enclosingType
131 // already know they are not the identical type
132 ReferenceBinding outerInvocationType = invocationType;
133 ReferenceBinding temp = outerInvocationType.enclosingType();
134 while (temp != null) {
135 outerInvocationType = temp;
136 temp = temp.enclosingType();
139 ReferenceBinding outerDeclaringClass = declaringClass;
140 temp = outerDeclaringClass.enclosingType();
141 while (temp != null) {
142 outerDeclaringClass = temp;
143 temp = temp.enclosingType();
145 return outerInvocationType == outerDeclaringClass;
149 return invocationType.fPackage == declaringClass.fPackage;
153 * Answer true if the receiver is visible to the type provided by the scope.
154 * InvocationSite implements isSuperAccess() to provide additional
155 * information if the receiver is protected.
157 * NOTE: Cannot invoke this method with a compilation unit scope.
159 public final boolean canBeSeenBy(TypeBinding receiverType,
160 InvocationSite invocationSite, Scope scope) {
164 SourceTypeBinding invocationType = scope.enclosingSourceType();
165 if (invocationType == declaringClass && invocationType == receiverType)
169 // answer true if the invocationType is the declaringClass or they
170 // are in the same package
171 // OR the invocationType is a subclass of the declaringClass
172 // AND the receiverType is the invocationType or its subclass
173 // OR the method is a static method accessed directly through a type
174 // OR previous assertions are true for one of the enclosing type
175 if (invocationType == declaringClass)
177 if (invocationType.fPackage == declaringClass.fPackage)
180 ReferenceBinding currentType = invocationType;
183 if (declaringClass.isSuperclassOf(currentType)) {
184 if (invocationSite.isSuperAccess()) {
187 // receiverType can be an array binding in one case... see
188 // if you can change it
189 if (receiverType instanceof ArrayBinding) {
193 return true; // see 1FMEPDL - return
194 // invocationSite.isTypeAccess();
196 if (currentType == receiverType
198 .isSuperclassOf((ReferenceBinding) receiverType)) {
200 invocationSite.setDepth(depth);
205 currentType = currentType.enclosingType();
206 } while (currentType != null);
211 // answer true if the receiverType is the declaringClass
212 // AND the invocationType and the declaringClass have a common
214 if (receiverType != declaringClass)
217 if (invocationType != declaringClass) {
218 ReferenceBinding outerInvocationType = invocationType;
219 ReferenceBinding temp = outerInvocationType.enclosingType();
220 while (temp != null) {
221 outerInvocationType = temp;
222 temp = temp.enclosingType();
225 ReferenceBinding outerDeclaringClass = declaringClass;
226 temp = outerDeclaringClass.enclosingType();
227 while (temp != null) {
228 outerDeclaringClass = temp;
229 temp = temp.enclosingType();
231 if (outerInvocationType != outerDeclaringClass)
238 if (invocationType.fPackage != declaringClass.fPackage)
241 // receiverType can be an array binding in one case... see if you can
243 if (receiverType instanceof ArrayBinding)
245 ReferenceBinding type = (ReferenceBinding) receiverType;
246 PackageBinding declaringPackage = declaringClass.fPackage;
248 if (declaringClass == type)
250 if (declaringPackage != type.fPackage)
252 } while ((type = type.superclass()) != null);
257 * Answer the receiver's constant pool name.
259 * <init> for constructors <clinit> for clinit methods or the source name of
262 public final char[] constantPoolName() {
266 public final int getAccessFlags() {
267 return modifiers & AccJustFlag;
271 * Answer true if the receiver is an abstract method
273 public final boolean isAbstract() {
274 return (modifiers & AccAbstract) != 0;
278 * Answer true if the receiver is a constructor
280 public final boolean isConstructor() {
281 return selector == ConstructorDeclaration.ConstantPoolName;
284 protected boolean isConstructorRelated() {
285 return isConstructor();
289 * Answer true if the receiver has default visibility
291 public final boolean isDefault() {
292 return !isPublic() && !isProtected() && !isPrivate();
296 * Answer true if the receiver is a system generated default abstract method
298 public final boolean isDefaultAbstract() {
299 return (modifiers & AccDefaultAbstract) != 0;
303 * Answer true if the receiver is a deprecated method
305 public final boolean isDeprecated() {
306 return (modifiers & AccDeprecated) != 0;
310 * Answer true if the receiver is final and cannot be overridden
312 public final boolean isFinal() {
313 return (modifiers & AccFinal) != 0;
317 * Answer true if the receiver is implementing another method in other
318 * words, it is overriding and concrete, and overriden method is abstract
319 * Only set for source methods
321 public final boolean isImplementing() {
322 return (modifiers & AccImplementing) != 0;
326 * Answer true if the receiver is a native method
328 // public final boolean isNative() {
329 // return (modifiers & AccNative) != 0;
332 * Answer true if the receiver is overriding another method Only set for
335 public final boolean isOverriding() {
336 return (modifiers & AccOverriding) != 0;
340 * Answer true if the receiver is a "public static void main(String[])"
343 public final boolean isMain() {
344 if (this.selector.length == 4
345 && CharOperation.equals(this.selector, MAIN)
346 && ((this.modifiers & (AccPublic | AccStatic)) != 0)
347 && VoidBinding == this.returnType
348 && this.parameters.length == 1) {
349 TypeBinding paramType = this.parameters[0];
350 if (paramType.dimensions() == 1
351 && paramType.leafComponentType().id == TypeIds.T_JavaLangString) {
359 * Answer true if the receiver has private visibility
361 public final boolean isPrivate() {
362 return (modifiers & AccPrivate) != 0;
366 * Answer true if the receiver has private visibility and is used locally
368 public final boolean isPrivateUsed() {
369 return (modifiers & AccPrivateUsed) != 0;
373 * Answer true if the receiver has protected visibility
375 public final boolean isProtected() {
376 return (modifiers & AccProtected) != 0;
380 * Answer true if the receiver has public visibility
382 public final boolean isPublic() {
383 return (modifiers & AccPublic) != 0;
387 * Answer true if the receiver got requested to clear the private modifier
388 * during private access emulation.
390 public final boolean isRequiredToClearPrivateModifier() {
391 return (modifiers & AccClearPrivateModifier) != 0;
395 * Answer true if the receiver is a static method
397 public final boolean isStatic() {
398 return (modifiers & AccStatic) != 0;
402 * Answer true if all float operations must adher to IEEE 754 float/double
405 // public final boolean isStrictfp() {
406 // return (modifiers & AccStrictfp) != 0;
409 * Answer true if the receiver is a synchronized method
411 // public final boolean isSynchronized() {
412 // return (modifiers & AccSynchronized) != 0;
415 * Answer true if the receiver has public visibility
417 // public final boolean isSynthetic() {
418 // return (modifiers & AccSynthetic) != 0;
421 * Answer true if the receiver's declaring type is deprecated (or any of its
424 public final boolean isViewedAsDeprecated() {
425 return (modifiers & AccDeprecated) != 0
426 || (modifiers & AccDeprecatedImplicitly) != 0;
429 public char[] readableName() /* foo(int, Thread) */{
430 StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
432 buffer.append(declaringClass.sourceName());
434 buffer.append(selector);
436 if (parameters != NoParameters) {
437 for (int i = 0, length = parameters.length; i < length; i++) {
439 buffer.append(", "); //$NON-NLS-1$
440 buffer.append(parameters[i].sourceName());
444 return buffer.toString().toCharArray();
448 * @see net.sourceforge.phpdt.internal.compiler.lookup.Binding#shortReadableName()
450 public char[] shortReadableName() {
451 StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
453 buffer.append(declaringClass.shortReadableName());
455 buffer.append(selector);
457 if (parameters != NoParameters) {
458 for (int i = 0, length = parameters.length; i < length; i++) {
460 buffer.append(", "); //$NON-NLS-1$
461 buffer.append(parameters[i].shortReadableName());
465 return buffer.toString().toCharArray();
468 protected final void selector(char[] selector) {
469 this.selector = selector;
470 this.signature = null;
474 * Answer the receiver's signature.
476 * NOTE: This method should only be used during/after code gen. The
477 * signature is cached so if the signature of the return type or any
478 * parameter type changes, the cached state is invalid.
480 public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */{
481 if (signature != null)
484 StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
487 TypeBinding[] targetParameters = this.parameters;
488 boolean considerSynthetics = isConstructorRelated()
489 && declaringClass.isNestedType();
490 if (considerSynthetics) {
492 // take into account the synthetic argument type signatures as well
493 ReferenceBinding[] syntheticArgumentTypes = declaringClass
494 .syntheticEnclosingInstanceTypes();
495 int count = syntheticArgumentTypes == null ? 0
496 : syntheticArgumentTypes.length;
497 for (int i = 0; i < count; i++) {
498 buffer.append(syntheticArgumentTypes[i].signature());
501 if (this instanceof SyntheticAccessMethodBinding) {
502 targetParameters = ((SyntheticAccessMethodBinding) this).targetMethod.parameters;
506 if (targetParameters != NoParameters) {
507 for (int i = 0; i < targetParameters.length; i++) {
508 buffer.append(targetParameters[i].signature());
511 if (considerSynthetics) {
512 SyntheticArgumentBinding[] syntheticOuterArguments = declaringClass
513 .syntheticOuterLocalVariables();
514 int count = syntheticOuterArguments == null ? 0
515 : syntheticOuterArguments.length;
516 for (int i = 0; i < count; i++) {
517 buffer.append(syntheticOuterArguments[i].type.signature());
519 // move the extra padding arguments of the synthetic constructor
520 // invocation to the end
521 for (int i = targetParameters.length, extraLength = parameters.length; i < extraLength; i++) {
522 buffer.append(parameters[i].signature());
526 buffer.append(returnType.signature());
527 return signature = buffer.toString().toCharArray();
530 public final int sourceEnd() {
531 AbstractMethodDeclaration method = sourceMethod();
535 return method.sourceEnd;
538 AbstractMethodDeclaration sourceMethod() {
539 SourceTypeBinding sourceType;
541 sourceType = (SourceTypeBinding) declaringClass;
542 } catch (ClassCastException e) {
546 AbstractMethodDeclaration[] methods = sourceType.scope.referenceContext.methods;
547 for (int i = methods.length; --i >= 0;)
548 if (this == methods[i].binding)
553 public final int sourceStart() {
554 AbstractMethodDeclaration method = sourceMethod();
558 return method.sourceStart;
562 * During private access emulation, the binding can be requested to loose
563 * its private visibility when the class file is dumped.
566 public final void tagForClearingPrivateModifier() {
567 modifiers |= AccClearPrivateModifier;
570 public String toString() {
571 String s = (returnType != null) ? returnType.debugName() : "NULL TYPE"; //$NON-NLS-1$
572 s += " "; //$NON-NLS-1$
573 s += (selector != null) ? new String(selector) : "UNNAMED METHOD"; //$NON-NLS-1$
575 s += "("; //$NON-NLS-1$
576 if (parameters != null) {
577 if (parameters != NoParameters) {
578 for (int i = 0, length = parameters.length; i < length; i++) {
580 s += ", "; //$NON-NLS-1$
581 s += (parameters[i] != null) ? parameters[i].debugName()
582 : "NULL TYPE"; //$NON-NLS-1$
586 s += "NULL PARAMETERS"; //$NON-NLS-1$
588 s += ") "; //$NON-NLS-1$
590 if (thrownExceptions != null) {
591 if (thrownExceptions != NoExceptions) {
592 s += "throws "; //$NON-NLS-1$
593 for (int i = 0, length = thrownExceptions.length; i < length; i++) {
595 s += ", "; //$NON-NLS-1$
596 s += (thrownExceptions[i] != null) ? thrownExceptions[i]
597 .debugName() : "NULL TYPE"; //$NON-NLS-1$
601 s += "NULL THROWN EXCEPTIONS"; //$NON-NLS-1$