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

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. }