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 30KB

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