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

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