You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MethodBinding.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*******************************************************************************
  2. * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Common Public License v0.5
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/cpl-v05.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. * Palo Alto Research Center, Incorporated - AspectJ adaptation
  11. ******************************************************************************/
  12. package org.eclipse.jdt.internal.compiler.lookup;
  13. import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
  14. import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
  15. /**
  16. * AspectJ - hooks for subtypes
  17. */
  18. public class MethodBinding extends Binding implements BaseTypes, TypeConstants {
  19. public int modifiers;
  20. public char[] selector;
  21. public TypeBinding returnType;
  22. public TypeBinding[] parameters;
  23. public ReferenceBinding[] thrownExceptions;
  24. public ReferenceBinding declaringClass;
  25. char[] signature;
  26. protected MethodBinding() {
  27. }
  28. public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
  29. this.modifiers = modifiers;
  30. this.selector = selector;
  31. this.returnType = returnType;
  32. this.parameters = (args == null || args.length == 0) ? NoParameters : args;
  33. this.thrownExceptions = (exceptions == null || exceptions.length == 0) ? NoExceptions : exceptions;
  34. this.declaringClass = declaringClass;
  35. // propagate the strictfp & deprecated modifiers
  36. if (this.declaringClass != null) {
  37. if (this.declaringClass.isStrictfp())
  38. if (!(isNative() || isAbstract()))
  39. this.modifiers |= AccStrictfp;
  40. if (this.declaringClass.isViewedAsDeprecated() && !isDeprecated())
  41. this.modifiers |= AccDeprecatedImplicitly;
  42. }
  43. }
  44. public MethodBinding(int modifiers, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
  45. this(modifiers, ConstructorDeclaration.ConstantPoolName, VoidBinding, args, exceptions, declaringClass);
  46. }
  47. // special API used to change method declaring class for runtime visibility check
  48. public MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declaringClass) {
  49. this.modifiers = initialMethodBinding.modifiers;
  50. this.selector = initialMethodBinding.selector;
  51. this.returnType = initialMethodBinding.returnType;
  52. this.parameters = initialMethodBinding.parameters;
  53. this.thrownExceptions = initialMethodBinding.thrownExceptions;
  54. this.declaringClass = declaringClass;
  55. }
  56. /* Answer true if the argument types & the receiver's parameters are equal
  57. */
  58. public final boolean areParametersEqual(MethodBinding method) {
  59. TypeBinding[] args = method.parameters;
  60. if (parameters == args)
  61. return true;
  62. int length = parameters.length;
  63. if (length != args.length)
  64. return false;
  65. for (int i = 0; i < length; i++)
  66. if (parameters[i] != args[i])
  67. return false;
  68. return true;
  69. }
  70. /* API
  71. * Answer the receiver's binding type from Binding.BindingID.
  72. */
  73. public final int bindingType() {
  74. return METHOD;
  75. }
  76. /* Answer true if the receiver is visible to the type provided by the scope.
  77. * InvocationSite implements isSuperAccess() to provide additional information
  78. * if the receiver is protected.
  79. *
  80. * NOTE: This method should ONLY be sent if the receiver is a constructor.
  81. *
  82. * NOTE: Cannot invoke this method with a compilation unit scope.
  83. */
  84. public boolean canBeSeenBy(InvocationSite invocationSite, Scope scope) {
  85. if (isPublic()) return true;
  86. SourceTypeBinding invocationType = scope.invocationType();
  87. if (invocationType == declaringClass) return true;
  88. if (isProtected()) {
  89. // answer true if the receiver is in the same package as the invocationType
  90. if (invocationType.fPackage == declaringClass.fPackage) return true;
  91. return invocationSite.isSuperAccess();
  92. }
  93. if (isPrivate()) {
  94. // answer true if the invocationType and the declaringClass have a common enclosingType
  95. // already know they are not the identical type
  96. ReferenceBinding outerInvocationType = invocationType;
  97. ReferenceBinding temp = outerInvocationType.enclosingType();
  98. while (temp != null) {
  99. outerInvocationType = temp;
  100. temp = temp.enclosingType();
  101. }
  102. ReferenceBinding outerDeclaringClass = declaringClass;
  103. temp = outerDeclaringClass.enclosingType();
  104. while (temp != null) {
  105. outerDeclaringClass = temp;
  106. temp = temp.enclosingType();
  107. }
  108. return outerInvocationType == outerDeclaringClass;
  109. }
  110. // isDefault()
  111. return invocationType.fPackage == declaringClass.fPackage;
  112. }
  113. /* Answer true if the receiver is visible to the type provided by the scope.
  114. * InvocationSite implements isSuperAccess() to provide additional information
  115. * if the receiver is protected.
  116. *
  117. * NOTE: Cannot invoke this method with a compilation unit scope.
  118. */
  119. public boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) {
  120. if (isPublic()) return true;
  121. //XXX invocation vs. source
  122. SourceTypeBinding invocationType = scope.invocationType();
  123. if (invocationType == declaringClass && invocationType == receiverType) return true;
  124. if (isProtected()) {
  125. // answer true if the invocationType is the declaringClass or they are in the same package
  126. // OR the invocationType is a subclass of the declaringClass
  127. // AND the receiverType is the invocationType or its subclass
  128. // OR the method is a static method accessed directly through a type
  129. // OR previous assertions are true for one of the enclosing type
  130. if (invocationType == declaringClass) return true;
  131. if (invocationType.fPackage == declaringClass.fPackage) return true;
  132. // for protected we need to check based on the type of this
  133. ReferenceBinding currentType = scope.enclosingSourceType();;
  134. int depth = 0;
  135. do {
  136. if (declaringClass.isSuperclassOf(currentType)) {
  137. if (invocationSite.isSuperAccess()){
  138. return true;
  139. }
  140. // receiverType can be an array binding in one case... see if you can change it
  141. if (receiverType instanceof ArrayBinding){
  142. return false;
  143. }
  144. if (isStatic()){
  145. return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
  146. }
  147. if (currentType == receiverType || currentType.isSuperclassOf((ReferenceBinding) receiverType)){
  148. if (depth > 0) invocationSite.setDepth(depth);
  149. return true;
  150. }
  151. }
  152. depth++;
  153. currentType = currentType.enclosingType();
  154. } while (currentType != null);
  155. return false;
  156. }
  157. if (isPrivate()) {
  158. // answer true if the receiverType is the declaringClass
  159. // AND the invocationType and the declaringClass have a common enclosingType
  160. if (receiverType != declaringClass) return false;
  161. if (invocationType != declaringClass) {
  162. ReferenceBinding outerInvocationType = invocationType;
  163. ReferenceBinding temp = outerInvocationType.enclosingType();
  164. while (temp != null) {
  165. outerInvocationType = temp;
  166. temp = temp.enclosingType();
  167. }
  168. ReferenceBinding outerDeclaringClass = declaringClass;
  169. temp = outerDeclaringClass.enclosingType();
  170. while (temp != null) {
  171. outerDeclaringClass = temp;
  172. temp = temp.enclosingType();
  173. }
  174. if (outerInvocationType != outerDeclaringClass) return false;
  175. }
  176. return true;
  177. }
  178. // isDefault()
  179. if (invocationType.fPackage != declaringClass.fPackage) return false;
  180. // receiverType can be an array binding in one case... see if you can change it
  181. if (receiverType instanceof ArrayBinding)
  182. return false;
  183. ReferenceBinding type = (ReferenceBinding) receiverType;
  184. PackageBinding declaringPackage = declaringClass.fPackage;
  185. do {
  186. if (declaringClass == type) return true;
  187. if (declaringPackage != type.fPackage) return false;
  188. } while ((type = type.superclass()) != null);
  189. return false;
  190. }
  191. /* Answer the receiver's constant pool name.
  192. *
  193. * <init> for constructors
  194. * <clinit> for clinit methods
  195. * or the source name of the method
  196. */
  197. public final char[] constantPoolName() {
  198. return selector;
  199. }
  200. public final int getAccessFlags() {
  201. return modifiers & AccJustFlag;
  202. }
  203. /* Answer true if the receiver is an abstract method
  204. */
  205. public final boolean isAbstract() {
  206. return (modifiers & AccAbstract) != 0;
  207. }
  208. /* Answer true if the receiver is a constructor
  209. */
  210. public final boolean isConstructor() {
  211. return selector == ConstructorDeclaration.ConstantPoolName;
  212. }
  213. protected boolean isConstructorRelated() {
  214. return isConstructor();
  215. }
  216. /* Answer true if the receiver has default visibility
  217. */
  218. public final boolean isDefault() {
  219. return !isPublic() && !isProtected() && !isPrivate();
  220. }
  221. /* Answer true if the receiver is a system generated default abstract method
  222. */
  223. public final boolean isDefaultAbstract() {
  224. return (modifiers & AccDefaultAbstract) != 0;
  225. }
  226. /* Answer true if the receiver is a deprecated method
  227. */
  228. public final boolean isDeprecated() {
  229. return (modifiers & AccDeprecated) != 0;
  230. }
  231. /* Answer true if the receiver is final and cannot be overridden
  232. */
  233. public final boolean isFinal() {
  234. return (modifiers & AccFinal) != 0;
  235. }
  236. /* Answer true if the receiver is a native method
  237. */
  238. public final boolean isNative() {
  239. return (modifiers & AccNative) != 0;
  240. }
  241. /* Answer true if the receiver has private visibility
  242. */
  243. public final boolean isPrivate() {
  244. return (modifiers & AccPrivate) != 0;
  245. }
  246. /* Answer true if the receiver has protected visibility
  247. */
  248. public final boolean isProtected() {
  249. return (modifiers & AccProtected) != 0;
  250. }
  251. /* Answer true if the receiver has public visibility
  252. */
  253. public final boolean isPublic() {
  254. return (modifiers & AccPublic) != 0;
  255. }
  256. /* Answer true if the receiver got requested to clear the private modifier
  257. * during private access emulation.
  258. */
  259. public final boolean isRequiredToClearPrivateModifier() {
  260. return (modifiers & AccClearPrivateModifier) != 0;
  261. }
  262. /* Answer true if the receiver is a static method
  263. */
  264. public final boolean isStatic() {
  265. return (modifiers & AccStatic) != 0;
  266. }
  267. /* Answer true if all float operations must adher to IEEE 754 float/double rules
  268. */
  269. public final boolean isStrictfp() {
  270. return (modifiers & AccStrictfp) != 0;
  271. }
  272. /* Answer true if the receiver is a synchronized method
  273. */
  274. public final boolean isSynchronized() {
  275. return (modifiers & AccSynchronized) != 0;
  276. }
  277. /* Answer true if the receiver has public visibility
  278. */
  279. public final boolean isSynthetic() {
  280. return (modifiers & AccSynthetic) != 0;
  281. }
  282. /* Answer true if the receiver's declaring type is deprecated (or any of its enclosing types)
  283. */
  284. public final boolean isViewedAsDeprecated() {
  285. return (modifiers & AccDeprecated) != 0 ||
  286. (modifiers & AccDeprecatedImplicitly) != 0;
  287. }
  288. public char[] readableName() /* foo(int, Thread) */ {
  289. StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
  290. if (isConstructor())
  291. buffer.append(declaringClass.sourceName());
  292. else
  293. buffer.append(selector);
  294. buffer.append('(');
  295. if (parameters != NoParameters) {
  296. for (int i = 0, length = parameters.length; i < length; i++) {
  297. if (i > 0)
  298. buffer.append(", "); //$NON-NLS-1$
  299. buffer.append(parameters[i].sourceName());
  300. }
  301. }
  302. buffer.append(')');
  303. return buffer.toString().toCharArray();
  304. }
  305. protected final void selector(char[] selector) {
  306. this.selector = selector;
  307. this.signature = null;
  308. }
  309. /* Answer the receiver's signature.
  310. *
  311. * NOTE: This method should only be used during/after code gen.
  312. * The signature is cached so if the signature of the return type or any parameter
  313. * type changes, the cached state is invalid.
  314. */
  315. public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
  316. if (signature != null)
  317. return signature;
  318. StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
  319. buffer.append('(');
  320. if (isConstructorRelated() && declaringClass.isNestedType()) {
  321. // take into account the synthetic argument type signatures as well
  322. ReferenceBinding[] syntheticArgumentTypes = declaringClass.syntheticEnclosingInstanceTypes();
  323. int count = syntheticArgumentTypes == null ? 0 : syntheticArgumentTypes.length;
  324. for (int i = 0; i < count; i++)
  325. buffer.append(syntheticArgumentTypes[i].signature());
  326. SyntheticArgumentBinding[] syntheticArguments = declaringClass.syntheticOuterLocalVariables();
  327. count = syntheticArguments == null ? 0 : syntheticArguments.length;
  328. for (int i = 0; i < count; i++)
  329. buffer.append(syntheticArguments[i].type.signature());
  330. }
  331. if (parameters != NoParameters)
  332. for (int i = 0, length = parameters.length; i < length; i++)
  333. buffer.append(parameters[i].signature());
  334. buffer.append(')');
  335. buffer.append(returnType.signature());
  336. return signature = buffer.toString().toCharArray();
  337. }
  338. public final int sourceEnd() {
  339. AbstractMethodDeclaration method = sourceMethod();
  340. if (method == null)
  341. return 0;
  342. else
  343. return method.sourceEnd;
  344. }
  345. public AbstractMethodDeclaration sourceMethod() {
  346. SourceTypeBinding sourceType;
  347. try {
  348. sourceType = (SourceTypeBinding) declaringClass;
  349. } catch (ClassCastException e) {
  350. return null;
  351. }
  352. AbstractMethodDeclaration[] methods = sourceType.scope.referenceContext.methods;
  353. for (int i = methods.length; --i >= 0;)
  354. if (this == methods[i].binding)
  355. return methods[i];
  356. return null;
  357. }
  358. public final int sourceStart() {
  359. AbstractMethodDeclaration method = sourceMethod();
  360. if (method == null)
  361. return 0;
  362. else
  363. return method.sourceStart;
  364. }
  365. /**
  366. * Subtypes can override this to return true if an access method should be
  367. * used when referring to this method binding. Currently used
  368. * for AspectJ's inter-type method declarations.
  369. */
  370. public boolean alwaysNeedsAccessMethod() { return false; }
  371. /**
  372. * This will only be called if alwaysNeedsAccessMethod() returns true.
  373. * In that case it should return the access method to be used.
  374. */
  375. public MethodBinding getAccessMethod() {
  376. throw new RuntimeException("unimplemented");
  377. }
  378. /* During private access emulation, the binding can be requested to loose its
  379. * private visibility when the class file is dumped.
  380. */
  381. public final void tagForClearingPrivateModifier() {
  382. modifiers |= AccClearPrivateModifier;
  383. }
  384. public String toString() {
  385. String s = (returnType != null) ? returnType.debugName() : "NULL TYPE"; //$NON-NLS-1$
  386. s += " "; //$NON-NLS-1$
  387. s += (selector != null) ? new String(selector) : "UNNAMED METHOD"; //$NON-NLS-1$
  388. s += "("; //$NON-NLS-1$
  389. if (parameters != null) {
  390. if (parameters != NoParameters) {
  391. for (int i = 0, length = parameters.length; i < length; i++) {
  392. if (i > 0)
  393. s += ", "; //$NON-NLS-1$
  394. s += (parameters[i] != null) ? parameters[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
  395. }
  396. }
  397. } else {
  398. s += "NULL PARAMETERS"; //$NON-NLS-1$
  399. }
  400. s += ") "; //$NON-NLS-1$
  401. if (thrownExceptions != null) {
  402. if (thrownExceptions != NoExceptions) {
  403. s += "throws "; //$NON-NLS-1$
  404. for (int i = 0, length = thrownExceptions.length; i < length; i++) {
  405. if (i > 0)
  406. s += ", "; //$NON-NLS-1$
  407. s += (thrownExceptions[i] != null) ? thrownExceptions[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
  408. }
  409. }
  410. } else {
  411. s += "NULL THROWN EXCEPTIONS"; //$NON-NLS-1$
  412. }
  413. return s;
  414. }
  415. }