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.

BcelGenericSignatureToTypeXConverter.java 13KB

14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
16 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /* *******************************************************************
  2. * Copyright (c) 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. * Adrian Colyer Initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.bcel;
  13. import java.util.HashMap;
  14. import java.util.Map;
  15. import org.aspectj.util.GenericSignature;
  16. import org.aspectj.util.GenericSignature.SimpleClassTypeSignature;
  17. import org.aspectj.weaver.BoundedReferenceType;
  18. import org.aspectj.weaver.ReferenceType;
  19. import org.aspectj.weaver.ResolvedType;
  20. import org.aspectj.weaver.TypeFactory;
  21. import org.aspectj.weaver.TypeVariable;
  22. import org.aspectj.weaver.TypeVariableReferenceType;
  23. import org.aspectj.weaver.UnresolvedType;
  24. import org.aspectj.weaver.World;
  25. import org.aspectj.weaver.tools.Trace;
  26. import org.aspectj.weaver.tools.TraceFactory;
  27. /**
  28. * A utility class that assists in unpacking constituent parts of generic signature attributes and returning their equivalents in
  29. * UnresolvedType world.
  30. */
  31. public class BcelGenericSignatureToTypeXConverter {
  32. private static final Trace trace = TraceFactory.getTraceFactory().getTrace(BcelGenericSignatureToTypeXConverter.class);
  33. public static ResolvedType classTypeSignature2TypeX(GenericSignature.ClassTypeSignature aClassTypeSignature,
  34. GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
  35. Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<>();
  36. ResolvedType ret = classTypeSignature2TypeX(aClassTypeSignature, typeParams, world, typeMap);
  37. fixUpCircularDependencies(ret, typeMap);
  38. return ret;
  39. }
  40. private static ResolvedType classTypeSignature2TypeX(GenericSignature.ClassTypeSignature aClassTypeSignature,
  41. GenericSignature.FormalTypeParameter[] typeParams, World world,
  42. Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
  43. throws GenericSignatureFormatException {
  44. // class type sig consists of an outer type, and zero or more nested types
  45. // the fully qualified name is outer-type.nested-type1.nested-type2....
  46. // each type in the hierarchy may have type arguments
  47. // first build the 'raw type' signature
  48. StringBuilder sig = new StringBuilder();
  49. sig.append(aClassTypeSignature.outerType.identifier.replace(';', ' ').trim());
  50. for (int i = 0; i < aClassTypeSignature.nestedTypes.length; i++) {
  51. sig.append("$");
  52. sig.append(aClassTypeSignature.nestedTypes[i].identifier.replace(';', ' ').trim());
  53. }
  54. sig.append(";");
  55. // now look for any type parameters.
  56. // I *think* we only need to worry about the 'right-most' type...
  57. SimpleClassTypeSignature innerType = aClassTypeSignature.outerType;
  58. if (aClassTypeSignature.nestedTypes.length > 0) {
  59. innerType = aClassTypeSignature.nestedTypes[aClassTypeSignature.nestedTypes.length - 1];
  60. }
  61. if (innerType.typeArguments.length > 0) {
  62. // we have to create a parameterized type
  63. // type arguments may be array types, class types, or typevariable types
  64. ResolvedType theBaseType = UnresolvedType.forSignature(sig.toString()).resolve(world);
  65. // Sometimes we may find that when the code is being load-time woven that the types have changed.
  66. // Perhaps an old form of a library jar is being used - this can mean we discover right here
  67. // that a type is not parameterizable (is that a word?). I think in these cases it is ok to
  68. // just return with what we know (the base type). (see pr152848)
  69. if (!(theBaseType.isGenericType() || theBaseType.isRawType())) {
  70. if (trace.isTraceEnabled()) {
  71. trace.event("classTypeSignature2TypeX: this type is not a generic type:", null, new Object[] { theBaseType });
  72. }
  73. return theBaseType;
  74. }
  75. ResolvedType[] typeArgumentTypes = new ResolvedType[innerType.typeArguments.length];
  76. for (int i = 0; i < typeArgumentTypes.length; i++) {
  77. typeArgumentTypes[i] = typeArgument2TypeX(innerType.typeArguments[i], typeParams, world,
  78. inProgressTypeVariableResolutions);
  79. }
  80. return TypeFactory.createParameterizedType(theBaseType, typeArgumentTypes, world);
  81. // world.resolve(UnresolvedType.forParameterizedTypes(
  82. // UnresolvedType.forSignature(sig.toString()).resolve(world),
  83. // typeArgumentTypes));
  84. } else {
  85. // we have a non-parameterized type
  86. return world.resolve(UnresolvedType.forSignature(sig.toString()));
  87. }
  88. }
  89. public static ResolvedType fieldTypeSignature2TypeX(GenericSignature.FieldTypeSignature aFieldTypeSignature,
  90. GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
  91. Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<>();
  92. ResolvedType ret = fieldTypeSignature2TypeX(aFieldTypeSignature, typeParams, world, typeMap);
  93. fixUpCircularDependencies(ret, typeMap);
  94. return ret;
  95. }
  96. private static ResolvedType fieldTypeSignature2TypeX(GenericSignature.FieldTypeSignature aFieldTypeSignature,
  97. GenericSignature.FormalTypeParameter[] typeParams, World world,
  98. Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
  99. throws GenericSignatureFormatException {
  100. if (aFieldTypeSignature.isClassTypeSignature()) {
  101. return classTypeSignature2TypeX((GenericSignature.ClassTypeSignature) aFieldTypeSignature, typeParams, world,
  102. inProgressTypeVariableResolutions);
  103. } else if (aFieldTypeSignature.isArrayTypeSignature()) {
  104. int dims = 0;
  105. GenericSignature.TypeSignature ats = aFieldTypeSignature;
  106. while (ats instanceof GenericSignature.ArrayTypeSignature) {
  107. dims++;
  108. ats = ((GenericSignature.ArrayTypeSignature) ats).typeSig;
  109. }
  110. return world.resolve(UnresolvedType.makeArray(
  111. typeSignature2TypeX(ats, typeParams, world, inProgressTypeVariableResolutions), dims));
  112. } else if (aFieldTypeSignature.isTypeVariableSignature()) {
  113. ResolvedType rtx = typeVariableSignature2TypeX((GenericSignature.TypeVariableSignature) aFieldTypeSignature,
  114. typeParams, world, inProgressTypeVariableResolutions);
  115. return rtx;
  116. } else {
  117. throw new GenericSignatureFormatException("Cant understand field type signature: " + aFieldTypeSignature);
  118. }
  119. }
  120. public static TypeVariable formalTypeParameter2TypeVariable(GenericSignature.FormalTypeParameter aFormalTypeParameter,
  121. GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
  122. Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<>();
  123. return formalTypeParameter2TypeVariable(aFormalTypeParameter, typeParams, world, typeMap);
  124. }
  125. private static TypeVariable formalTypeParameter2TypeVariable(GenericSignature.FormalTypeParameter aFormalTypeParameter,
  126. GenericSignature.FormalTypeParameter[] typeParams, World world,
  127. Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
  128. throws GenericSignatureFormatException {
  129. UnresolvedType upperBound = fieldTypeSignature2TypeX(aFormalTypeParameter.classBound, typeParams, world,
  130. inProgressTypeVariableResolutions);
  131. UnresolvedType[] ifBounds = new UnresolvedType[aFormalTypeParameter.interfaceBounds.length];
  132. for (int i = 0; i < ifBounds.length; i++) {
  133. ifBounds[i] = fieldTypeSignature2TypeX(aFormalTypeParameter.interfaceBounds[i], typeParams, world,
  134. inProgressTypeVariableResolutions);
  135. }
  136. return new TypeVariable(aFormalTypeParameter.identifier, upperBound, ifBounds);
  137. }
  138. private static ResolvedType typeArgument2TypeX(GenericSignature.TypeArgument aTypeArgument,
  139. GenericSignature.FormalTypeParameter[] typeParams, World world,
  140. Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
  141. throws GenericSignatureFormatException {
  142. if (aTypeArgument.isWildcard) {
  143. return UnresolvedType.SOMETHING.resolve(world);
  144. }
  145. if (aTypeArgument.isMinus) {
  146. UnresolvedType bound = fieldTypeSignature2TypeX(aTypeArgument.signature, typeParams, world,
  147. inProgressTypeVariableResolutions);
  148. ResolvedType resolvedBound = world.resolve(bound);
  149. if (resolvedBound.isMissing()) {
  150. world.getLint().cantFindType.signal("Unable to find type (for bound): " + resolvedBound.getName(), null);
  151. resolvedBound = world.resolve(UnresolvedType.OBJECT);
  152. }
  153. ReferenceType rBound = (ReferenceType) resolvedBound;
  154. return new BoundedReferenceType(rBound, false, world);
  155. } else if (aTypeArgument.isPlus) {
  156. UnresolvedType bound = fieldTypeSignature2TypeX(aTypeArgument.signature, typeParams, world,
  157. inProgressTypeVariableResolutions);
  158. ResolvedType resolvedBound = world.resolve(bound);
  159. if (resolvedBound.isMissing()) {
  160. world.getLint().cantFindType.signal("Unable to find type (for bound): " + resolvedBound.getName(), null);
  161. resolvedBound = world.resolve(UnresolvedType.OBJECT);
  162. }
  163. ReferenceType rBound = (ReferenceType) resolvedBound;
  164. return new BoundedReferenceType(rBound, true, world);
  165. } else {
  166. return fieldTypeSignature2TypeX(aTypeArgument.signature, typeParams, world, inProgressTypeVariableResolutions);
  167. }
  168. }
  169. public static ResolvedType typeSignature2TypeX(GenericSignature.TypeSignature aTypeSig,
  170. GenericSignature.FormalTypeParameter[] typeParams, World world) throws GenericSignatureFormatException {
  171. Map<GenericSignature.FormalTypeParameter, ReferenceType> typeMap = new HashMap<>();
  172. ResolvedType ret = typeSignature2TypeX(aTypeSig, typeParams, world, typeMap);
  173. fixUpCircularDependencies(ret, typeMap);
  174. return ret;
  175. }
  176. private static ResolvedType typeSignature2TypeX(GenericSignature.TypeSignature aTypeSig,
  177. GenericSignature.FormalTypeParameter[] typeParams, World world,
  178. Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
  179. throws GenericSignatureFormatException {
  180. if (aTypeSig.isBaseType()) {
  181. return world.resolve(UnresolvedType.forSignature(((GenericSignature.BaseTypeSignature) aTypeSig).toString()));
  182. } else {
  183. return fieldTypeSignature2TypeX((GenericSignature.FieldTypeSignature) aTypeSig, typeParams, world,
  184. inProgressTypeVariableResolutions);
  185. }
  186. }
  187. private static ResolvedType typeVariableSignature2TypeX(GenericSignature.TypeVariableSignature aTypeVarSig,
  188. GenericSignature.FormalTypeParameter[] typeParams, World world,
  189. Map<GenericSignature.FormalTypeParameter, ReferenceType> inProgressTypeVariableResolutions)
  190. throws GenericSignatureFormatException {
  191. GenericSignature.FormalTypeParameter typeVarBounds = null;
  192. for (GenericSignature.FormalTypeParameter typeParam : typeParams) {
  193. if (typeParam.identifier.equals(aTypeVarSig.typeVariableName)) {
  194. typeVarBounds = typeParam;
  195. break;
  196. }
  197. }
  198. if (typeVarBounds == null) {
  199. // blowing up here breaks the situation with ITDs where the type variable is mentioned in the
  200. // declaring type and used somewhere in the signature. Temporary change to allow it to return just a
  201. // 'dumb' typevariablereference.
  202. return new TypeVariableReferenceType(new TypeVariable(aTypeVarSig.typeVariableName), world);
  203. // throw new GenericSignatureFormatException("Undeclared type variable in signature: " + aTypeVarSig.typeVariableName);
  204. }
  205. if (inProgressTypeVariableResolutions.containsKey(typeVarBounds)) {
  206. return inProgressTypeVariableResolutions.get(typeVarBounds);
  207. }
  208. inProgressTypeVariableResolutions.put(typeVarBounds, new FTPHolder(typeVarBounds, world));
  209. ReferenceType ret = new TypeVariableReferenceType(formalTypeParameter2TypeVariable(typeVarBounds, typeParams, world,
  210. inProgressTypeVariableResolutions), world);
  211. inProgressTypeVariableResolutions.put(typeVarBounds, ret);
  212. return ret;
  213. }
  214. private static void fixUpCircularDependencies(ResolvedType aTypeX,
  215. Map<GenericSignature.FormalTypeParameter, ReferenceType> typeVariableResolutions) {
  216. if (!(aTypeX instanceof ReferenceType)) {
  217. return;
  218. }
  219. ReferenceType rt = (ReferenceType) aTypeX;
  220. TypeVariable[] typeVars = rt.getTypeVariables();
  221. if (typeVars != null) {
  222. for (TypeVariable typeVar : typeVars) {
  223. if (typeVar.getUpperBound() instanceof FTPHolder) {
  224. GenericSignature.FormalTypeParameter key = ((FTPHolder) typeVar.getUpperBound()).ftpToBeSubstituted;
  225. typeVar.setUpperBound(typeVariableResolutions.get(key));
  226. }
  227. }
  228. }
  229. }
  230. private static class FTPHolder extends ReferenceType {
  231. public GenericSignature.FormalTypeParameter ftpToBeSubstituted;
  232. public FTPHolder(GenericSignature.FormalTypeParameter ftp, World world) {
  233. super("Ljava/lang/Object;", world);
  234. this.ftpToBeSubstituted = ftp;
  235. }
  236. public String toString() {
  237. return "placeholder for TypeVariable of " + ftpToBeSubstituted.toString();
  238. }
  239. public ResolvedType resolve(World world) {
  240. return this;
  241. }
  242. public boolean isCacheable() {
  243. return false;
  244. }
  245. }
  246. public static class GenericSignatureFormatException extends Exception {
  247. public GenericSignatureFormatException(String explanation) {
  248. super(explanation);
  249. }
  250. }
  251. }