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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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.enclosingSourceType();
  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. SourceTypeBinding invocationType = scope.invocationType(); //enclosingSourceType();
  122. if (invocationType == declaringClass && invocationType == receiverType) return true;
  123. if (isProtected()) {
  124. // answer true if the invocationType is the declaringClass or they are in the same package
  125. // OR the invocationType is a subclass of the declaringClass
  126. // AND the receiverType is the invocationType or its subclass
  127. // OR the method is a static method accessed directly through a type
  128. // OR previous assertions are true for one of the enclosing type
  129. if (invocationType == declaringClass) return true;
  130. if (invocationType.fPackage == declaringClass.fPackage) return true;
  131. ReferenceBinding currentType = invocationType;
  132. int depth = 0;
  133. do {
  134. if (declaringClass.isSuperclassOf(currentType)) {
  135. if (invocationSite.isSuperAccess()){
  136. return true;
  137. }
  138. // receiverType can be an array binding in one case... see if you can change it
  139. if (receiverType instanceof ArrayBinding){
  140. return false;
  141. }
  142. if (isStatic()){
  143. return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
  144. }
  145. if (currentType == receiverType || currentType.isSuperclassOf((ReferenceBinding) receiverType)){
  146. if (depth > 0) invocationSite.setDepth(depth);
  147. return true;
  148. }
  149. }
  150. depth++;
  151. currentType = currentType.enclosingType();
  152. } while (currentType != null);
  153. return false;
  154. }
  155. if (isPrivate()) {
  156. // answer true if the receiverType is the declaringClass
  157. // AND the invocationType and the declaringClass have a common enclosingType
  158. if (receiverType != declaringClass) return false;
  159. if (invocationType != declaringClass) {
  160. ReferenceBinding outerInvocationType = invocationType;
  161. ReferenceBinding temp = outerInvocationType.enclosingType();
  162. while (temp != null) {
  163. outerInvocationType = temp;
  164. temp = temp.enclosingType();
  165. }
  166. ReferenceBinding outerDeclaringClass = declaringClass;
  167. temp = outerDeclaringClass.enclosingType();
  168. while (temp != null) {
  169. outerDeclaringClass = temp;
  170. temp = temp.enclosingType();
  171. }
  172. if (outerInvocationType != outerDeclaringClass) return false;
  173. }
  174. return true;
  175. }
  176. // isDefault()
  177. if (invocationType.fPackage != declaringClass.fPackage) return false;
  178. // receiverType can be an array binding in one case... see if you can change it
  179. if (receiverType instanceof ArrayBinding)
  180. return false;
  181. ReferenceBinding type = (ReferenceBinding) receiverType;
  182. PackageBinding declaringPackage = declaringClass.fPackage;
  183. do {
  184. if (declaringClass == type) return true;
  185. if (declaringPackage != type.fPackage) return false;
  186. } while ((type = type.superclass()) != null);
  187. return false;
  188. }
  189. /* Answer the receiver's constant pool name.
  190. *
  191. * <init> for constructors
  192. * <clinit> for clinit methods
  193. * or the source name of the method
  194. */
  195. public final char[] constantPoolName() {
  196. return selector;
  197. }
  198. public final int getAccessFlags() {
  199. return modifiers & AccJustFlag;
  200. }
  201. /* Answer true if the receiver is an abstract method
  202. */
  203. public final boolean isAbstract() {
  204. return (modifiers & AccAbstract) != 0;
  205. }
  206. /* Answer true if the receiver is a constructor
  207. */
  208. public final boolean isConstructor() {
  209. return selector == ConstructorDeclaration.ConstantPoolName;
  210. }
  211. protected boolean isConstructorRelated() {
  212. return isConstructor();
  213. }
  214. /* Answer true if the receiver has default visibility
  215. */
  216. public final boolean isDefault() {
  217. return !isPublic() && !isProtected() && !isPrivate();
  218. }
  219. /* Answer true if the receiver is a system generated default abstract method
  220. */
  221. public final boolean isDefaultAbstract() {
  222. return (modifiers & AccDefaultAbstract) != 0;
  223. }
  224. /* Answer true if the receiver is a deprecated method
  225. */
  226. public final boolean isDeprecated() {
  227. return (modifiers & AccDeprecated) != 0;
  228. }
  229. /* Answer true if the receiver is final and cannot be overridden
  230. */
  231. public final boolean isFinal() {
  232. return (modifiers & AccFinal) != 0;
  233. }
  234. /* Answer true if the receiver is a native method
  235. */
  236. public final boolean isNative() {
  237. return (modifiers & AccNative) != 0;
  238. }
  239. /* Answer true if the receiver has private visibility
  240. */
  241. public final boolean isPrivate() {
  242. return (modifiers & AccPrivate) != 0;
  243. }
  244. /* Answer true if the receiver has protected visibility
  245. */
  246. public final boolean isProtected() {
  247. return (modifiers & AccProtected) != 0;
  248. }
  249. /* Answer true if the receiver has public visibility
  250. */
  251. public final boolean isPublic() {
  252. return (modifiers & AccPublic) != 0;
  253. }
  254. /* Answer true if the receiver got requested to clear the private modifier
  255. * during private access emulation.
  256. */
  257. public final boolean isRequiredToClearPrivateModifier() {
  258. return (modifiers & AccClearPrivateModifier) != 0;
  259. }
  260. /* Answer true if the receiver is a static method
  261. */
  262. public final boolean isStatic() {
  263. return (modifiers & AccStatic) != 0;
  264. }
  265. /* Answer true if all float operations must adher to IEEE 754 float/double rules
  266. */
  267. public final boolean isStrictfp() {
  268. return (modifiers & AccStrictfp) != 0;
  269. }
  270. /* Answer true if the receiver is a synchronized method
  271. */
  272. public final boolean isSynchronized() {
  273. return (modifiers & AccSynchronized) != 0;
  274. }
  275. /* Answer true if the receiver has public visibility
  276. */
  277. public final boolean isSynthetic() {
  278. return (modifiers & AccSynthetic) != 0;
  279. }
  280. /* Answer true if the receiver's declaring type is deprecated (or any of its enclosing types)
  281. */
  282. public final boolean isViewedAsDeprecated() {
  283. return (modifiers & AccDeprecated) != 0 ||
  284. (modifiers & AccDeprecatedImplicitly) != 0;
  285. }
  286. public char[] readableName() /* foo(int, Thread) */ {
  287. StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
  288. if (isConstructor())
  289. buffer.append(declaringClass.sourceName());
  290. else
  291. buffer.append(selector);
  292. buffer.append('(');
  293. if (parameters != NoParameters) {
  294. for (int i = 0, length = parameters.length; i < length; i++) {
  295. if (i > 0)
  296. buffer.append(", "); //$NON-NLS-1$
  297. buffer.append(parameters[i].sourceName());
  298. }
  299. }
  300. buffer.append(')');
  301. return buffer.toString().toCharArray();
  302. }
  303. protected final void selector(char[] selector) {
  304. this.selector = selector;
  305. this.signature = null;
  306. }
  307. /* Answer the receiver's signature.
  308. *
  309. * NOTE: This method should only be used during/after code gen.
  310. * The signature is cached so if the signature of the return type or any parameter
  311. * type changes, the cached state is invalid.
  312. */
  313. public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
  314. if (signature != null)
  315. return signature;
  316. StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
  317. buffer.append('(');
  318. if (isConstructorRelated() && declaringClass.isNestedType()) {
  319. // take into account the synthetic argument type signatures as well
  320. ReferenceBinding[] syntheticArgumentTypes = declaringClass.syntheticEnclosingInstanceTypes();
  321. int count = syntheticArgumentTypes == null ? 0 : syntheticArgumentTypes.length;
  322. for (int i = 0; i < count; i++)
  323. buffer.append(syntheticArgumentTypes[i].signature());
  324. SyntheticArgumentBinding[] syntheticArguments = declaringClass.syntheticOuterLocalVariables();
  325. count = syntheticArguments == null ? 0 : syntheticArguments.length;
  326. for (int i = 0; i < count; i++)
  327. buffer.append(syntheticArguments[i].type.signature());
  328. }
  329. if (parameters != NoParameters)
  330. for (int i = 0, length = parameters.length; i < length; i++)
  331. buffer.append(parameters[i].signature());
  332. buffer.append(')');
  333. buffer.append(returnType.signature());
  334. return signature = buffer.toString().toCharArray();
  335. }
  336. public final int sourceEnd() {
  337. AbstractMethodDeclaration method = sourceMethod();
  338. if (method == null)
  339. return 0;
  340. else
  341. return method.sourceEnd;
  342. }
  343. public AbstractMethodDeclaration sourceMethod() {
  344. SourceTypeBinding sourceType;
  345. try {
  346. sourceType = (SourceTypeBinding) declaringClass;
  347. } catch (ClassCastException e) {
  348. return null;
  349. }
  350. AbstractMethodDeclaration[] methods = sourceType.scope.referenceContext.methods;
  351. for (int i = methods.length; --i >= 0;)
  352. if (this == methods[i].binding)
  353. return methods[i];
  354. return null;
  355. }
  356. public final int sourceStart() {
  357. AbstractMethodDeclaration method = sourceMethod();
  358. if (method == null)
  359. return 0;
  360. else
  361. return method.sourceStart;
  362. }
  363. /**
  364. * Subtypes can override this to return true if an access method should be
  365. * used when referring to this method binding. Currently used
  366. * for AspectJ's inter-type method declarations.
  367. */
  368. public boolean alwaysNeedsAccessMethod() { return false; }
  369. /**
  370. * This will only be called if alwaysNeedsAccessMethod() returns true.
  371. * In that case it should return the access method to be used.
  372. */
  373. public MethodBinding getAccessMethod() {
  374. throw new RuntimeException("unimplemented");
  375. }
  376. /* During private access emulation, the binding can be requested to loose its
  377. * private visibility when the class file is dumped.
  378. */
  379. public final void tagForClearingPrivateModifier() {
  380. modifiers |= AccClearPrivateModifier;
  381. }
  382. public String toString() {
  383. String s = (returnType != null) ? returnType.debugName() : "NULL TYPE"; //$NON-NLS-1$
  384. s += " "; //$NON-NLS-1$
  385. s += (selector != null) ? new String(selector) : "UNNAMED METHOD"; //$NON-NLS-1$
  386. s += "("; //$NON-NLS-1$
  387. if (parameters != null) {
  388. if (parameters != NoParameters) {
  389. for (int i = 0, length = parameters.length; i < length; i++) {
  390. if (i > 0)
  391. s += ", "; //$NON-NLS-1$
  392. s += (parameters[i] != null) ? parameters[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
  393. }
  394. }
  395. } else {
  396. s += "NULL PARAMETERS"; //$NON-NLS-1$
  397. }
  398. s += ") "; //$NON-NLS-1$
  399. if (thrownExceptions != null) {
  400. if (thrownExceptions != NoExceptions) {
  401. s += "throws "; //$NON-NLS-1$
  402. for (int i = 0, length = thrownExceptions.length; i < length; i++) {
  403. if (i > 0)
  404. s += ", "; //$NON-NLS-1$
  405. s += (thrownExceptions[i] != null) ? thrownExceptions[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
  406. }
  407. }
  408. } else {
  409. s += "NULL THROWN EXCEPTIONS"; //$NON-NLS-1$
  410. }
  411. return s;
  412. }
  413. }