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.

EclipseResolvedMember.java 18KB

14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. /* *******************************************************************
  2. * Copyright (c) 2006 Contributors
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v 2.0
  6. * which accompanies this distribution and is available at
  7. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  8. *
  9. * Contributors:
  10. * Andy Clement initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.ajdt.internal.compiler.lookup;
  13. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
  14. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
  15. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
  16. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
  17. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
  18. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
  19. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
  20. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.IntLiteral;
  21. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
  22. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
  23. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
  24. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
  25. import org.aspectj.org.eclipse.jdt.internal.compiler.impl.IntConstant;
  26. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
  27. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
  28. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
  29. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
  30. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
  31. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
  32. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  33. import org.aspectj.weaver.AnnotationAJ;
  34. import org.aspectj.weaver.BCException;
  35. import org.aspectj.weaver.Member;
  36. import org.aspectj.weaver.MemberKind;
  37. import org.aspectj.weaver.ReferenceType;
  38. import org.aspectj.weaver.ResolvedMember;
  39. import org.aspectj.weaver.ResolvedMemberImpl;
  40. import org.aspectj.weaver.ResolvedType;
  41. import org.aspectj.weaver.UnresolvedType;
  42. import org.aspectj.weaver.World;
  43. import org.aspectj.weaver.bcel.BcelObjectType;
  44. /**
  45. * In the pipeline world, we can be weaving before all types have come through from compilation. In some cases this means the weaver
  46. * will want to ask questions of eclipse types and this subtype of ResolvedMemberImpl is here to answer some of those questions - it
  47. * is backed by the real eclipse MethodBinding object and can translate from Eclipse → Weaver information.
  48. */
  49. public class EclipseResolvedMember extends ResolvedMemberImpl {
  50. private static String[] NO_ARGS = new String[] {};
  51. private Binding realBinding;
  52. private String[] argumentNames;
  53. private World w;
  54. private ResolvedType[] cachedAnnotationTypes;
  55. private ResolvedType[][] cachedParameterAnnotationTypes;
  56. private EclipseFactory eclipseFactory;
  57. public EclipseResolvedMember(MethodBinding binding, MemberKind memberKind, ResolvedType realDeclaringType, int modifiers,
  58. UnresolvedType rettype, String name, UnresolvedType[] paramtypes, UnresolvedType[] extypes,
  59. EclipseFactory eclipseFactory) {
  60. super(memberKind, realDeclaringType, modifiers, rettype, name, paramtypes, extypes);
  61. this.realBinding = binding;
  62. this.eclipseFactory = eclipseFactory;
  63. this.w = realDeclaringType.getWorld();
  64. }
  65. public EclipseResolvedMember(FieldBinding binding, MemberKind field, ResolvedType realDeclaringType, int modifiers,
  66. ResolvedType type, String string, UnresolvedType[] none) {
  67. super(field, realDeclaringType, modifiers, type, string, none);
  68. this.realBinding = binding;
  69. this.w = realDeclaringType.getWorld();
  70. }
  71. public boolean hasAnnotation(UnresolvedType ofType) {
  72. ResolvedType[] annotationTypes = getAnnotationTypes();
  73. if (annotationTypes == null) {
  74. return false;
  75. }
  76. for (ResolvedType type : annotationTypes) {
  77. if (type.equals(ofType)) {
  78. return true;
  79. }
  80. }
  81. return false;
  82. }
  83. public AnnotationAJ[] getAnnotations() {
  84. if (isTypeDeclarationAvailable()) {
  85. // long abits =
  86. realBinding.getAnnotationTagBits(); // ensure resolved
  87. Annotation[] annos = getEclipseAnnotations();
  88. if (annos == null) {
  89. return null;
  90. }
  91. AnnotationAJ[] annoAJs = new AnnotationAJ[annos.length];
  92. for (int i = 0; i < annos.length; i++) {
  93. annoAJs[i] = EclipseAnnotationConvertor.convertEclipseAnnotation(annos[i], w, eclipseFactory);
  94. }
  95. return annoAJs;
  96. } else {
  97. UnresolvedType declaringType = this.getDeclaringType();
  98. if (declaringType instanceof ReferenceType) {
  99. ReferenceType referenceDeclaringType = (ReferenceType) declaringType;
  100. if (referenceDeclaringType.getDelegate() instanceof BcelObjectType) {
  101. // worth a look!
  102. ResolvedMember field = ((ResolvedType) declaringType).lookupField(this);
  103. if (field != null) {
  104. return field.getAnnotations();
  105. }
  106. }
  107. }
  108. return null;
  109. }
  110. }
  111. public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) {
  112. if (isTypeDeclarationAvailable()) {
  113. // long abits =
  114. realBinding.getAnnotationTagBits(); // ensure resolved
  115. Annotation[] annos = getEclipseAnnotations();
  116. if (annos == null) {
  117. return null;
  118. }
  119. for (Annotation anno : annos) {
  120. UnresolvedType ut = UnresolvedType.forSignature(new String(anno.resolvedType.signature()));
  121. if (w.resolve(ut).equals(ofType)) {
  122. // Found the one
  123. return EclipseAnnotationConvertor.convertEclipseAnnotation(anno, w, eclipseFactory);
  124. }
  125. }
  126. } else {
  127. UnresolvedType declaringType = this.getDeclaringType();
  128. if (declaringType instanceof ReferenceType) {
  129. ReferenceType referenceDeclaringType = (ReferenceType) declaringType;
  130. if (referenceDeclaringType.getDelegate() instanceof BcelObjectType) {
  131. // worth a look!
  132. ResolvedMember field = ((ResolvedType) declaringType).lookupField(this);
  133. if (field != null) {
  134. return field.getAnnotationOfType(ofType);
  135. }
  136. }
  137. }
  138. }
  139. return null;
  140. }
  141. public String getAnnotationDefaultValue() {
  142. // Andy, if you are debugging in here and your problem is some kind of incremental build failure where a match on
  143. // a member annotation value is failing then you should look at bug 307120. Under that bug you discovered that
  144. // for privileged field accesses from ITDs, an EclipseResolvedMember may be created (inside the privileged munger - see
  145. // PrivilegedHandler) and then later when the annotations are looked up on it, that fails because we can't find the
  146. // declaration for the member. This is because on the incremental build the member will likely represent something
  147. // inside a binary type (BinaryTypeBinding) - and when that happens we should not look on the type declaration but
  148. // instead on the delegate for the declaringClass because it will likely be a BcelObjectType with the right stuff
  149. // in it - see the other checks on BcelObjectType in this class.
  150. if (realBinding instanceof MethodBinding) {
  151. AbstractMethodDeclaration methodDecl = getTypeDeclaration().declarationOf((MethodBinding) realBinding);
  152. if (methodDecl instanceof AnnotationMethodDeclaration) {
  153. AnnotationMethodDeclaration annoMethodDecl = (AnnotationMethodDeclaration) methodDecl;
  154. Expression e = annoMethodDecl.defaultValue;
  155. if (e.resolvedType == null) {
  156. e.resolve(methodDecl.scope);
  157. }
  158. // TODO does not cope with many cases...
  159. if (e instanceof QualifiedNameReference) {
  160. QualifiedNameReference qnr = (QualifiedNameReference) e;
  161. if (qnr.binding instanceof FieldBinding) {
  162. FieldBinding fb = (FieldBinding) qnr.binding;
  163. StringBuilder sb = new StringBuilder();
  164. sb.append(fb.declaringClass.signature());
  165. sb.append(fb.name);
  166. return sb.toString();
  167. }
  168. } else if (e instanceof TrueLiteral) {
  169. return "true";
  170. } else if (e instanceof FalseLiteral) {
  171. return "false";
  172. } else if (e instanceof StringLiteral) {
  173. return new String(((StringLiteral) e).source());
  174. } else if (e instanceof IntLiteral) {
  175. return Integer.toString(((IntConstant) e.constant).intValue());
  176. } else {
  177. throw new BCException("EclipseResolvedMember.getAnnotationDefaultValue() not implemented for value of type '"
  178. + e.getClass() + "' - raise an AspectJ bug !");
  179. }
  180. }
  181. }
  182. return null;
  183. }
  184. public ResolvedType[] getAnnotationTypes() {
  185. if (cachedAnnotationTypes == null) {
  186. // long abits =
  187. realBinding.getAnnotationTagBits(); // ensure resolved
  188. if (isTypeDeclarationAvailable()) {
  189. Annotation[] annos = getEclipseAnnotations();
  190. if (annos == null) {
  191. cachedAnnotationTypes = ResolvedType.EMPTY_RESOLVED_TYPE_ARRAY;
  192. } else {
  193. cachedAnnotationTypes = new ResolvedType[annos.length];
  194. for (int i = 0; i < annos.length; i++) {
  195. Annotation type = annos[i];
  196. TypeBinding typebinding = type.resolvedType;
  197. // If there was a problem resolving the annotation (the import couldn't be found) then that can manifest
  198. // here as typebinding == null. Normally errors are reported prior to weaving (so weaving is avoided and
  199. // the null is not encountered) but the use of hasfield/hasmethod can cause early attempts to look at
  200. // annotations and if we NPE here then the real error will not get reported.
  201. if (typebinding == null) {
  202. // Give up now - expect proper error to be reported
  203. cachedAnnotationTypes = ResolvedType.EMPTY_RESOLVED_TYPE_ARRAY;
  204. return cachedAnnotationTypes;
  205. }
  206. cachedAnnotationTypes[i] = w.resolve(UnresolvedType.forSignature(new String(typebinding.signature())));
  207. }
  208. }
  209. } else {
  210. // annotations may be accessible through the declaringClass if there is a bcel object behind it...
  211. cachedAnnotationTypes = ResolvedType.EMPTY_RESOLVED_TYPE_ARRAY;
  212. UnresolvedType declaringType = this.getDeclaringType();
  213. if (declaringType instanceof ReferenceType) {
  214. ReferenceType referenceDeclaringType = (ReferenceType) declaringType;
  215. if (referenceDeclaringType.getDelegate() instanceof BcelObjectType) {
  216. // worth a look!
  217. if (this.getKind() == Member.METHOD) {
  218. ResolvedMember method = ((ResolvedType) declaringType).lookupMethod(this);
  219. if (method != null) {
  220. cachedAnnotationTypes = method.getAnnotationTypes();
  221. }
  222. } else {
  223. ResolvedMember field = ((ResolvedType) declaringType).lookupField(this);
  224. if (field != null) {
  225. cachedAnnotationTypes = field.getAnnotationTypes();
  226. }
  227. }
  228. }
  229. }
  230. }
  231. }
  232. return cachedAnnotationTypes;
  233. }
  234. private static final ResolvedType[][] NO_PARAM_ANNOS = new ResolvedType[0][];
  235. @Override
  236. public ResolvedType[][] getParameterAnnotationTypes() {
  237. if (cachedParameterAnnotationTypes == null) {
  238. realBinding.getAnnotationTagBits();
  239. Annotation[][] pannos = getEclipseParameterAnnotations();
  240. if (pannos == null) {
  241. cachedParameterAnnotationTypes = NO_PARAM_ANNOS;
  242. } else {
  243. cachedParameterAnnotationTypes = new ResolvedType[pannos.length][];
  244. for (int i = 0; i < pannos.length; i++) {
  245. cachedParameterAnnotationTypes[i] = new ResolvedType[pannos[i].length];
  246. for (int j = 0; j < pannos[i].length; j++) {
  247. TypeBinding typebinding = pannos[i][j].resolvedType;
  248. // If there was a problem resolving the annotation (the import couldn't be found) then that can manifest
  249. // here as typebinding == null. Normally errors are reported prior to weaving (so weaving is avoided and
  250. // the null is not encountered) but the use of hasfield/hasmethod can cause early attempts to look at
  251. // annotations and if we NPE here then the real error will not get reported.
  252. if (typebinding == null) {
  253. // Give up now - expect proper error to be reported
  254. cachedParameterAnnotationTypes = NO_PARAM_ANNOS;
  255. return cachedParameterAnnotationTypes;
  256. }
  257. cachedParameterAnnotationTypes[i][j] = w.resolve(UnresolvedType.forSignature(new String(typebinding
  258. .signature())));
  259. }
  260. }
  261. }
  262. }
  263. return cachedParameterAnnotationTypes;
  264. }
  265. public String[] getParameterNames() {
  266. if (argumentNames != null) {
  267. return argumentNames;
  268. }
  269. if (realBinding instanceof FieldBinding) {
  270. argumentNames = NO_ARGS;
  271. } else {
  272. TypeDeclaration typeDecl = getTypeDeclaration();
  273. AbstractMethodDeclaration methodDecl = (typeDecl == null ? null : typeDecl.declarationOf((MethodBinding) realBinding));
  274. Argument[] args = (methodDecl == null ? null : methodDecl.arguments); // dont
  275. // like
  276. // this
  277. // -
  278. // why
  279. // isnt
  280. // the
  281. // method
  282. // found
  283. // sometimes? is it because other errors are
  284. // being reported?
  285. if (args == null) {
  286. argumentNames = NO_ARGS;
  287. } else {
  288. argumentNames = new String[args.length];
  289. for (int i = 0; i < argumentNames.length; i++) {
  290. argumentNames[i] = new String(methodDecl.arguments[i].name);
  291. }
  292. }
  293. }
  294. return argumentNames;
  295. }
  296. /**
  297. * Discover the (eclipse form) annotations on this resolved member. This is done by going to the type declaration, looking up
  298. * the member (field/method) then grabbing the annotations.
  299. *
  300. * @return an array of (eclipse form) annotations on this member
  301. */
  302. private Annotation[] getEclipseAnnotations() {
  303. TypeDeclaration tDecl = getTypeDeclaration();
  304. // two possible reasons for it being null:
  305. // 1. code is broken
  306. // 2. this resolvedmember is an EclipseResolvedMember created up front to represent a privileged'd accessed member
  307. if (tDecl != null) {
  308. if (realBinding instanceof MethodBinding) {
  309. MethodBinding methodBinding = (MethodBinding) realBinding;
  310. AbstractMethodDeclaration methodDecl = tDecl.declarationOf(methodBinding);
  311. if (methodDecl == null) {
  312. // pr284862
  313. // bindings may have been trashed by InterTypeMemberFinder.addInterTypeMethod() - and so we need to take
  314. // a better look. Really this EclipseResolvedMember is broken...
  315. // Grab the set of bindings with matching selector
  316. MethodBinding[] mb = ((MethodBinding) realBinding).declaringClass.getMethods(methodBinding.selector);
  317. if (mb != null) {
  318. for (MethodBinding candidate : mb) {
  319. if (candidate instanceof InterTypeMethodBinding) {
  320. if (InterTypeMemberFinder.matches(candidate, methodBinding)) {
  321. InterTypeMethodBinding intertypeMethodBinding = (InterTypeMethodBinding) candidate;
  322. Annotation[] annos = intertypeMethodBinding.sourceMethod.annotations;
  323. return annos;
  324. }
  325. }
  326. }
  327. }
  328. return null; // give up! kind of assuming here that the code has other problems (and they will be reported)
  329. }
  330. return methodDecl.annotations;
  331. } else if (realBinding instanceof FieldBinding) {
  332. FieldDeclaration fieldDecl = tDecl.declarationOf((FieldBinding) realBinding);
  333. return fieldDecl.annotations;
  334. }
  335. }
  336. return null;
  337. }
  338. private Annotation[][] getEclipseParameterAnnotations() {
  339. TypeDeclaration tDecl = getTypeDeclaration();
  340. // two possible reasons for it being null:
  341. // 1. code is broken
  342. // 2. this resolvedmember is an EclipseResolvedMember created up front to represent a privileged'd accessed member
  343. if (tDecl != null) {
  344. if (realBinding instanceof MethodBinding) {
  345. MethodBinding methodBinding = (MethodBinding) realBinding;
  346. AbstractMethodDeclaration methodDecl = tDecl.declarationOf(methodBinding);
  347. boolean foundsome = false;
  348. if (methodDecl != null) {
  349. Argument[] args = methodDecl.arguments;
  350. if (args != null) {
  351. int pcount = args.length;
  352. Annotation[][] pannos = new Annotation[pcount][];
  353. for (int i = 0; i < pcount; i++) {
  354. pannos[i] = args[i].annotations;
  355. if (pannos[i] == null) {
  356. pannos[i] = NO_ANNOTATIONS;
  357. } else {
  358. for (int j = 0; j < pannos[i].length; j++) {
  359. pannos[i][j].resolveType(methodDecl.scope);
  360. }
  361. }
  362. foundsome = foundsome || pannos[i].length != 0;
  363. }
  364. if (foundsome) {
  365. return pannos;
  366. }
  367. }
  368. }
  369. }
  370. }
  371. return null;
  372. }
  373. private final static Annotation[] NO_ANNOTATIONS = new Annotation[0];
  374. private boolean isTypeDeclarationAvailable() {
  375. return getTypeDeclaration() != null;
  376. }
  377. /**
  378. * @return the type declaration that contained this member, or NULL if it is not available (eg. this isn't currently related to
  379. * a SOURCE-FORM artifact, it is instead related to a BINARY-FORM artifact)
  380. */
  381. private TypeDeclaration getTypeDeclaration() {
  382. if (realBinding instanceof MethodBinding) {
  383. MethodBinding mb = (MethodBinding) realBinding;
  384. if (mb != null) {
  385. SourceTypeBinding stb = (SourceTypeBinding) mb.declaringClass;
  386. if (stb != null) {
  387. ClassScope cScope = stb.scope;
  388. if (cScope != null) {
  389. return cScope.referenceContext;
  390. }
  391. }
  392. }
  393. } else if (realBinding instanceof FieldBinding) {
  394. FieldBinding fb = (FieldBinding) realBinding;
  395. if (fb != null) {
  396. SourceTypeBinding stb = (SourceTypeBinding) fb.declaringClass;
  397. if (stb != null) {
  398. ClassScope cScope = stb.scope;
  399. if (cScope != null) {
  400. return cScope.referenceContext;
  401. }
  402. }
  403. }
  404. }
  405. return null;
  406. }
  407. /**
  408. * Return true if this is the default constructor. The default constructor is the one generated if there isn't one in the
  409. * source. Eclipse helpfully uses a bit to indicate the default constructor.
  410. *
  411. * @return true if this is the default constructor.
  412. */
  413. public boolean isDefaultConstructor() {
  414. if (!(realBinding instanceof MethodBinding)) {
  415. return false;
  416. }
  417. MethodBinding mb = (MethodBinding) realBinding;
  418. return mb.isConstructor() && ((mb.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0);
  419. }
  420. }