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.

UnresolvedType.java 33KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. /* *******************************************************************
  2. * Copyright (c) 2002,2005 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://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * Andy Clement start of generics upgrade...
  12. * Adrian Colyer - overhaul
  13. * ******************************************************************/
  14. package org.aspectj.weaver;
  15. import java.io.DataInputStream;
  16. import java.io.DataOutputStream;
  17. import java.io.IOException;
  18. import java.util.Map;
  19. import org.aspectj.apache.bcel.classfile.GenericSignatureParser;
  20. import org.aspectj.apache.bcel.classfile.Signature;
  21. import org.aspectj.apache.bcel.classfile.Signature.ClassSignature;
  22. import org.aspectj.weaver.tools.Traceable;
  23. /**
  24. * A UnresolvedType represents a type to the weaver. It has a basic signature that knows
  25. * nothing about type variables, type parameters, etc.. UnresolvedTypes are resolved in some World
  26. * (a repository of types). When a UnresolvedType is resolved it turns into a
  27. * ResolvedType which may be a primitive type, an array type or a ReferenceType.
  28. * ReferenceTypes may refer to simple, generic, parameterized or type-variable
  29. * based reference types. A ReferenceType is backed by a delegate that provides
  30. * information about the type based on some repository (currently either BCEL
  31. * or an EclipseSourceType, but in the future we probably need to support
  32. * java.lang.reflect based delegates too).
  33. *
  34. * Every UnresolvedType has a signature, the unique key for the type in the world.
  35. *
  36. *
  37. * TypeXs are fully aware of their complete type information (there is no
  38. * erasure in the UnresolvedType world). To achieve this, the signature of TypeXs
  39. * combines the basic Java signature and the generic signature information
  40. * into one complete signature.
  41. *
  42. * The format of a UnresolvedType signature is as follows:
  43. *
  44. * a simple (non-generic, non-parameterized) type has the as its signature
  45. * the Java signature.
  46. * e.g. Ljava/lang/String;
  47. *
  48. * a generic type has signature:
  49. * TypeParamsOpt ClassSig SuperClassSig SuperIntfListOpt
  50. *
  51. * following the Generic signature grammar in the JVM spec., but with the
  52. * addition of the ClassSignature (which is not in the generic signature). In addition
  53. * type variable names are replaced by a simple number which represents their
  54. * declaration order in the type declaration.
  55. *
  56. * e.g. public class Foo<T extends Number> would have signature:
  57. * <1:Ljava/lang/Number>Lorg.xyz.Foo;Ljava/lang/Object;
  58. *
  59. * A parameterized type is a distinct type in the world with its own signature
  60. * following the grammar:
  61. *
  62. * TypeParamsOpt ClassSig<ParamSigList>;
  63. *
  64. * but with the L for the class sig replaced by "P". For example List<String> has
  65. * signature
  66. *
  67. * Pjava/util/List<Ljava/lang/String>;
  68. *
  69. * and List<T> in the following class :
  70. * class Foo<T> { List<T> lt; }
  71. *
  72. * has signature:
  73. * <1:>Pjava/util/List<T1;>;
  74. *
  75. * A typex that represents a type variable has its own unique signature,
  76. * following the grammar for a FormalTypeParameter in the JVM spec.
  77. *
  78. * A generic typex has its true signature and also an erasure signature.
  79. * Both of these are keys pointing to the same UnresolvedType in the world. For example
  80. * List has signature:
  81. *
  82. * <1:>Ljava/util/List;Ljava/lang/Object;
  83. *
  84. * and the erasure signature
  85. *
  86. * Ljava/util/List;
  87. *
  88. * Generics wildcards introduce their own special signatures for type parameters.
  89. * The wildcard ? has signature *
  90. * The wildcard ? extends Foo has signature +LFoo;
  91. * The wildcard ? super Foo has signature -LFoo;
  92. */
  93. public class UnresolvedType implements Traceable, TypeVariableDeclaringElement {
  94. // common types referred to by the weaver
  95. public static final UnresolvedType[] NONE = new UnresolvedType[0];
  96. public static final UnresolvedType OBJECT = forSignature("Ljava/lang/Object;");
  97. public static final UnresolvedType OBJECTARRAY = forSignature("[Ljava/lang/Object;");
  98. public static final UnresolvedType CLONEABLE = forSignature("Ljava/lang/Cloneable;");
  99. public static final UnresolvedType SERIALIZABLE = forSignature("Ljava/io/Serializable;");
  100. public static final UnresolvedType THROWABLE = forSignature("Ljava/lang/Throwable;");
  101. public static final UnresolvedType RUNTIME_EXCEPTION = forSignature("Ljava/lang/RuntimeException;");
  102. public static final UnresolvedType ERROR = forSignature("Ljava/lang/Error;");
  103. public static final UnresolvedType AT_INHERITED = forSignature("Ljava/lang/annotation/Inherited;");
  104. public static final UnresolvedType AT_RETENTION = forSignature("Ljava/lang/annotation/Retention;");
  105. public static final UnresolvedType ENUM = forSignature("Ljava/lang/Enum;");
  106. public static final UnresolvedType ANNOTATION = forSignature("Ljava/lang/annotation/Annotation;");
  107. public static final UnresolvedType JAVA_LANG_CLASS = forSignature("Ljava/lang/Class;");
  108. public static final UnresolvedType JAVA_LANG_STRING = forSignature("Ljava/lang/String;");
  109. public static final UnresolvedType JAVA_LANG_EXCEPTION = forSignature("Ljava/lang/Exception;");
  110. public static final UnresolvedType JAVA_LANG_REFLECT_METHOD = forSignature("Ljava/lang/reflect/Method;");
  111. public static final UnresolvedType SUPPRESS_AJ_WARNINGS = forSignature("Lorg/aspectj/lang/annotation/SuppressAjWarnings;");
  112. public static final UnresolvedType AT_TARGET = forSignature("Ljava/lang/annotation/Target;");
  113. public static final UnresolvedType SOMETHING = new UnresolvedType("?");
  114. public static final UnresolvedType[] ARRAY_WITH_JUST_OBJECT = new UnresolvedType[]{OBJECT};
  115. // this doesn't belong here and will get moved to ResolvedType later in the refactoring
  116. public static final String MISSING_NAME = "@missing@";
  117. // OPTIMIZE I dont think you can ask something unresolved what kind of type it is, how can it always know? Push down into resolvedtype
  118. // that will force references to resolvedtypes to be correct rather than relying on unresolvedtypes to answer questions
  119. protected TypeKind typeKind = TypeKind.SIMPLE; // what kind of type am I?
  120. /**
  121. * THE SIGNATURE - see the comments above for how this is defined
  122. */
  123. protected String signature;
  124. /**
  125. * The erasure of the signature. Contains only the Java signature of the type
  126. * with all supertype, superinterface, type variable, and parameter information
  127. * removed.
  128. */
  129. protected String signatureErasure;
  130. /**
  131. * Iff isParameterized(), then these are the type parameters
  132. */
  133. protected UnresolvedType[] typeParameters;
  134. /**
  135. * Iff isGeneric(), then these are the type variables declared on the type
  136. * Iff isParameterized(), then these are the type variables bound as parameters
  137. * in the type
  138. */
  139. protected TypeVariable[] typeVariables;
  140. /**
  141. * Iff isGenericWildcard, then this is the upper bound type for ? extends Foo
  142. */
  143. private UnresolvedType upperBound;
  144. /**
  145. * Iff isGenericWildcard, then this is the lower bound type for ? super Foo
  146. */
  147. private UnresolvedType lowerBound;
  148. /**
  149. * for wildcards '? extends' or for type variables 'T extends'
  150. */
  151. private boolean isSuper = false;
  152. private boolean isExtends = false;
  153. /**
  154. * Determines if this represents a primitive type. A primitive type
  155. * is one of nine predefined resolved types.
  156. *
  157. * @return true iff this type represents a primitive type
  158. *
  159. * @see ResolvedType#Boolean
  160. * @see ResolvedType#Character
  161. * @see ResolvedType#Byte
  162. * @see ResolvedType#Short
  163. * @see ResolvedType#Integer
  164. * @see ResolvedType#Long
  165. * @see ResolvedType#Float
  166. * @see ResolvedType#Double
  167. * @see ResolvedType#Void
  168. */
  169. public boolean isPrimitiveType() { return typeKind == TypeKind.PRIMITIVE; }
  170. public boolean isSimpleType() { return typeKind == TypeKind.SIMPLE; }
  171. public boolean isRawType() { return typeKind == TypeKind.RAW; }
  172. public boolean isGenericType() { return typeKind == TypeKind.GENERIC; }
  173. public boolean isParameterizedType() { return typeKind == TypeKind.PARAMETERIZED; }
  174. public boolean isTypeVariableReference() { return typeKind == TypeKind.TYPE_VARIABLE; }
  175. public boolean isGenericWildcard() { return typeKind == TypeKind.WILDCARD; }
  176. public boolean isExtends() { return isExtends;}
  177. public boolean isSuper() { return isSuper; }
  178. public TypeKind getTypekind() { return typeKind;}
  179. // for any reference type, we can get some extra information...
  180. public final boolean isArray() { return signature.startsWith("["); }
  181. /**
  182. * Equality is checked based on the underlying signature.
  183. * {@link ResolvedType} objects' equals is by reference.
  184. */
  185. public boolean equals(Object other) {
  186. if (! (other instanceof UnresolvedType)) return false;
  187. return signature.equals(((UnresolvedType) other).signature);
  188. }
  189. /**
  190. * Equality is checked based on the underlying signature, so the hash code
  191. * of a particular type is the hash code of its signature string.
  192. */
  193. public final int hashCode() {
  194. return signature.hashCode();
  195. }
  196. /**
  197. * Return a version of this parameterized type in which any type parameters
  198. * that are type variable references are replaced by their matching type variable
  199. * binding.
  200. */
  201. // OPTIMIZE methods like this just allow callers to be lazy and not ensure they are working with the right (resolved) subtype
  202. public UnresolvedType parameterize(Map typeBindings) {
  203. throw new UnsupportedOperationException("unable to parameterize unresolved type: " + signature);
  204. }
  205. /**
  206. * protected constructor for use only within UnresolvedType hierarchy. Use
  207. * one of the UnresolvedType.forXXX static methods for normal creation of
  208. * TypeXs.
  209. * Picks apart the signature string to set the type kind and calculates the
  210. * corresponding signatureErasure. A SIMPLE type created from a plain
  211. * Java signature may turn into a GENERIC type when it is resolved.
  212. *
  213. * This method should never be called for a primitive type. (UnresolvedType. forSignature
  214. * deals with those).
  215. *
  216. * @param signature in the form described in the class comment at the
  217. * top of this file.
  218. */
  219. // protected UnresolvedType(String aSignature) {
  220. // this.signature = aSignature;
  221. //
  222. //
  223. // }
  224. // -----------------------------
  225. // old stuff...
  226. /**
  227. * @param signature the bytecode string representation of this Type
  228. */
  229. protected UnresolvedType(String signature) {
  230. super();
  231. this.signature = signature;
  232. this.signatureErasure = signature;
  233. if (signature.charAt(0)=='-') isSuper = true;
  234. if (signature.charAt(0)=='+') isExtends = true;
  235. }
  236. protected UnresolvedType(String signature, String signatureErasure) {
  237. this.signature = signature;
  238. this.signatureErasure = signatureErasure;
  239. if (signature.charAt(0)=='-') isSuper = true;
  240. if (signature.charAt(0)=='+') isExtends = true;
  241. }
  242. // called from TypeFactory
  243. public UnresolvedType(String signature, String signatureErasure, UnresolvedType[] typeParams) {
  244. this.signature = signature;
  245. this.signatureErasure = signatureErasure;
  246. this.typeParameters = typeParams;
  247. if (typeParams != null) this.typeKind = TypeKind.PARAMETERIZED;
  248. }
  249. // ---- Things we can do without a world
  250. /**
  251. * This is the size of this type as used in JVM.
  252. */
  253. public int getSize() {
  254. return 1;
  255. }
  256. public static UnresolvedType makeArray(UnresolvedType base, int dims) {
  257. StringBuffer sig = new StringBuffer();
  258. for (int i=0; i < dims; i++) sig.append("[");
  259. sig.append(base.getSignature());
  260. return UnresolvedType.forSignature(sig.toString());
  261. }
  262. /**
  263. * NOTE: Use forSignature() if you can, it'll be cheaper !
  264. * Constructs a UnresolvedType for a java language type name. For example:
  265. *
  266. * <blockquote><pre>
  267. * UnresolvedType.forName("java.lang.Thread[]")
  268. * UnresolvedType.forName("int")
  269. * </pre></blockquote>
  270. *
  271. * Types may equivalently be produced by this or by {@link #forSignature(String)}.
  272. *
  273. * <blockquote><pre>
  274. * UnresolvedType.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;")
  275. * UnresolvedType.forName("int").equals(Type.forSignature("I"))
  276. * </pre></blockquote>
  277. *
  278. * @param name the java language type name in question.
  279. * @return a type object representing that java language type.
  280. */
  281. // OPTIMIZE change users of this to use forSignature, especially for simple cases
  282. public static UnresolvedType forName(String name) {
  283. return forSignature(nameToSignature(name));
  284. }
  285. /** Constructs a UnresolvedType for each java language type name in an incoming array.
  286. *
  287. * @param names an array of java language type names.
  288. * @return an array of UnresolvedType objects.
  289. * @see #forName(String)
  290. */
  291. public static UnresolvedType[] forNames(String[] names) {
  292. UnresolvedType[] ret = new UnresolvedType[names.length];
  293. for (int i = 0, len = names.length; i < len; i++) {
  294. ret[i] = UnresolvedType.forName(names[i]);
  295. }
  296. return ret;
  297. }
  298. public static UnresolvedType forGenericType(String name,TypeVariable[] tvbs,String genericSig) {
  299. // TODO asc generics needs a declared sig
  300. String sig = nameToSignature(name);
  301. UnresolvedType ret = UnresolvedType.forSignature(sig);
  302. ret.typeKind=TypeKind.GENERIC;
  303. ret.typeVariables = tvbs;
  304. ret.signatureErasure = sig;
  305. return ret;
  306. }
  307. public static UnresolvedType forGenericTypeSignature(String sig,String declaredGenericSig) {
  308. UnresolvedType ret = UnresolvedType.forSignature(sig);
  309. ret.typeKind=TypeKind.GENERIC;
  310. ClassSignature csig = new GenericSignatureParser().parseAsClassSignature(declaredGenericSig);
  311. Signature.FormalTypeParameter[] ftps = csig.formalTypeParameters;
  312. ret.typeVariables = new TypeVariable[ftps.length];
  313. for (int i = 0; i < ftps.length; i++) {
  314. Signature.FormalTypeParameter parameter = ftps[i];
  315. if (parameter.classBound instanceof Signature.ClassTypeSignature) {
  316. Signature.ClassTypeSignature cts = (Signature.ClassTypeSignature)parameter.classBound;
  317. ret.typeVariables[i]=new TypeVariable(ftps[i].identifier,UnresolvedType.forSignature(cts.outerType.identifier+";"));
  318. } else if (parameter.classBound instanceof Signature.TypeVariableSignature) {
  319. Signature.TypeVariableSignature tvs = (Signature.TypeVariableSignature)parameter.classBound;
  320. UnresolvedTypeVariableReferenceType utvrt = new UnresolvedTypeVariableReferenceType(new TypeVariable(tvs.typeVariableName));
  321. ret.typeVariables[i]=new TypeVariable(ftps[i].identifier,utvrt);
  322. } else {
  323. throw new BCException("UnresolvedType.forGenericTypeSignature(): Do not know how to process type variable bound of type '"+
  324. parameter.classBound.getClass()+"'. Full signature is '"+sig+"'");
  325. }
  326. }
  327. ret.signatureErasure = sig;
  328. ret.signature = ret.signatureErasure;
  329. return ret;
  330. }
  331. public static UnresolvedType forGenericTypeVariables(String sig, TypeVariable[] tVars) {
  332. UnresolvedType ret = UnresolvedType.forSignature(sig);
  333. ret.typeKind=TypeKind.GENERIC;
  334. ret.typeVariables = tVars;
  335. ret.signatureErasure = sig;
  336. ret.signature = ret.signatureErasure;
  337. return ret;
  338. }
  339. public static UnresolvedType forRawTypeName(String name) {
  340. UnresolvedType ret = UnresolvedType.forName(name);
  341. ret.typeKind = TypeKind.RAW;
  342. return ret;
  343. }
  344. /**
  345. * Creates a new type array with a fresh type appended to the end.
  346. *
  347. * @param types the left hand side of the new array
  348. * @param end the right hand side of the new array
  349. */
  350. public static UnresolvedType[] add(UnresolvedType[] types, UnresolvedType end) {
  351. int len = types.length;
  352. UnresolvedType[] ret = new UnresolvedType[len + 1];
  353. System.arraycopy(types, 0, ret, 0, len);
  354. ret[len] = end;
  355. return ret;
  356. }
  357. /**
  358. * Creates a new type array with a fresh type inserted at the beginning.
  359. *
  360. *
  361. * @param start the left hand side of the new array
  362. * @param types the right hand side of the new array
  363. */
  364. public static UnresolvedType[] insert(UnresolvedType start, UnresolvedType[] types) {
  365. int len = types.length;
  366. UnresolvedType[] ret = new UnresolvedType[len + 1];
  367. ret[0] = start;
  368. System.arraycopy(types, 0, ret, 1, len);
  369. return ret;
  370. }
  371. /**
  372. * Constructs a Type for a JVM bytecode signature string. For example:
  373. *
  374. * <blockquote><pre>
  375. * UnresolvedType.forSignature("[Ljava/lang/Thread;")
  376. * UnresolvedType.forSignature("I");
  377. * </pre></blockquote>
  378. *
  379. * Types may equivalently be produced by this or by {@link #forName(String)}.
  380. *
  381. * <blockquote><pre>
  382. * UnresolvedType.forName("java.lang.Thread[]").equals(Type.forSignature("[Ljava/lang/Thread;")
  383. * UnresolvedType.forName("int").equals(Type.forSignature("I"))
  384. * </pre></blockquote>
  385. *
  386. * @param signature the JVM bytecode signature string for the desired type.
  387. * @return a type object represnting that JVM bytecode signature.
  388. */
  389. public static UnresolvedType forSignature(String signature) {
  390. switch (signature.charAt(0)) {
  391. case 'B': return ResolvedType.BYTE;
  392. case 'C': return ResolvedType.CHAR;
  393. case 'D': return ResolvedType.DOUBLE;
  394. case 'F': return ResolvedType.FLOAT;
  395. case 'I': return ResolvedType.INT;
  396. case 'J': return ResolvedType.LONG;
  397. case 'L': return TypeFactory.createTypeFromSignature(signature);
  398. case 'P': return TypeFactory.createTypeFromSignature(signature);
  399. case 'S': return ResolvedType.SHORT;
  400. case 'V': return ResolvedType.VOID;
  401. case 'Z': return ResolvedType.BOOLEAN;
  402. case '[': return TypeFactory.createTypeFromSignature(signature);
  403. case '+': return TypeFactory.createTypeFromSignature(signature);
  404. case '-' : return TypeFactory.createTypeFromSignature(signature);
  405. case '?' : return TypeFactory.createTypeFromSignature(signature);
  406. case 'T' : return TypeFactory.createTypeFromSignature(signature);
  407. default: throw new BCException("Bad type signature " + signature);
  408. }
  409. }
  410. /** Constructs a UnresolvedType for each JVM bytecode type signature in an incoming array.
  411. *
  412. * @param names an array of JVM bytecode type signatures
  413. * @return an array of UnresolvedType objects.
  414. * @see #forSignature(String)
  415. */
  416. public static UnresolvedType[] forSignatures(String[] sigs) {
  417. UnresolvedType[] ret = new UnresolvedType[sigs.length];
  418. for (int i = 0, len = sigs.length; i < len; i++) {
  419. ret[i] = UnresolvedType.forSignature(sigs[i]);
  420. }
  421. return ret;
  422. }
  423. /**
  424. * Returns the name of this type in java language form (e.g. java.lang.Thread or boolean[]).
  425. * This produces a more aesthetically pleasing string than {@link java.lang.Class#getName()}.
  426. *
  427. * @return the java language name of this type.
  428. */
  429. public String getName() {
  430. return signatureToName(signature);
  431. }
  432. public String getSimpleName() {
  433. String name = getRawName();
  434. int lastDot = name.lastIndexOf('.');
  435. if (lastDot != -1) {
  436. name = name.substring(lastDot+1);
  437. }
  438. if (isParameterizedType()) {
  439. StringBuffer sb = new StringBuffer(name);
  440. sb.append("<");
  441. for (int i = 0; i < (typeParameters.length -1); i++) {
  442. sb.append(typeParameters[i].getSimpleName());
  443. sb.append(",");
  444. }
  445. sb.append(typeParameters[typeParameters.length -1].getSimpleName());
  446. sb.append(">");
  447. name = sb.toString();
  448. }
  449. return name;
  450. }
  451. public String getRawName() {
  452. return signatureToName((signatureErasure==null?signature:signatureErasure));
  453. }
  454. public String getBaseName() {
  455. String name = getName();
  456. if (isParameterizedType() || isGenericType()) {
  457. if (typeParameters==null) return name;
  458. else return name.substring(0,name.indexOf("<"));
  459. } else {
  460. return name;
  461. }
  462. }
  463. public String getSimpleBaseName() {
  464. String name = getBaseName();
  465. int lastDot = name.lastIndexOf('.');
  466. if (lastDot != -1) {
  467. name = name.substring(lastDot+1);
  468. }
  469. return name;
  470. }
  471. /**
  472. * Returns an array of strings representing the java langauge names of
  473. * an array of types.
  474. *
  475. * @param types an array of UnresolvedType objects
  476. * @return an array of Strings fo the java language names of types.
  477. * @see #getName()
  478. */
  479. public static String[] getNames(UnresolvedType[] types) {
  480. String[] ret = new String[types.length];
  481. for (int i = 0, len = types.length; i < len; i++) {
  482. ret[i] = types[i].getName();
  483. }
  484. return ret;
  485. }
  486. /**
  487. * Returns the name of this type in JVM signature form. For all
  488. * UnresolvedType t:
  489. *
  490. * <blockquote><pre>
  491. * UnresolvedType.forSignature(t.getSignature()).equals(t)
  492. * </pre></blockquote>
  493. *
  494. * and for all String s where s is a lexically valid JVM type signature string:
  495. *
  496. * <blockquote><pre>
  497. * UnresolvedType.forSignature(s).getSignature().equals(s)
  498. * </pre></blockquote>
  499. *
  500. * @return the java JVM signature string for this type.
  501. */
  502. public String getSignature() {
  503. return signature;
  504. }
  505. // public String getParameterizedSignature() {
  506. // return signature;
  507. // }
  508. /**
  509. * For parameterized types, return the signature for the raw type
  510. */
  511. public String getErasureSignature() {
  512. if (signatureErasure==null) return signature;
  513. return signatureErasure;
  514. }
  515. private boolean needsModifiableDelegate =false;
  516. public boolean needsModifiableDelegate() {
  517. return needsModifiableDelegate;
  518. }
  519. public void setNeedsModifiableDelegate(boolean b) {
  520. this.needsModifiableDelegate=b;
  521. }
  522. public UnresolvedType getRawType() {
  523. return UnresolvedType.forSignature(getErasureSignature());
  524. }
  525. /**
  526. * Get the upper bound for a generic wildcard
  527. */
  528. public UnresolvedType getUpperBound() {
  529. return upperBound;
  530. }
  531. /**
  532. * Get the lower bound for a generic wildcard
  533. */
  534. public UnresolvedType getLowerBound() {
  535. return lowerBound;
  536. }
  537. /**
  538. * Set the upper bound for a generic wildcard
  539. */
  540. public void setUpperBound(UnresolvedType aBound) {
  541. this.upperBound = aBound;
  542. }
  543. /**
  544. * Set the lower bound for a generic wildcard
  545. */
  546. public void setLowerBound(UnresolvedType aBound) {
  547. this.lowerBound = aBound;
  548. }
  549. /**
  550. * Returns a UnresolvedType object representing the effective outermost enclosing type
  551. * for a name type. For all other types, this will return the type itself.
  552. *
  553. * The only guarantee is given in JLS 13.1 where code generated according to
  554. * those rules will have type names that can be split apart in this way.
  555. * @return the outermost enclosing UnresolvedType object or this.
  556. */
  557. public UnresolvedType getOutermostType() {
  558. if (isArray() || isPrimitiveType()) return this;
  559. String sig = getErasureSignature();
  560. int dollar = sig.indexOf('$');
  561. if (dollar != -1) {
  562. return UnresolvedType.forSignature(sig.substring(0, dollar) + ';');
  563. } else {
  564. return this;
  565. }
  566. }
  567. /**
  568. * Returns a UnresolvedType object representing the component type of this array, or
  569. * null if this type does not represent an array type.
  570. *
  571. * @return the component UnresolvedType object, or null.
  572. */
  573. public UnresolvedType getComponentType() {
  574. if (isArray()) {
  575. return forSignature(signature.substring(1));
  576. } else {
  577. return null;
  578. }
  579. }
  580. /**
  581. * Returns a java language string representation of this type.
  582. */
  583. public String toString() {
  584. return getName(); // + " - " + getKind();
  585. }
  586. public String toDebugString() {
  587. return getName();
  588. }
  589. // ---- requires worlds
  590. /**
  591. * Returns a resolved version of this type according to a particular world.
  592. *
  593. * @param world thie {@link World} within which to resolve.
  594. * @return a resolved type representing this type in the appropriate world.
  595. */
  596. public ResolvedType resolve(World world) {
  597. return world.resolve(this);
  598. }
  599. // ---- helpers
  600. private static String signatureToName(String signature) {
  601. switch (signature.charAt(0)) {
  602. case 'B': return "byte";
  603. case 'C': return "char";
  604. case 'D': return "double";
  605. case 'F': return "float";
  606. case 'I': return "int";
  607. case 'J': return "long";
  608. case 'L':
  609. String name = signature.substring(1, signature.length() - 1).replace('/', '.');
  610. return name;
  611. case 'T':
  612. StringBuffer nameBuff2 = new StringBuffer();
  613. int colon = signature.indexOf(";");
  614. String tvarName = signature.substring(1,colon);
  615. nameBuff2.append(tvarName);
  616. return nameBuff2.toString();
  617. case 'P': // it's one of our parameterized type sigs
  618. StringBuffer nameBuff = new StringBuffer();
  619. // signature for parameterized types is e.g.
  620. // List<String> -> Ljava/util/List<Ljava/lang/String;>;
  621. // Map<String,List<Integer>> -> Ljava/util/Map<java/lang/String;Ljava/util/List<Ljava/lang/Integer;>;>;
  622. int paramNestLevel = 0;
  623. for (int i = 1 ; i < signature.length(); i++) {
  624. char c = signature.charAt(i);
  625. switch (c) {
  626. case '/' : nameBuff.append('.'); break;
  627. case '<' :
  628. nameBuff.append("<");
  629. paramNestLevel++;
  630. StringBuffer innerBuff = new StringBuffer();
  631. while(paramNestLevel > 0) {
  632. c = signature.charAt(++i);
  633. if (c == '<') paramNestLevel++;
  634. if (c == '>') paramNestLevel--;
  635. if (paramNestLevel > 0) innerBuff.append(c);
  636. if (c == ';' && paramNestLevel == 1) {
  637. nameBuff.append(signatureToName(innerBuff.toString()));
  638. if (signature.charAt(i+1) != '>') nameBuff.append(',');
  639. innerBuff = new StringBuffer();
  640. }
  641. }
  642. nameBuff.append(">");
  643. break;
  644. case ';' : break;
  645. default:
  646. nameBuff.append(c);
  647. }
  648. }
  649. return nameBuff.toString();
  650. case 'S': return "short";
  651. case 'V': return "void";
  652. case 'Z': return "boolean";
  653. case '[':
  654. return signatureToName(signature.substring(1, signature.length())) + "[]";
  655. // case '<':
  656. // // its a generic!
  657. // if (signature.charAt(1)=='>') return signatureToName(signature.substring(2));
  658. case '+' : return "? extends " + signatureToName(signature.substring(1, signature.length()));
  659. case '-' : return "? super " + signatureToName(signature.substring(1, signature.length()));
  660. case '?' : return "?";
  661. default:
  662. throw new BCException("Bad type signature: " + signature);
  663. }
  664. }
  665. private static String nameToSignature(String name) {
  666. if (name.equals("byte")) return "B";
  667. if (name.equals("char")) return "C";
  668. if (name.equals("double")) return "D";
  669. if (name.equals("float")) return "F";
  670. if (name.equals("int")) return "I";
  671. if (name.equals("long")) return "J";
  672. if (name.equals("short")) return "S";
  673. if (name.equals("boolean")) return "Z";
  674. if (name.equals("void")) return "V";
  675. if (name.equals("?")) return name;
  676. if (name.endsWith("[]"))
  677. return "[" + nameToSignature(name.substring(0, name.length() - 2));
  678. if (name.length() != 0) {
  679. // lots more tests could be made here...
  680. // check if someone is calling us with something that is a signature already
  681. if (name.charAt(0)=='[') {
  682. throw new BCException("Do not call nameToSignature with something that looks like a signature (descriptor): '"+name+"'");
  683. }
  684. if (name.indexOf("<") == -1) {
  685. // not parameterised
  686. return "L" + name.replace('.', '/') + ";";
  687. } else {
  688. StringBuffer nameBuff = new StringBuffer();
  689. int nestLevel = 0;
  690. nameBuff.append("P");
  691. for (int i = 0; i < name.length(); i++) {
  692. char c = name.charAt(i);
  693. switch (c) {
  694. case '.' : nameBuff.append('/'); break;
  695. case '<' :
  696. nameBuff.append("<");
  697. nestLevel++;
  698. StringBuffer innerBuff = new StringBuffer();
  699. while(nestLevel > 0) {
  700. c = name.charAt(++i);
  701. if (c == '<') nestLevel++;
  702. if (c == '>') nestLevel--;
  703. if (c == ',' && nestLevel == 1) {
  704. nameBuff.append(nameToSignature(innerBuff.toString()));
  705. innerBuff = new StringBuffer();
  706. } else {
  707. if (nestLevel > 0) innerBuff.append(c);
  708. }
  709. }
  710. nameBuff.append(nameToSignature(innerBuff.toString()));
  711. nameBuff.append('>');
  712. break;
  713. case '>' :
  714. throw new IllegalStateException("Should by matched by <");
  715. case ',' :
  716. throw new IllegalStateException("Should only happen inside <...>");
  717. default: nameBuff.append(c);
  718. }
  719. }
  720. nameBuff.append(";");
  721. return nameBuff.toString();
  722. }
  723. }
  724. else
  725. throw new BCException("Bad type name: " + name);
  726. }
  727. public void write(DataOutputStream s) throws IOException {
  728. s.writeUTF(getSignature());
  729. }
  730. public static UnresolvedType read(DataInputStream s) throws IOException {
  731. String sig = s.readUTF();
  732. if (sig.equals(MISSING_NAME)) {
  733. return ResolvedType.MISSING;
  734. } else {
  735. UnresolvedType ret = UnresolvedType.forSignature(sig);
  736. return ret;
  737. }
  738. }
  739. public static void writeArray(UnresolvedType[] types, DataOutputStream s) throws IOException {
  740. int len = types.length;
  741. s.writeShort(len);
  742. for (int i=0; i < len; i++) {
  743. types[i].write(s);
  744. }
  745. }
  746. public static UnresolvedType[] readArray(DataInputStream s) throws IOException {
  747. int len = s.readShort();
  748. if (len==0) return UnresolvedType.NONE;
  749. UnresolvedType[] types = new UnresolvedType[len];
  750. for (int i=0; i < len; i++) {
  751. types[i] = UnresolvedType.read(s);
  752. }
  753. return types;
  754. }
  755. public String getNameAsIdentifier() {
  756. return getName().replace('.', '_');
  757. }
  758. public String getPackageNameAsIdentifier() {
  759. String name = getName();
  760. int index = name.lastIndexOf('.');
  761. if (index == -1) {
  762. return "";
  763. } else {
  764. return name.substring(0, index).replace('.', '_');
  765. }
  766. }
  767. public String getPackageName() {
  768. String name = getName();
  769. if (name.indexOf("<")!=-1) {
  770. name = name.substring(0,name.indexOf("<"));
  771. }
  772. int index = name.lastIndexOf('.');
  773. if (index == -1) {
  774. return null;
  775. } else {
  776. return name.substring(0, index);
  777. }
  778. }
  779. public UnresolvedType[] getTypeParameters() {
  780. return typeParameters == null ? UnresolvedType.NONE : typeParameters;
  781. }
  782. /**
  783. * Doesn't include the package
  784. */
  785. public String getClassName() {
  786. String name = getName();
  787. int index = name.lastIndexOf('.');
  788. if (index == -1) {
  789. return name;
  790. } else {
  791. return name.substring(index+1);
  792. }
  793. }
  794. public TypeVariable[] getTypeVariables() {
  795. return typeVariables;
  796. }
  797. public static class TypeKind {
  798. // Note: It is not sufficient to say that a parameterized type with no type parameters in fact
  799. // represents a raw type - a parameterized type with no type parameters can represent
  800. // an inner type of a parameterized type that specifies no type parameters of its own.
  801. public final static TypeKind PRIMITIVE = new TypeKind("primitive");
  802. public final static TypeKind SIMPLE = new TypeKind("simple"); // a type with NO type parameters/vars
  803. public final static TypeKind RAW = new TypeKind("raw"); // the erasure of a generic type
  804. public final static TypeKind GENERIC = new TypeKind("generic"); // a generic type
  805. public final static TypeKind PARAMETERIZED= new TypeKind("parameterized"); // a parameterized type
  806. public final static TypeKind TYPE_VARIABLE= new TypeKind("type_variable"); // a type variable
  807. public final static TypeKind WILDCARD = new TypeKind("wildcard"); // a generic wildcard type
  808. public String toString() {
  809. return type;
  810. }
  811. private TypeKind(String type) {
  812. this.type = type;
  813. }
  814. private final String type;
  815. }
  816. /**
  817. * Will return true if the type being represented is parameterized with a type variable
  818. * from a generic method/ctor rather than a type variable from a generic type.
  819. * Only subclasses know the answer...
  820. */
  821. // OPTIMIZE don't allow this to be called, the caller must have a resolved entity
  822. public boolean isParameterizedWithAMemberTypeVariable() {
  823. throw new RuntimeException("I dont know - you should ask a resolved version of me: "+this);
  824. }
  825. public TypeVariable getTypeVariableNamed(String name) {
  826. TypeVariable[] vars = getTypeVariables();
  827. if (vars==null || vars.length==0) return null;
  828. for (int i = 0; i < vars.length; i++) {
  829. TypeVariable aVar = vars[i];
  830. if (aVar.getName().equals(name)) return aVar;
  831. }
  832. return null;
  833. }
  834. public String toTraceString() {
  835. return getClass().getName() + "[" + getName() + "]";
  836. }
  837. }