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.

ResolvedMemberImpl.java 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver;
  13. import java.io.DataOutputStream;
  14. import java.io.IOException;
  15. import java.lang.reflect.Modifier;
  16. import java.util.ArrayList;
  17. import java.util.Collection;
  18. import java.util.HashMap;
  19. import java.util.HashSet;
  20. import java.util.Iterator;
  21. import java.util.List;
  22. import java.util.Map;
  23. import java.util.Set;
  24. import org.aspectj.bridge.ISourceLocation;
  25. /**
  26. * This is the declared member, i.e. it will always correspond to an
  27. * actual method/... declaration
  28. */
  29. public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, AnnotatedElement, TypeVariableDeclaringElement, ResolvedMember {
  30. public String[] parameterNames = null;
  31. protected UnresolvedType[] checkedExceptions = UnresolvedType.NONE;
  32. /**
  33. * if this member is a parameterized version of a member in a generic type,
  34. * then this field holds a reference to the member we parameterize.
  35. */
  36. protected ResolvedMember backingGenericMember = null;
  37. protected Set annotationTypes = null;
  38. // Some members are 'created' to represent other things (for example ITDs). These
  39. // members have their annotations stored elsewhere, and this flag indicates that is
  40. // the case. It is up to the caller to work out where that is!
  41. // Once determined the caller may choose to stash the annotations in this member...
  42. private boolean isAnnotatedElsewhere = false; // this field is not serialized.
  43. private boolean isAjSynthetic = true;
  44. // generic methods have type variables
  45. private TypeVariable[] typeVariables;
  46. // these three fields hold the source location of this member
  47. protected int start, end;
  48. protected ISourceContext sourceContext = null;
  49. //XXX deprecate this in favor of the constructor below
  50. public ResolvedMemberImpl(
  51. Kind kind,
  52. UnresolvedType declaringType,
  53. int modifiers,
  54. UnresolvedType returnType,
  55. String name,
  56. UnresolvedType[] parameterTypes)
  57. {
  58. super(kind, declaringType, modifiers, returnType, name, parameterTypes);
  59. }
  60. public ResolvedMemberImpl(
  61. Kind kind,
  62. UnresolvedType declaringType,
  63. int modifiers,
  64. UnresolvedType returnType,
  65. String name,
  66. UnresolvedType[] parameterTypes,
  67. UnresolvedType[] checkedExceptions)
  68. {
  69. super(kind, declaringType, modifiers, returnType, name, parameterTypes);
  70. this.checkedExceptions = checkedExceptions;
  71. }
  72. public ResolvedMemberImpl(
  73. Kind kind,
  74. UnresolvedType declaringType,
  75. int modifiers,
  76. UnresolvedType returnType,
  77. String name,
  78. UnresolvedType[] parameterTypes,
  79. UnresolvedType[] checkedExceptions,
  80. ResolvedMember backingGenericMember)
  81. {
  82. this(kind, declaringType, modifiers, returnType, name, parameterTypes,checkedExceptions);
  83. this.backingGenericMember = backingGenericMember;
  84. this.isAjSynthetic = backingGenericMember.isAjSynthetic();
  85. }
  86. public ResolvedMemberImpl(
  87. Kind kind,
  88. UnresolvedType declaringType,
  89. int modifiers,
  90. String name,
  91. String signature)
  92. {
  93. super(kind, declaringType, modifiers, name, signature);
  94. }
  95. /**
  96. * Compute the full set of signatures for a member. This walks up the hierarchy
  97. * giving the ResolvedMember in each defining type in the hierarchy. A shadowMember
  98. * can be created with a target type (declaring type) that does not actually define
  99. * the member. This is ok as long as the member is inherited in the declaring type.
  100. * Each declaring type in the line to the actual declaring type is added as an additional
  101. * signature. For example:
  102. *
  103. * class A { void foo(); }
  104. * class B extends A {}
  105. *
  106. * shadowMember : void B.foo()
  107. *
  108. * gives { void B.foo(), void A.foo() }
  109. * @param joinPointSignature
  110. * @param inAWorld
  111. */
  112. public static JoinPointSignature[] getJoinPointSignatures(Member joinPointSignature, World inAWorld) {
  113. // Walk up hierarchy creating one member for each type up to and including the
  114. // first defining type
  115. ResolvedType originalDeclaringType = joinPointSignature.getDeclaringType().resolve(inAWorld);
  116. ResolvedMemberImpl firstDefiningMember = (ResolvedMemberImpl) joinPointSignature.resolve(inAWorld);
  117. if (firstDefiningMember == null) {
  118. return new JoinPointSignature[0];
  119. }
  120. // declaringType can be unresolved if we matched a synthetic member generated by Aj...
  121. // should be fixed elsewhere but add this resolve call on the end for now so that we can
  122. // focus on one problem at a time...
  123. ResolvedType firstDefiningType = firstDefiningMember.getDeclaringType().resolve(inAWorld);
  124. if (firstDefiningType != originalDeclaringType) {
  125. if (joinPointSignature.getKind() == Member.CONSTRUCTOR) {
  126. return new JoinPointSignature[0];
  127. }
  128. // else if (shadowMember.isStatic()) {
  129. // return new ResolvedMember[] {firstDefiningMember};
  130. // }
  131. }
  132. List declaringTypes = new ArrayList();
  133. accumulateTypesInBetween(originalDeclaringType,
  134. firstDefiningType,
  135. declaringTypes);
  136. Set memberSignatures = new HashSet();
  137. for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
  138. ResolvedType declaringType = (ResolvedType) iter.next();
  139. ResolvedMember member = firstDefiningMember.withSubstituteDeclaringType(declaringType);
  140. memberSignatures.add(member);
  141. }
  142. if (shouldWalkUpHierarchyFor(firstDefiningMember)) {
  143. // now walk up the hierarchy from the firstDefiningMember and include the signature for
  144. // every type between the firstDefiningMember and the root defining member.
  145. Iterator superTypeIterator = firstDefiningType.getDirectSupertypes();
  146. List typesAlreadyVisited = new ArrayList();
  147. accumulateMembersMatching(firstDefiningMember,superTypeIterator,typesAlreadyVisited,memberSignatures);
  148. }
  149. JoinPointSignature[] ret = new JoinPointSignature[memberSignatures.size()];
  150. memberSignatures.toArray(ret);
  151. return ret;
  152. }
  153. private static boolean shouldWalkUpHierarchyFor(Member aMember) {
  154. if (aMember.getKind() == Member.CONSTRUCTOR) return false;
  155. if (aMember.getKind() == Member.FIELD) return false;
  156. if (aMember.isStatic()) return false;
  157. return true;
  158. }
  159. /**
  160. * Build a list containing every type between subtype and supertype, inclusively.
  161. */
  162. private static void accumulateTypesInBetween(ResolvedType subType, ResolvedType superType, List types) {
  163. types.add(subType);
  164. if (subType == superType) {
  165. return;
  166. } else {
  167. for (Iterator iter = subType.getDirectSupertypes(); iter.hasNext();) {
  168. ResolvedType parent = (ResolvedType) iter.next();
  169. if (superType.isAssignableFrom(parent)) {
  170. accumulateTypesInBetween(parent, superType,types);
  171. }
  172. }
  173. }
  174. }
  175. /**
  176. * We have a resolved member, possibly with type parameter references as parameters or return
  177. * type. We need to find all its ancestor members. When doing this, a type parameter matches
  178. * regardless of bounds (bounds can be narrowed down the hierarchy).
  179. */
  180. private static void accumulateMembersMatching(
  181. ResolvedMemberImpl memberToMatch,
  182. Iterator typesToLookIn,
  183. List typesAlreadyVisited,
  184. Set foundMembers) {
  185. while(typesToLookIn.hasNext()) {
  186. ResolvedType toLookIn = (ResolvedType) typesToLookIn.next();
  187. if (!typesAlreadyVisited.contains(toLookIn)) {
  188. typesAlreadyVisited.add(toLookIn);
  189. ResolvedMemberImpl foundMember = (ResolvedMemberImpl) toLookIn.lookupResolvedMember(memberToMatch,true);
  190. if (foundMember != null && isVisibleTo(memberToMatch,foundMember)) {
  191. List declaringTypes = new ArrayList();
  192. // declaring type can be unresolved if the member can from an ITD...
  193. ResolvedType resolvedDeclaringType = foundMember.getDeclaringType().resolve(toLookIn.getWorld());
  194. accumulateTypesInBetween(toLookIn, resolvedDeclaringType, declaringTypes);
  195. for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
  196. ResolvedType declaringType = (ResolvedType) iter.next();
  197. // typesAlreadyVisited.add(declaringType);
  198. ResolvedMember member = foundMember.withSubstituteDeclaringType(declaringType);
  199. foundMembers.add(member);
  200. }
  201. if (toLookIn.isParameterizedType() && (foundMember.backingGenericMember != null)) {
  202. foundMembers.add(new JoinPointSignature(foundMember.backingGenericMember,foundMember.declaringType.resolve(toLookIn.getWorld())));
  203. }
  204. accumulateMembersMatching(foundMember,toLookIn.getDirectSupertypes(),typesAlreadyVisited,foundMembers);
  205. // if this was a parameterized type, look in the generic type that backs it too
  206. }
  207. }
  208. }
  209. }
  210. /**
  211. * Returns true if the parent member is visible to the child member
  212. * In the same declaring type this is always true, otherwise if parent is private
  213. * it is false.
  214. * @param childMember
  215. * @param parentMember
  216. * @return
  217. */
  218. private static boolean isVisibleTo(ResolvedMember childMember, ResolvedMember parentMember) {
  219. if (childMember.getDeclaringType().equals(parentMember.getDeclaringType())) return true;
  220. if (Modifier.isPrivate(parentMember.getModifiers())) {
  221. return false;
  222. } else {
  223. return true;
  224. }
  225. }
  226. // ----
  227. public final int getModifiers(World world) {
  228. return modifiers;
  229. }
  230. public final int getModifiers() {
  231. return modifiers;
  232. }
  233. // ----
  234. public final UnresolvedType[] getExceptions(World world) {
  235. return getExceptions();
  236. }
  237. public UnresolvedType[] getExceptions() {
  238. return checkedExceptions;
  239. }
  240. public ShadowMunger getAssociatedShadowMunger() {
  241. return null;
  242. }
  243. // ??? true or false?
  244. public boolean isAjSynthetic() {
  245. return isAjSynthetic;
  246. }
  247. public boolean hasAnnotations() {
  248. return (annotationTypes!=null);
  249. }
  250. public boolean hasAnnotation(UnresolvedType ofType) {
  251. // The ctors don't allow annotations to be specified ... yet - but
  252. // that doesn't mean it is an error to call this method.
  253. // Normally the weaver will be working with subtypes of
  254. // this type - BcelField/BcelMethod
  255. if (annotationTypes==null) return false;
  256. return annotationTypes.contains(ofType);
  257. }
  258. public ResolvedType[] getAnnotationTypes() {
  259. // The ctors don't allow annotations to be specified ... yet - but
  260. // that doesn't mean it is an error to call this method.
  261. // Normally the weaver will be working with subtypes of
  262. // this type - BcelField/BcelMethod
  263. if (annotationTypes == null) return null;
  264. return (ResolvedType[])annotationTypes.toArray(new ResolvedType[]{});
  265. }
  266. public AnnotationX[] getAnnotations() {
  267. if (backingGenericMember != null) return backingGenericMember.getAnnotations();
  268. return super.getAnnotations();
  269. }
  270. public void setAnnotationTypes(UnresolvedType[] annotationtypes) {
  271. if (annotationTypes == null) annotationTypes = new HashSet();
  272. for (int i = 0; i < annotationtypes.length; i++) {
  273. UnresolvedType typeX = annotationtypes[i];
  274. annotationTypes.add(typeX);
  275. }
  276. }
  277. public void addAnnotation(AnnotationX annotation) {
  278. // FIXME asc only allows for annotation types, not instances - should it?
  279. if (annotationTypes == null) annotationTypes = new HashSet();
  280. annotationTypes.add(annotation.getSignature());
  281. }
  282. public boolean isBridgeMethod() {
  283. return (modifiers & Constants.ACC_BRIDGE)!=0;
  284. }
  285. public boolean isVarargsMethod() {
  286. return (modifiers & Constants.ACC_VARARGS)!=0;
  287. }
  288. public void setVarargsMethod() {
  289. modifiers = modifiers | Constants.ACC_VARARGS;
  290. }
  291. public boolean isSynthetic() {
  292. return false;
  293. }
  294. public void write(DataOutputStream s) throws IOException {
  295. getKind().write(s);
  296. getDeclaringType().write(s);
  297. s.writeInt(modifiers);
  298. s.writeUTF(getName());
  299. s.writeUTF(getSignature());
  300. UnresolvedType.writeArray(getExceptions(), s);
  301. s.writeInt(getStart());
  302. s.writeInt(getEnd());
  303. s.writeBoolean(isVarargsMethod());
  304. // Write out any type variables...
  305. if (typeVariables==null) {
  306. s.writeInt(0);
  307. } else {
  308. s.writeInt(typeVariables.length);
  309. for (int i = 0; i < typeVariables.length; i++) {
  310. typeVariables[i].write(s);
  311. }
  312. }
  313. }
  314. public static void writeArray(ResolvedMember[] members, DataOutputStream s) throws IOException {
  315. s.writeInt(members.length);
  316. for (int i = 0, len = members.length; i < len; i++) {
  317. members[i].write(s);
  318. }
  319. }
  320. public static ResolvedMemberImpl readResolvedMember(VersionedDataInputStream s, ISourceContext sourceContext) throws IOException {
  321. ResolvedMemberImpl m = new ResolvedMemberImpl(Kind.read(s), UnresolvedType.read(s), s.readInt(),
  322. s.readUTF(), s.readUTF());
  323. m.checkedExceptions = UnresolvedType.readArray(s);
  324. m.start = s.readInt();
  325. m.end = s.readInt();
  326. m.sourceContext = sourceContext;
  327. if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
  328. if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150M4) {
  329. boolean isvarargs = s.readBoolean();
  330. if (isvarargs) m.setVarargsMethod();
  331. }
  332. int tvcount = s.readInt();
  333. if (tvcount!=0) {
  334. m.typeVariables = new TypeVariable[tvcount];
  335. for (int i=0;i<tvcount;i++) {
  336. m.typeVariables[i]=TypeVariable.read(s);
  337. m.typeVariables[i].setDeclaringElement(m);
  338. }
  339. }
  340. }
  341. return m;
  342. }
  343. public static ResolvedMember[] readResolvedMemberArray(VersionedDataInputStream s, ISourceContext context) throws IOException {
  344. int len = s.readInt();
  345. ResolvedMember[] members = new ResolvedMember[len];
  346. for (int i=0; i < len; i++) {
  347. members[i] = ResolvedMemberImpl.readResolvedMember(s, context);
  348. }
  349. return members;
  350. }
  351. public ResolvedMember resolve(World world) {
  352. // make sure all the pieces of a resolvedmember really are resolved
  353. try {
  354. if (typeVariables!=null && typeVariables.length>0) {
  355. for (int i = 0; i < typeVariables.length; i++) {
  356. typeVariables[i] = typeVariables[i].resolve(world);
  357. }
  358. }
  359. world.setTypeVariableLookupScope(this);
  360. if (annotationTypes!=null) {
  361. Set r = new HashSet();
  362. for (Iterator iter = annotationTypes.iterator(); iter.hasNext();) {
  363. UnresolvedType element = (UnresolvedType) iter.next();
  364. r.add(world.resolve(element));
  365. }
  366. annotationTypes = r;
  367. }
  368. declaringType = declaringType.resolve(world);
  369. if (declaringType.isRawType()) declaringType = ((ReferenceType)declaringType).getGenericType();
  370. if (parameterTypes!=null && parameterTypes.length>0) {
  371. for (int i = 0; i < parameterTypes.length; i++) {
  372. UnresolvedType array_element = parameterTypes[i];
  373. // parameterTypes[i] = parameterTypes[i].resolve(world);
  374. parameterTypes[i] = parameterTypes[i].resolve(world);
  375. }
  376. }
  377. returnType = returnType.resolve(world);
  378. } finally {
  379. world.setTypeVariableLookupScope(null);
  380. }
  381. return this;
  382. }
  383. public ISourceContext getSourceContext(World world) {
  384. return getDeclaringType().resolve(world).getSourceContext();
  385. }
  386. public final String[] getParameterNames() {
  387. return parameterNames;
  388. }
  389. public final String[] getParameterNames(World world) {
  390. return getParameterNames();
  391. }
  392. public AjAttribute.EffectiveSignatureAttribute getEffectiveSignature() {
  393. return null;
  394. }
  395. public ISourceLocation getSourceLocation() {
  396. //System.out.println("get context: " + this + " is " + sourceContext);
  397. if (sourceContext == null) {
  398. //System.err.println("no context: " + this);
  399. return null;
  400. }
  401. return sourceContext.makeSourceLocation(this);
  402. }
  403. public int getEnd() {
  404. return end;
  405. }
  406. public ISourceContext getSourceContext() {
  407. return sourceContext;
  408. }
  409. public int getStart() {
  410. return start;
  411. }
  412. public void setPosition(int sourceStart, int sourceEnd) {
  413. this.start = sourceStart;
  414. this.end = sourceEnd;
  415. }
  416. public void setSourceContext(ISourceContext sourceContext) {
  417. this.sourceContext = sourceContext;
  418. }
  419. public boolean isAbstract() {
  420. return Modifier.isAbstract(modifiers);
  421. }
  422. public boolean isPublic() {
  423. return Modifier.isPublic(modifiers);
  424. }
  425. public boolean isProtected() {
  426. return Modifier.isProtected(modifiers);
  427. }
  428. public boolean isNative() {
  429. return Modifier.isNative(modifiers);
  430. }
  431. public boolean isDefault() {
  432. return !(isPublic() || isProtected() || isPrivate());
  433. }
  434. public boolean isVisible(ResolvedType fromType) {
  435. World world = fromType.getWorld();
  436. return ResolvedType.isVisible(getModifiers(), getDeclaringType().resolve(world),
  437. fromType);
  438. }
  439. public void setCheckedExceptions(UnresolvedType[] checkedExceptions) {
  440. this.checkedExceptions = checkedExceptions;
  441. }
  442. public void setAnnotatedElsewhere(boolean b) {
  443. isAnnotatedElsewhere = b;
  444. }
  445. public boolean isAnnotatedElsewhere() {
  446. return isAnnotatedElsewhere;
  447. }
  448. /**
  449. * Get the UnresolvedType for the return type, taking generic signature into account
  450. */
  451. public UnresolvedType getGenericReturnType() {
  452. return getReturnType();
  453. }
  454. /**
  455. * Get the TypeXs of the parameter types, taking generic signature into account
  456. */
  457. public UnresolvedType[] getGenericParameterTypes() {
  458. return getParameterTypes();
  459. }
  460. // return a resolved member in which all type variables in the signature of this
  461. // member have been replaced with the given bindings.
  462. // the isParameterized flag tells us whether we are creating a raw type version or not
  463. // if isParameterized List<T> will turn into List<String> (for example),
  464. // but if !isParameterized List<T> will turn into List.
  465. public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters,ResolvedType newDeclaringType, boolean isParameterized) {
  466. if (!this.getDeclaringType().isGenericType()) {
  467. throw new IllegalStateException("Can't ask to parameterize a member of a non-generic type");
  468. }
  469. TypeVariable[] typeVariables = getDeclaringType().getTypeVariables();
  470. if (typeVariables.length != typeParameters.length) {
  471. throw new IllegalStateException("Wrong number of type parameters supplied");
  472. }
  473. Map typeMap = new HashMap();
  474. for (int i = 0; i < typeVariables.length; i++) {
  475. typeMap.put(typeVariables[i].getName(), typeParameters[i]);
  476. }
  477. UnresolvedType parameterizedReturnType = parameterize(getGenericReturnType(),typeMap,isParameterized);
  478. UnresolvedType[] parameterizedParameterTypes = new UnresolvedType[getGenericParameterTypes().length];
  479. for (int i = 0; i < parameterizedParameterTypes.length; i++) {
  480. parameterizedParameterTypes[i] =
  481. parameterize(getGenericParameterTypes()[i], typeMap,isParameterized);
  482. }
  483. ResolvedMemberImpl ret = new ResolvedMemberImpl(
  484. getKind(),
  485. newDeclaringType,
  486. getModifiers(),
  487. parameterizedReturnType,
  488. getName(),
  489. parameterizedParameterTypes,
  490. getExceptions(),
  491. this
  492. );
  493. ret.setSourceContext(getSourceContext());
  494. return ret;
  495. }
  496. public void setTypeVariables(TypeVariable[] tvars) {
  497. typeVariables = tvars;
  498. }
  499. public TypeVariable[] getTypeVariables() {
  500. return typeVariables;
  501. }
  502. private UnresolvedType parameterize(UnresolvedType aType, Map typeVariableMap, boolean inParameterizedType) {
  503. if (aType instanceof TypeVariableReferenceType) {
  504. String variableName = ((TypeVariableReferenceType)aType).getTypeVariable().getName();
  505. if (!typeVariableMap.containsKey(variableName)) {
  506. return aType; // if the type variable comes from the method (and not the type) thats OK
  507. }
  508. return (UnresolvedType) typeVariableMap.get(variableName);
  509. } else if (aType.isParameterizedType()) {
  510. if (inParameterizedType) {
  511. return aType.parameterize(typeVariableMap);
  512. } else {
  513. return aType.getRawType();
  514. }
  515. }
  516. return aType;
  517. }
  518. /**
  519. * If this member is defined by a parameterized super-type, return the erasure
  520. * of that member.
  521. * For example:
  522. * interface I<T> { T foo(T aTea); }
  523. * class C implements I<String> {
  524. * String foo(String aString) { return "something"; }
  525. * }
  526. * The resolved member for C.foo has signature String foo(String). The
  527. * erasure of that member is Object foo(Object) -- use upper bound of type
  528. * variable.
  529. * A type is a supertype of itself.
  530. */
  531. public ResolvedMember getErasure() {
  532. if (calculatedMyErasure) return myErasure;
  533. calculatedMyErasure = true;
  534. ResolvedType resolvedDeclaringType = (ResolvedType) getDeclaringType();
  535. // this next test is fast, and the result is cached.
  536. if (!resolvedDeclaringType.hasParameterizedSuperType()) {
  537. return null;
  538. } else {
  539. // we have one or more parameterized super types.
  540. // this member may be defined by one of them... we need to find out.
  541. Collection declaringTypes = this.getDeclaringTypes(resolvedDeclaringType.getWorld());
  542. for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
  543. ResolvedType aDeclaringType = (ResolvedType) iter.next();
  544. if (aDeclaringType.isParameterizedType()) {
  545. // we've found the (a?) parameterized type that defines this member.
  546. // now get the erasure of it
  547. ResolvedMemberImpl matchingMember = (ResolvedMemberImpl) aDeclaringType.lookupMemberNoSupers(this);
  548. if (matchingMember != null && matchingMember.backingGenericMember != null) {
  549. myErasure = matchingMember.backingGenericMember;
  550. return myErasure;
  551. }
  552. }
  553. }
  554. }
  555. return null;
  556. }
  557. private ResolvedMember myErasure = null;
  558. private boolean calculatedMyErasure = false;
  559. /**
  560. * For ITDs, we use the default factory methods to build a resolved member, then alter a couple of characteristics
  561. * using this method - this is safe.
  562. */
  563. public void resetName(String newName) {this.name = newName;}
  564. public void resetKind(Kind newKind) {this.kind=newKind; }
  565. public void resetModifiers(int newModifiers) {this.modifiers=newModifiers;}
  566. public void resetReturnTypeToObjectArray() {
  567. returnType = UnresolvedType.OBJECTARRAY;
  568. }
  569. /**
  570. * Returns a copy of this member but with the declaring type swapped.
  571. * Copy only needs to be shallow.
  572. * @param newDeclaringType
  573. */
  574. public JoinPointSignature withSubstituteDeclaringType(ResolvedType newDeclaringType) {
  575. JoinPointSignature ret = new JoinPointSignature(this,newDeclaringType);
  576. return ret;
  577. }
  578. /**
  579. * Returns true if this member matches the other. The matching takes into account
  580. * name and parameter types only. When comparing parameter types, we allow any type
  581. * variable to match any other type variable regardless of bounds.
  582. */
  583. public boolean matches(ResolvedMember aCandidateMatch) {
  584. ResolvedMemberImpl candidateMatchImpl = (ResolvedMemberImpl)aCandidateMatch;
  585. if (!getName().equals(aCandidateMatch.getName())) return false;
  586. UnresolvedType[] myParameterTypes = getGenericParameterTypes();
  587. UnresolvedType[] candidateParameterTypes = aCandidateMatch.getGenericParameterTypes();
  588. if (myParameterTypes.length != candidateParameterTypes.length) return false;
  589. String myParameterSignature = getParameterSigWithBoundsRemoved();
  590. String candidateParameterSignature = candidateMatchImpl.getParameterSigWithBoundsRemoved();
  591. if (myParameterSignature.equals(candidateParameterSignature)) {
  592. return true;
  593. } else {
  594. // try erasure
  595. myParameterSignature = getParameterSigErasure();
  596. candidateParameterSignature = candidateMatchImpl.getParameterSigErasure();
  597. return myParameterSignature.equals(candidateParameterSignature);
  598. }
  599. }
  600. /** converts e.g. <T extends Number>.... List<T> to just Ljava/util/List<T;>;
  601. * whereas the full signature would be Ljava/util/List<T:Ljava/lang/Number;>;
  602. */
  603. private String myParameterSignatureWithBoundsRemoved = null;
  604. /**
  605. * converts e.g. <T extends Number>.... List<T> to just Ljava/util/List;
  606. */
  607. private String myParameterSignatureErasure = null;
  608. // does NOT produce a meaningful java signature, but does give a unique string suitable for
  609. // comparison.
  610. private String getParameterSigWithBoundsRemoved() {
  611. if (myParameterSignatureWithBoundsRemoved != null) return myParameterSignatureWithBoundsRemoved;
  612. StringBuffer sig = new StringBuffer();
  613. UnresolvedType[] myParameterTypes = getGenericParameterTypes();
  614. for (int i = 0; i < myParameterTypes.length; i++) {
  615. appendSigWithTypeVarBoundsRemoved(myParameterTypes[i], sig);
  616. }
  617. myParameterSignatureWithBoundsRemoved = sig.toString();
  618. return myParameterSignatureWithBoundsRemoved;
  619. }
  620. private String getParameterSigErasure() {
  621. if (myParameterSignatureErasure != null) return myParameterSignatureErasure;
  622. StringBuffer sig = new StringBuffer();
  623. UnresolvedType[] myParameterTypes = getParameterTypes();
  624. for (int i = 0; i < myParameterTypes.length; i++) {
  625. UnresolvedType thisParameter = myParameterTypes[i];
  626. if (thisParameter.isTypeVariableReference()) {
  627. sig.append(thisParameter.getUpperBound().getSignature());
  628. } else {
  629. sig.append(thisParameter.getSignature());
  630. }
  631. }
  632. myParameterSignatureErasure = sig.toString();
  633. return myParameterSignatureErasure;
  634. }
  635. // does NOT produce a meaningful java signature, but does give a unique string suitable for
  636. // comparison.
  637. private void appendSigWithTypeVarBoundsRemoved(UnresolvedType aType, StringBuffer toBuffer) {
  638. if (aType.isTypeVariableReference()) {
  639. toBuffer.append("T;");
  640. } else if (aType.isParameterizedType()) {
  641. toBuffer.append(aType.getRawType().getSignature());
  642. toBuffer.append("<");
  643. for (int i = 0; i < aType.getTypeParameters().length; i++) {
  644. appendSigWithTypeVarBoundsRemoved(aType.getTypeParameters()[i], toBuffer);
  645. }
  646. toBuffer.append(">;");
  647. } else {
  648. toBuffer.append(aType.getSignature());
  649. }
  650. }
  651. public String toGenericString() {
  652. StringBuffer buf = new StringBuffer();
  653. buf.append(getGenericReturnType().getSimpleName());
  654. buf.append(' ');
  655. buf.append(declaringType.getName());
  656. buf.append('.');
  657. buf.append(name);
  658. if (kind != FIELD) {
  659. buf.append("(");
  660. UnresolvedType[] params = getGenericParameterTypes();
  661. if (params.length != 0) {
  662. buf.append(params[0].getSimpleName());
  663. for (int i=1, len = params.length; i < len; i++) {
  664. buf.append(", ");
  665. buf.append(params[i].getSimpleName());
  666. }
  667. }
  668. buf.append(")");
  669. }
  670. return buf.toString();
  671. }
  672. public TypeVariable getTypeVariableNamed(String name) {
  673. // Check locally...
  674. if (typeVariables!=null) {
  675. for (int i = 0; i < typeVariables.length; i++) {
  676. if (typeVariables[i].getName().equals(name)) return typeVariables[i];
  677. }
  678. }
  679. // Bugger, check the declaring type!
  680. return declaringType.getTypeVariableNamed(name);
  681. // Do generic aspects with ITDs that share type variables with the aspect and the target type and have their own tvars cause this to be messier?
  682. }
  683. }