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

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