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.

ExactTypePattern.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  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. * ******************************************************************/
  12. package org.aspectj.weaver.patterns;
  13. import java.io.DataInputStream;
  14. import java.io.IOException;
  15. import java.util.HashMap;
  16. import java.util.Map;
  17. import org.aspectj.util.FuzzyBoolean;
  18. import org.aspectj.weaver.AjAttribute;
  19. import org.aspectj.weaver.BCException;
  20. import org.aspectj.weaver.CompressingDataOutputStream;
  21. import org.aspectj.weaver.ISourceContext;
  22. import org.aspectj.weaver.ResolvedType;
  23. import org.aspectj.weaver.TypeVariableReference;
  24. import org.aspectj.weaver.TypeVariableReferenceType;
  25. import org.aspectj.weaver.UnresolvedType;
  26. import org.aspectj.weaver.VersionedDataInputStream;
  27. import org.aspectj.weaver.World;
  28. public class ExactTypePattern extends TypePattern {
  29. protected UnresolvedType type;
  30. protected transient ResolvedType resolvedType;
  31. public boolean checked = false;
  32. public boolean isVoid = false;
  33. public static final Map<String, Class<?>> primitiveTypesMap;
  34. public static final Map<String, Class<?>> boxedPrimitivesMap;
  35. private static final Map<String, Class<?>> boxedTypesMap;
  36. static {
  37. primitiveTypesMap = new HashMap<>();
  38. primitiveTypesMap.put("int", int.class);
  39. primitiveTypesMap.put("short", short.class);
  40. primitiveTypesMap.put("long", long.class);
  41. primitiveTypesMap.put("byte", byte.class);
  42. primitiveTypesMap.put("char", char.class);
  43. primitiveTypesMap.put("float", float.class);
  44. primitiveTypesMap.put("double", double.class);
  45. boxedPrimitivesMap = new HashMap<>();
  46. boxedPrimitivesMap.put("java.lang.Integer", Integer.class);
  47. boxedPrimitivesMap.put("java.lang.Short", Short.class);
  48. boxedPrimitivesMap.put("java.lang.Long", Long.class);
  49. boxedPrimitivesMap.put("java.lang.Byte", Byte.class);
  50. boxedPrimitivesMap.put("java.lang.Character", Character.class);
  51. boxedPrimitivesMap.put("java.lang.Float", Float.class);
  52. boxedPrimitivesMap.put("java.lang.Double", Double.class);
  53. boxedTypesMap = new HashMap<>();
  54. boxedTypesMap.put("int", Integer.class);
  55. boxedTypesMap.put("short", Short.class);
  56. boxedTypesMap.put("long", Long.class);
  57. boxedTypesMap.put("byte", Byte.class);
  58. boxedTypesMap.put("char", Character.class);
  59. boxedTypesMap.put("float", Float.class);
  60. boxedTypesMap.put("double", Double.class);
  61. }
  62. @Override
  63. protected boolean matchesSubtypes(ResolvedType type) {
  64. boolean match = super.matchesSubtypes(type);
  65. if (match) {
  66. return match;
  67. }
  68. // are we dealing with array funkyness - pattern might be jlObject[]+ and type jlString[]
  69. if (type.isArray() && this.type.isArray()) {
  70. ResolvedType componentType = type.getComponentType().resolve(type.getWorld());
  71. UnresolvedType newPatternType = this.type.getComponentType();
  72. ExactTypePattern etp = new ExactTypePattern(newPatternType, includeSubtypes, false, typeParameters);
  73. return etp.matchesSubtypes(componentType, type);
  74. }
  75. return match;
  76. }
  77. public ExactTypePattern(UnresolvedType type, boolean includeSubtypes, boolean isVarArgs, TypePatternList typeParams) {
  78. super(includeSubtypes, isVarArgs, typeParams);
  79. this.type = type;
  80. }
  81. @Override
  82. public boolean isArray() {
  83. return type.isArray();
  84. }
  85. public int getDimensions() {
  86. return type.getDimensions();
  87. }
  88. /*
  89. * (non-Javadoc)
  90. *
  91. * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
  92. */
  93. @Override
  94. protected boolean couldEverMatchSameTypesAs(TypePattern other) {
  95. if (super.couldEverMatchSameTypesAs(other)) {
  96. return true;
  97. }
  98. // false is necessary but not sufficient
  99. UnresolvedType otherType = other.getExactType();
  100. if (!ResolvedType.isMissing(otherType)) {
  101. return type.equals(otherType);
  102. }
  103. if (other instanceof WildTypePattern) {
  104. WildTypePattern owtp = (WildTypePattern) other;
  105. String yourSimpleNamePrefix = owtp.getNamePatterns()[0].maybeGetSimpleName();
  106. if (yourSimpleNamePrefix != null) {
  107. return (type.getName().startsWith(yourSimpleNamePrefix));
  108. }
  109. }
  110. return true;
  111. }
  112. @Override
  113. protected boolean matchesExactly(ResolvedType matchType) {
  114. if (!matchesArray(matchType)) {
  115. return false;
  116. }
  117. boolean typeMatch = this.type.equals(matchType);
  118. if (!typeMatch && (matchType.isParameterizedType() || matchType.isGenericType())) {
  119. typeMatch = this.type.equals(matchType.getRawType());
  120. }
  121. if (!typeMatch && matchType.isTypeVariableReference()) {
  122. typeMatch = matchesTypeVariable((TypeVariableReferenceType) matchType);
  123. }
  124. if (!typeMatch) {
  125. return false;
  126. }
  127. annotationPattern.resolve(matchType.getWorld());
  128. boolean annMatch = false;
  129. if (matchType.temporaryAnnotationTypes != null) {
  130. annMatch = annotationPattern.matches(matchType, matchType.temporaryAnnotationTypes).alwaysTrue();
  131. } else {
  132. annMatch = annotationPattern.matches(matchType).alwaysTrue();
  133. }
  134. return (typeMatch && annMatch);
  135. }
  136. private boolean matchesTypeVariable(TypeVariableReferenceType matchType) {
  137. // was this method previously coded to return false *on purpose* ?? pr124808
  138. return this.type.equals(((TypeVariableReference) matchType).getTypeVariable().getFirstBound());
  139. // return false;
  140. }
  141. @Override
  142. protected boolean matchesExactly(ResolvedType matchType, ResolvedType annotatedType) {
  143. if (!matchesArray(matchType)) {
  144. return false;
  145. }
  146. boolean typeMatch = this.type.equals(matchType);
  147. if (!typeMatch && (matchType.isParameterizedType() || matchType.isGenericType())) {
  148. typeMatch = this.type.equals(matchType.getRawType());
  149. }
  150. if (!typeMatch && matchType.isTypeVariableReference()) {
  151. typeMatch = matchesTypeVariable((TypeVariableReferenceType) matchType);
  152. }
  153. annotationPattern.resolve(matchType.getWorld());
  154. boolean annMatch = false;
  155. if (annotatedType.temporaryAnnotationTypes != null) {
  156. annMatch = annotationPattern.matches(annotatedType, annotatedType.temporaryAnnotationTypes).alwaysTrue();
  157. } else {
  158. annMatch = annotationPattern.matches(annotatedType).alwaysTrue();
  159. }
  160. return (typeMatch && annMatch);
  161. }
  162. @Override
  163. protected boolean matchesArray(UnresolvedType type) {
  164. return type.getDimensions() == getDimensions();
  165. }
  166. public UnresolvedType getType() {
  167. return type;
  168. }
  169. public ResolvedType getResolvedExactType(World world) {
  170. if (resolvedType == null) {
  171. resolvedType = world.resolve(type);
  172. }
  173. return resolvedType;
  174. }
  175. @Override
  176. public boolean isVoid() {
  177. if (!checked) {
  178. isVoid = this.type.getSignature().equals("V");
  179. checked = true;
  180. }
  181. return isVoid;
  182. }
  183. // true if (matchType instanceof this.type)
  184. @Override
  185. public FuzzyBoolean matchesInstanceof(ResolvedType matchType) {
  186. // in our world, Object is assignable from anything
  187. annotationPattern.resolve(matchType.getWorld());
  188. if (type.equals(ResolvedType.OBJECT)) {
  189. return FuzzyBoolean.YES.and(annotationPattern.matches(matchType));
  190. }
  191. ResolvedType resolvedType = type.resolve(matchType.getWorld());
  192. if (resolvedType.isAssignableFrom(matchType)) {
  193. return FuzzyBoolean.YES.and(annotationPattern.matches(matchType));
  194. }
  195. // fix for PR 64262 - shouldn't try to coerce primitives
  196. if (type.isPrimitiveType()) {
  197. return FuzzyBoolean.NO;
  198. } else {
  199. return matchType.isCoerceableFrom(type.resolve(matchType.getWorld())) ? FuzzyBoolean.MAYBE : FuzzyBoolean.NO;
  200. }
  201. }
  202. @Override
  203. public boolean equals(Object other) {
  204. if (!(other instanceof ExactTypePattern)) {
  205. return false;
  206. }
  207. if (other instanceof BindingTypePattern) {
  208. return false;
  209. }
  210. ExactTypePattern o = (ExactTypePattern) other;
  211. if (includeSubtypes != o.includeSubtypes) {
  212. return false;
  213. }
  214. if (isVarArgs != o.isVarArgs) {
  215. return false;
  216. }
  217. if (!typeParameters.equals(o.typeParameters)) {
  218. return false;
  219. }
  220. return (o.type.equals(this.type) && o.annotationPattern.equals(this.annotationPattern));
  221. }
  222. @Override
  223. public int hashCode() {
  224. int result = 17;
  225. result = 37 * result + type.hashCode();
  226. result = 37 * result + Boolean.valueOf(includeSubtypes).hashCode();
  227. result = 37 * result + Boolean.valueOf(isVarArgs).hashCode();
  228. result = 37 * result + typeParameters.hashCode();
  229. result = 37 * result + annotationPattern.hashCode();
  230. return result;
  231. }
  232. private static final byte EXACT_VERSION = 1; // rev if changed
  233. @Override
  234. public void write(CompressingDataOutputStream out) throws IOException {
  235. out.writeByte(TypePattern.EXACT);
  236. out.writeByte(EXACT_VERSION);
  237. out.writeCompressedSignature(type.getSignature());
  238. out.writeBoolean(includeSubtypes);
  239. out.writeBoolean(isVarArgs);
  240. annotationPattern.write(out);
  241. typeParameters.write(out);
  242. writeLocation(out);
  243. }
  244. public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  245. if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
  246. return readTypePattern150(s, context);
  247. } else {
  248. return readTypePatternOldStyle(s, context);
  249. }
  250. }
  251. public static TypePattern readTypePattern150(VersionedDataInputStream s, ISourceContext context) throws IOException {
  252. byte version = s.readByte();
  253. if (version > EXACT_VERSION) {
  254. throw new BCException("ExactTypePattern was written by a more recent version of AspectJ");
  255. }
  256. TypePattern ret = new ExactTypePattern(
  257. s.isAtLeast169() ? s.readSignatureAsUnresolvedType() : UnresolvedType.read(s),
  258. s.readBoolean(),
  259. s.readBoolean(),
  260. null // set null first, use 'setTypeParameters' below
  261. );
  262. ret.setAnnotationTypePattern(AnnotationTypePattern.read(s, context));
  263. ret.setTypeParameters(TypePatternList.read(s, context));
  264. ret.readLocation(context, s);
  265. return ret;
  266. }
  267. public static TypePattern readTypePatternOldStyle(DataInputStream s, ISourceContext context) throws IOException {
  268. TypePattern ret = new ExactTypePattern(UnresolvedType.read(s), s.readBoolean(), false, null);
  269. ret.readLocation(context, s);
  270. return ret;
  271. }
  272. @Override
  273. public String toString() {
  274. StringBuilder buff = new StringBuilder();
  275. if (annotationPattern != AnnotationTypePattern.ANY) {
  276. buff.append('(');
  277. buff.append(annotationPattern.toString());
  278. buff.append(' ');
  279. }
  280. String typeString = type.toString();
  281. if (isVarArgs) {
  282. typeString = typeString.substring(0, typeString.lastIndexOf('['));
  283. }
  284. buff.append(typeString);
  285. if (includeSubtypes) {
  286. buff.append('+');
  287. }
  288. if (isVarArgs) {
  289. buff.append("...");
  290. }
  291. if (annotationPattern != AnnotationTypePattern.ANY) {
  292. buff.append(')');
  293. }
  294. return buff.toString();
  295. }
  296. @Override
  297. public TypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
  298. throw new BCException("trying to re-resolve");
  299. }
  300. /**
  301. * return a version of this type pattern with all type variables references replaced by the corresponding entry in the map.
  302. */
  303. @Override
  304. public TypePattern parameterizeWith(Map<String,UnresolvedType> typeVariableMap, World w) {
  305. UnresolvedType newType = type;
  306. if (type.isTypeVariableReference()) {
  307. TypeVariableReference t = (TypeVariableReference) type;
  308. String key = t.getTypeVariable().getName();
  309. if (typeVariableMap.containsKey(key)) {
  310. newType = typeVariableMap.get(key);
  311. }
  312. } else if (type.isParameterizedType()) {
  313. newType = w.resolve(type).parameterize(typeVariableMap);
  314. }
  315. ExactTypePattern ret = new ExactTypePattern(newType, includeSubtypes, isVarArgs, typeParameters);
  316. ret.annotationPattern = annotationPattern.parameterizeWith(typeVariableMap, w);
  317. ret.copyLocationFrom(this);
  318. return ret;
  319. }
  320. @Override
  321. public Object accept(PatternNodeVisitor visitor, Object data) {
  322. return visitor.visit(this, data);
  323. }
  324. }