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.

TypeVariable.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /* *******************************************************************
  2. * Copyright (c) 2005-2010 Contributors.
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://eclipse.org/legal/epl-v10.html
  8. * ******************************************************************/
  9. package org.aspectj.weaver;
  10. import java.io.IOException;
  11. /**
  12. * Represents a type variable with possible bounds.
  13. *
  14. * @author Adrian Colyer
  15. * @author Andy Clement
  16. */
  17. public class TypeVariable {
  18. public static final TypeVariable[] NONE = new TypeVariable[0];
  19. // the name of the type variable as recorded in the generic signature
  20. private String name;
  21. // index
  22. private int rank;
  23. // computed as required: either ==superclass or ==superInterfaces[0] or is OBJECT
  24. private UnresolvedType firstbound;
  25. // the upper bound of the type variable. From the extends clause, eg. T extends Number
  26. private UnresolvedType superclass;
  27. // any additional upper (interface) bounds. from the extends clause, e.g. T extends Number & Comparable
  28. private UnresolvedType[] superInterfaces = UnresolvedType.NONE;
  29. // It would be nice to push this field onto the TypeVariableDeclaringElement
  30. // interface (a getKind()) but at the moment we don't always guarantee
  31. // to set the declaring element (eclipse seems to utilise the knowledge of
  32. // what declared the type variable, but we dont yet...)
  33. public static final int UNKNOWN = -1;
  34. public static final int METHOD = 1;
  35. public static final int TYPE = 2;
  36. // What kind of element declared this type variable?
  37. private int declaringElementKind = UNKNOWN;
  38. private TypeVariableDeclaringElement declaringElement;
  39. // whether or not the bounds of this type variable have been resolved
  40. public boolean isResolved = false;
  41. // Is this type variable in the process of being resolved (allows for something self-referential like Enum)
  42. private boolean beingResolved = false;
  43. /**
  44. * Constructor for an unbound type variable, eg. 'T'
  45. */
  46. public TypeVariable(String name) {
  47. this.name = name;
  48. }
  49. public TypeVariable(String name, UnresolvedType anUpperBound) {
  50. this(name);
  51. this.superclass = anUpperBound;
  52. }
  53. public TypeVariable(String name, UnresolvedType anUpperBound, UnresolvedType[] superInterfaces) {
  54. this(name, anUpperBound);
  55. this.superInterfaces = superInterfaces;
  56. }
  57. /**
  58. * @return the first bound, either the superclass or if non is specified the first interface or if non are specified then OBJECT
  59. */
  60. public UnresolvedType getFirstBound() {
  61. if (firstbound != null) {
  62. return firstbound;
  63. }
  64. if (superclass == null || superclass.getSignature().equals("Ljava/lang/Object;")) {
  65. if (superInterfaces.length > 0) {
  66. firstbound = superInterfaces[0];
  67. } else {
  68. firstbound = UnresolvedType.OBJECT;
  69. }
  70. } else {
  71. firstbound = superclass;
  72. }
  73. return firstbound;
  74. }
  75. public UnresolvedType getUpperBound() {
  76. return superclass;
  77. }
  78. public UnresolvedType[] getSuperInterfaces() {
  79. return superInterfaces;
  80. }
  81. public String getName() {
  82. return name;
  83. }
  84. /**
  85. * resolve all the bounds of this type variable
  86. */
  87. public TypeVariable resolve(World world) {
  88. if (isResolved) {
  89. return this;
  90. }
  91. if (beingResolved) {
  92. return this;
  93. }
  94. beingResolved = true;
  95. TypeVariable resolvedTVar = null;
  96. if (declaringElement != null) {
  97. // resolve by finding the real type var that we refer to...
  98. if (declaringElementKind == TYPE) {
  99. UnresolvedType declaring = (UnresolvedType) declaringElement;
  100. ReferenceType rd = (ReferenceType) declaring.resolve(world);
  101. TypeVariable[] tVars = rd.getTypeVariables();
  102. for (TypeVariable tVar : tVars) {
  103. if (tVar.getName().equals(getName())) {
  104. resolvedTVar = tVar;
  105. break;
  106. }
  107. }
  108. } else {
  109. // look for type variable on method...
  110. ResolvedMember declaring = (ResolvedMember) declaringElement;
  111. TypeVariable[] tvrts = declaring.getTypeVariables();
  112. for (TypeVariable tvrt : tvrts) {
  113. if (tvrt.getName().equals(getName())) {
  114. resolvedTVar = tvrt;
  115. // if (tvrts[i].isTypeVariableReference()) {
  116. // TypeVariableReferenceType tvrt = (TypeVariableReferenceType) tvrts[i].resolve(inSomeWorld);
  117. // TypeVariable tv = tvrt.getTypeVariable();
  118. // if (tv.getName().equals(getName())) resolvedTVar = tv;
  119. // }
  120. }
  121. }
  122. }
  123. if (resolvedTVar == null) {
  124. throw new IllegalStateException();
  125. // well, this is bad... we didn't find the type variable on the member
  126. // could be a separate compilation issue...
  127. // should issue message, this is a workaround to get us going...
  128. // resolvedTVar = this;
  129. }
  130. } else {
  131. resolvedTVar = this;
  132. }
  133. superclass = resolvedTVar.superclass;
  134. superInterfaces = resolvedTVar.superInterfaces;
  135. if (superclass != null) {
  136. ResolvedType rt = superclass.resolve(world);
  137. // if (!superclass.isTypeVariableReference() && rt.isInterface()) {
  138. // throw new IllegalStateException("Why is the type an interface? " + rt);
  139. // }
  140. superclass = rt;
  141. }
  142. firstbound = getFirstBound().resolve(world);
  143. for (int i = 0; i < superInterfaces.length; i++) {
  144. superInterfaces[i] = superInterfaces[i].resolve(world);
  145. }
  146. isResolved = true;
  147. beingResolved = false;
  148. return this;
  149. }
  150. /**
  151. * answer true if the given type satisfies all of the bound constraints of this type variable. If type variable has not been
  152. * resolved then throws IllegalStateException
  153. */
  154. public boolean canBeBoundTo(ResolvedType candidate) {
  155. if (!isResolved) {
  156. throw new IllegalStateException("Can't answer binding questions prior to resolving");
  157. }
  158. // wildcard can accept any binding
  159. if (candidate.isGenericWildcard()) {
  160. return true;
  161. }
  162. // otherwise can be bound iff...
  163. // candidate is a subtype of upperBound
  164. if (superclass != null && !isASubtypeOf(superclass, candidate)) {
  165. return false;
  166. }
  167. // candidate is a subtype of all superInterfaces
  168. for (UnresolvedType superInterface : superInterfaces) {
  169. if (!isASubtypeOf(superInterface, candidate)) {
  170. return false;
  171. }
  172. }
  173. return true;
  174. }
  175. private boolean isASubtypeOf(UnresolvedType candidateSuperType, UnresolvedType candidateSubType) {
  176. ResolvedType superType = (ResolvedType) candidateSuperType;
  177. ResolvedType subType = (ResolvedType) candidateSubType;
  178. return superType.isAssignableFrom(subType);
  179. }
  180. // only used when resolving
  181. public void setUpperBound(UnresolvedType superclass) {
  182. // if (isResolved) {
  183. // throw new IllegalStateException("Why set this late?");
  184. // }
  185. this.firstbound = null;
  186. this.superclass = superclass;
  187. }
  188. // only used when resolving
  189. public void setAdditionalInterfaceBounds(UnresolvedType[] superInterfaces) {
  190. // if (isResolved) {
  191. // throw new IllegalStateException("Why set this late?");
  192. // }
  193. this.firstbound = null;
  194. this.superInterfaces = superInterfaces;
  195. }
  196. public String toDebugString() {
  197. return getDisplayName();
  198. }
  199. public String getDisplayName() {
  200. StringBuffer ret = new StringBuffer();
  201. ret.append(name);
  202. if (!getFirstBound().getName().equals("java.lang.Object")) {
  203. ret.append(" extends ");
  204. ret.append(getFirstBound().getName());
  205. if (superInterfaces != null) {
  206. for (UnresolvedType superInterface : superInterfaces) {
  207. if (!getFirstBound().equals(superInterface)) {
  208. ret.append(" & ");
  209. ret.append(superInterface.getName());
  210. }
  211. }
  212. }
  213. }
  214. return ret.toString();
  215. }
  216. @Override
  217. public String toString() {
  218. return "TypeVar " + getDisplayName();
  219. }
  220. /**
  221. * Return complete signature, e.g. "T extends Number" would return "T:Ljava/lang/Number;" note: MAY INCLUDE P types if bounds
  222. * are parameterized types
  223. */
  224. public String getSignature() {
  225. StringBuffer sb = new StringBuffer();
  226. sb.append(name);
  227. sb.append(":");
  228. if (superInterfaces.length == 0 || !superclass.getSignature().equals(UnresolvedType.OBJECT.getSignature())) {
  229. sb.append(superclass.getSignature());
  230. }
  231. if (superInterfaces.length != 0) {
  232. for (UnresolvedType superInterface : superInterfaces) {
  233. sb.append(":");
  234. UnresolvedType iBound = superInterface;
  235. sb.append(iBound.getSignature());
  236. }
  237. }
  238. return sb.toString();
  239. }
  240. /**
  241. * @return signature for inclusion in an attribute, there must be no 'P' in it signatures
  242. */
  243. public String getSignatureForAttribute() {
  244. StringBuffer sb = new StringBuffer();
  245. sb.append(name);
  246. sb.append(":");
  247. if (superInterfaces.length == 0 || !superclass.getSignature().equals(UnresolvedType.OBJECT.getSignature())) {
  248. sb.append(((ReferenceType)superclass).getSignatureForAttribute());
  249. }
  250. if (superInterfaces.length != 0) {
  251. for (UnresolvedType superInterface : superInterfaces) {
  252. sb.append(":");
  253. ResolvedType iBound = (ResolvedType) superInterface;
  254. sb.append(iBound.getSignatureForAttribute());
  255. }
  256. }
  257. return sb.toString();
  258. }
  259. public void setRank(int rank) {
  260. this.rank = rank;
  261. }
  262. public int getRank() {
  263. return rank;
  264. }
  265. public void setDeclaringElement(TypeVariableDeclaringElement element) {
  266. this.declaringElement = element;
  267. if (element instanceof UnresolvedType) {
  268. this.declaringElementKind = TYPE;
  269. } else {
  270. this.declaringElementKind = METHOD;
  271. }
  272. }
  273. public TypeVariableDeclaringElement getDeclaringElement() {
  274. return declaringElement;
  275. }
  276. public void setDeclaringElementKind(int kind) {
  277. this.declaringElementKind = kind;
  278. }
  279. public int getDeclaringElementKind() {
  280. // if (declaringElementKind==UNKNOWN) throw new RuntimeException("Dont know declarer of this tvar : "+this);
  281. return declaringElementKind;
  282. }
  283. public void write(CompressingDataOutputStream s) throws IOException {
  284. // name, upperbound, additionalInterfaceBounds, lowerbound
  285. s.writeUTF(name);
  286. superclass.write(s);
  287. if (superInterfaces.length == 0) {
  288. s.writeInt(0);
  289. } else {
  290. s.writeInt(superInterfaces.length);
  291. for (UnresolvedType ibound : superInterfaces) {
  292. ibound.write(s);
  293. }
  294. }
  295. }
  296. public static TypeVariable read(VersionedDataInputStream s) throws IOException {
  297. // if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
  298. String name = s.readUTF();
  299. UnresolvedType ubound = UnresolvedType.read(s);
  300. int iboundcount = s.readInt();
  301. UnresolvedType[] ibounds = UnresolvedType.NONE;
  302. if (iboundcount > 0) {
  303. ibounds = new UnresolvedType[iboundcount];
  304. for (int i = 0; i < iboundcount; i++) {
  305. ibounds[i] = UnresolvedType.read(s);
  306. }
  307. }
  308. TypeVariable newVariable = new TypeVariable(name, ubound, ibounds);
  309. return newVariable;
  310. }
  311. public String getGenericSignature() {
  312. return "T" + name + ";";
  313. }
  314. public String getErasureSignature() {
  315. return getFirstBound().getErasureSignature();
  316. }
  317. public UnresolvedType getSuperclass() {
  318. return superclass;
  319. }
  320. public void setSuperclass(UnresolvedType superclass) {
  321. this.firstbound = null;
  322. this.superclass = superclass;
  323. }
  324. }