您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

UnresolvedType.java 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962
  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 BOOLEAN = forPrimitiveType("Z");
  60. public static final UnresolvedType BYTE = forPrimitiveType("B");
  61. public static final UnresolvedType CHAR = forPrimitiveType("C");
  62. public static final UnresolvedType DOUBLE = forPrimitiveType("D");
  63. public static final UnresolvedType FLOAT = forPrimitiveType("F");
  64. public static final UnresolvedType INT = forPrimitiveType("I");
  65. public static final UnresolvedType LONG = forPrimitiveType("J");
  66. public static final UnresolvedType SHORT = forPrimitiveType("S");
  67. public static final UnresolvedType VOID = forPrimitiveType("V");
  68. // A type is considered missing if we have a signature for it but cannot find the delegate
  69. public static final String MISSING_NAME = "@missing@";
  70. // OPTIMIZE I dont think you can ask something unresolved what kind of type it is, how can it always know? Push down into
  71. // resolvedtype that will force references to resolvedtypes to be correct rather than relying on unresolvedtypes to answer
  72. // questions
  73. protected TypeKind typeKind = TypeKind.SIMPLE; // what kind of type am I?
  74. protected String signature;
  75. /**
  76. * The erasure of the signature. Contains only the Java signature of the type with all supertype, superinterface, type variable,
  77. * and parameter information removed.
  78. */
  79. protected String signatureErasure;
  80. /**
  81. * Calculated on first request - the package name (java.lang for type java.lang.String)
  82. */
  83. private String packageName;
  84. /**
  85. * Calculated on first request - the class name (String for type java.lang.String)
  86. */
  87. private String className;
  88. /**
  89. * Iff isParameterized(), then these are the type parameters
  90. */
  91. protected UnresolvedType[] typeParameters;
  92. /**
  93. * Iff isGeneric(), then these are the type variables declared on the type Iff isParameterized(), then these are the type
  94. * variables bound as parameters in the type
  95. */
  96. // OPTIMIZE should be no state in here that will damage whether equals() is correct...
  97. protected TypeVariable[] typeVariables;
  98. public boolean isPrimitiveType() {
  99. return typeKind == TypeKind.PRIMITIVE;
  100. }
  101. public boolean isVoid() {
  102. // OPTIMIZE promote to bitflag?
  103. return signature.equals("V");
  104. }
  105. public boolean isSimpleType() {
  106. return typeKind == TypeKind.SIMPLE;
  107. }
  108. public boolean isRawType() {
  109. return typeKind == TypeKind.RAW;
  110. }
  111. public boolean isGenericType() {
  112. return typeKind == TypeKind.GENERIC;
  113. }
  114. public boolean isParameterizedType() {
  115. return typeKind == TypeKind.PARAMETERIZED;
  116. }
  117. public boolean isParameterizedOrGenericType() {
  118. return typeKind == TypeKind.GENERIC || typeKind == TypeKind.PARAMETERIZED;
  119. }
  120. public boolean isParameterizedOrRawType() {
  121. return typeKind == TypeKind.PARAMETERIZED || typeKind == TypeKind.RAW;
  122. }
  123. public boolean isTypeVariableReference() {
  124. return typeKind == TypeKind.TYPE_VARIABLE;
  125. }
  126. public boolean isGenericWildcard() {
  127. return typeKind == TypeKind.WILDCARD;
  128. }
  129. public TypeKind getTypekind() {
  130. return typeKind;
  131. }
  132. // for any reference type, we can get some extra information...
  133. public final boolean isArray() {
  134. return signature.length() > 0 && signature.charAt(0) == '[';
  135. }
  136. /**
  137. * Equality is checked based on the underlying signature.
  138. */
  139. @Override
  140. public boolean equals(Object other) {
  141. if (!(other instanceof UnresolvedType)) {
  142. return false;
  143. }
  144. return signature.equals(((UnresolvedType) other).signature);
  145. }
  146. /**
  147. * Equality is checked based on the underlying signature, so the hash code of a particular type is the hash code of its
  148. * signature string.
  149. */
  150. @Override
  151. public final int hashCode() {
  152. return signature.hashCode();
  153. }
  154. protected UnresolvedType(String signature) {
  155. this.signature = signature;
  156. this.signatureErasure = signature;
  157. }
  158. protected UnresolvedType(String signature, String signatureErasure) {
  159. this.signature = signature;
  160. this.signatureErasure = signatureErasure;
  161. }
  162. // called from TypeFactory
  163. public UnresolvedType(String signature, String signatureErasure, UnresolvedType[] typeParams) {
  164. this.signature = signature;
  165. this.signatureErasure = signatureErasure;
  166. this.typeParameters = typeParams;
  167. if (typeParams != null) {
  168. this.typeKind = TypeKind.PARAMETERIZED;
  169. }
  170. }
  171. // The operations supported by an UnresolvedType are those that do not require a world
  172. /**
  173. * This is the size of this type as used in JVM.
  174. */
  175. public int getSize() {
  176. return size;
  177. }
  178. private int size = 1;
  179. /**
  180. * NOTE: Use forSignature() if you can, it'll be cheaper ! Constructs a UnresolvedType for a java language type name. For
  181. * example:
  182. *
  183. * <blockquote>
  184. *
  185. * <pre>
  186. * UnresolvedType.forName(&quot;java.lang.Thread[]&quot;)
  187. * UnresolvedType.forName(&quot;int&quot;)
  188. * </pre>
  189. *
  190. * </blockquote>
  191. *
  192. * Types may equivalently be produced by this or by {@link #forSignature(String)}.
  193. *
  194. * <blockquote>
  195. *
  196. * <pre>
  197. * UnresolvedType.forName(&quot;java.lang.Thread[]&quot;).equals(Type.forSignature(&quot;[Ljava/lang/Thread;&quot;)
  198. * UnresolvedType.forName(&quot;int&quot;).equals(Type.forSignature(&quot;I&quot;))
  199. * </pre>
  200. *
  201. * </blockquote>
  202. *
  203. * @param name the java language type name in question.
  204. * @return a type object representing that java language type.
  205. */
  206. // OPTIMIZE change users of this to use forSignature, especially for simple cases
  207. public static UnresolvedType forName(String name) {
  208. return forSignature(nameToSignature(name));
  209. }
  210. /**
  211. * Constructs a UnresolvedType for each java language type name in an incoming array.
  212. *
  213. * @param names an array of java language type names.
  214. * @return an array of UnresolvedType objects.
  215. * @see #forName(String)
  216. */
  217. public static UnresolvedType[] forNames(String[] names) {
  218. UnresolvedType[] ret = new UnresolvedType[names.length];
  219. for (int i = 0, len = names.length; i < len; i++) {
  220. ret[i] = UnresolvedType.forName(names[i]);
  221. }
  222. return ret;
  223. }
  224. public static UnresolvedType forGenericType(String name, TypeVariable[] tvbs, String genericSig) {
  225. // TODO asc generics needs a declared sig
  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("byte")) {
  646. return "B";
  647. }
  648. if (name.equals("char")) {
  649. return "C";
  650. }
  651. if (name.equals("double")) {
  652. return "D";
  653. }
  654. if (name.equals("float")) {
  655. return "F";
  656. }
  657. if (name.equals("int")) {
  658. return "I";
  659. }
  660. if (name.equals("long")) {
  661. return "J";
  662. }
  663. if (name.equals("short")) {
  664. return "S";
  665. }
  666. if (name.equals("boolean")) {
  667. return "Z";
  668. }
  669. if (name.equals("void")) {
  670. return "V";
  671. }
  672. if (name.equals("?")) {
  673. return name;
  674. }
  675. }
  676. if (name.endsWith("[]")) {
  677. return "[" + nameToSignature(name.substring(0, name.length() - 2));
  678. }
  679. if (len == 0) {
  680. throw new BCException("Bad type name: " + name);
  681. }
  682. if (name.indexOf("<") == -1) {
  683. // not parameterized
  684. return new StringBuilder("L").append(name.replace('.', '/')).append(';').toString();
  685. } else {
  686. StringBuffer nameBuff = new StringBuffer();
  687. int nestLevel = 0;
  688. nameBuff.append("P");
  689. for (int i = 0; i < len; i++) {
  690. char c = name.charAt(i);
  691. switch (c) {
  692. case '.':
  693. nameBuff.append('/');
  694. 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 == '<') {
  702. nestLevel++;
  703. } else if (c == '>') {
  704. nestLevel--;
  705. }
  706. if (c == ',' && nestLevel == 1) {
  707. nameBuff.append(nameToSignature(innerBuff.toString()));
  708. innerBuff = new StringBuffer();
  709. } else {
  710. if (nestLevel > 0) {
  711. innerBuff.append(c);
  712. }
  713. }
  714. }
  715. nameBuff.append(nameToSignature(innerBuff.toString()));
  716. nameBuff.append('>');
  717. break;
  718. // case '>':
  719. // throw new IllegalStateException("Should by matched by <");
  720. // case ',':
  721. // throw new IllegalStateException("Should only happen inside <...>");
  722. default:
  723. nameBuff.append(c);
  724. }
  725. }
  726. nameBuff.append(";");
  727. return nameBuff.toString();
  728. }
  729. }
  730. /**
  731. * Write out an UnresolvedType - the signature should be enough.
  732. */
  733. public final void write(CompressingDataOutputStream s) throws IOException {
  734. s.writeUTF(getSignature());
  735. }
  736. /**
  737. * Read in an UnresolvedType - just read the signature and rebuild the UnresolvedType.
  738. */
  739. public static UnresolvedType read(DataInputStream s) throws IOException {
  740. String sig = s.readUTF();
  741. if (sig.equals(MISSING_NAME)) {
  742. return ResolvedType.MISSING;
  743. } else {
  744. // TODO isn't it a shame to build these (this method is expensive) and then chuck them away on resolution?
  745. // TODO review callers and see if they are immediately resolving it, maybe we can do something more optimal if they are
  746. return UnresolvedType.forSignature(sig);
  747. }
  748. }
  749. public String getNameAsIdentifier() {
  750. return getName().replace('.', '_');
  751. }
  752. public String getPackageNameAsIdentifier() {
  753. String name = getName();
  754. int index = name.lastIndexOf('.');
  755. if (index == -1) {
  756. return "";
  757. } else {
  758. return name.substring(0, index).replace('.', '_');
  759. }
  760. }
  761. public UnresolvedType[] getTypeParameters() {
  762. return typeParameters == null ? UnresolvedType.NONE : typeParameters;
  763. }
  764. public TypeVariable[] getTypeVariables() {
  765. return typeVariables;
  766. }
  767. public static class TypeKind {
  768. // Note: It is not sufficient to say that a parameterized type with no type parameters in fact
  769. // represents a raw type - a parameterized type with no type parameters can represent
  770. // an inner type of a parameterized type that specifies no type parameters of its own.
  771. public final static TypeKind PRIMITIVE = new TypeKind("primitive");
  772. public final static TypeKind SIMPLE = new TypeKind("simple"); // a type with NO type parameters/vars
  773. public final static TypeKind RAW = new TypeKind("raw"); // the erasure of a generic type
  774. public final static TypeKind GENERIC = new TypeKind("generic"); // a generic type
  775. public final static TypeKind PARAMETERIZED = new TypeKind("parameterized"); // a parameterized type
  776. public final static TypeKind TYPE_VARIABLE = new TypeKind("type_variable"); // a type variable
  777. public final static TypeKind WILDCARD = new TypeKind("wildcard"); // a generic wildcard type
  778. @Override
  779. public String toString() {
  780. return type;
  781. }
  782. private TypeKind(String type) {
  783. this.type = type;
  784. }
  785. private final String type;
  786. }
  787. public TypeVariable getTypeVariableNamed(String name) {
  788. TypeVariable[] vars = getTypeVariables();
  789. if (vars == null || vars.length == 0) {
  790. return null;
  791. }
  792. for (int i = 0; i < vars.length; i++) {
  793. TypeVariable aVar = vars[i];
  794. if (aVar.getName().equals(name)) {
  795. return aVar;
  796. }
  797. }
  798. return null;
  799. }
  800. public String toTraceString() {
  801. return getClass().getName() + "[" + getName() + "]";
  802. }
  803. /**
  804. * Return a version of this parameterized type in which any type parameters that are type variable references are replaced by
  805. * their matching type variable binding.
  806. */
  807. // OPTIMIZE methods like this just allow callers to be lazy and not ensure they are working with the right (resolved) subtype
  808. public UnresolvedType parameterize(Map<String, UnresolvedType> typeBindings) {
  809. throw new UnsupportedOperationException("unable to parameterize unresolved type: " + signature);
  810. }
  811. /**
  812. * @return the class name (does not include the package name)
  813. */
  814. public String getClassName() {
  815. if (className == null) {
  816. String name = getName();
  817. if (name.indexOf("<") != -1) {
  818. name = name.substring(0, name.indexOf("<"));
  819. }
  820. int index = name.lastIndexOf('.');
  821. if (index == -1) {
  822. className = name;
  823. } else {
  824. className = name.substring(index + 1);
  825. }
  826. }
  827. return className;
  828. }
  829. /**
  830. * @return the package name (no class name included)
  831. */
  832. public String getPackageName() {
  833. if (packageName == null) {
  834. String name = getName();
  835. if (name.indexOf("<") != -1) {
  836. name = name.substring(0, name.indexOf("<"));
  837. }
  838. int index = name.lastIndexOf('.');
  839. if (index == -1) {
  840. packageName = "";
  841. } else {
  842. packageName = name.substring(0, index);
  843. }
  844. }
  845. return packageName;
  846. }
  847. // TODO these move to a TypeUtils class
  848. public static void writeArray(UnresolvedType[] types, CompressingDataOutputStream stream) throws IOException {
  849. int len = types.length;
  850. stream.writeShort(len);
  851. for (UnresolvedType type : types) {
  852. type.write(stream);
  853. }
  854. }
  855. public static UnresolvedType[] readArray(DataInputStream s) throws IOException {
  856. int len = s.readShort();
  857. if (len == 0) {
  858. return UnresolvedType.NONE;
  859. }
  860. UnresolvedType[] types = new UnresolvedType[len];
  861. for (int i = 0; i < len; i++) {
  862. types[i] = UnresolvedType.read(s);
  863. }
  864. return types;
  865. }
  866. public static UnresolvedType makeArray(UnresolvedType base, int dims) {
  867. StringBuffer sig = new StringBuffer();
  868. for (int i = 0; i < dims; i++) {
  869. sig.append("[");
  870. }
  871. sig.append(base.getSignature());
  872. return UnresolvedType.forSignature(sig.toString());
  873. }
  874. }