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.

TypePattern.java 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  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 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. * ******************************************************************/
  12. package org.aspectj.weaver.patterns;
  13. import java.io.DataOutputStream;
  14. import java.io.IOException;
  15. import java.lang.reflect.Modifier;
  16. import java.util.Iterator;
  17. import java.util.Map;
  18. import org.aspectj.bridge.MessageUtil;
  19. import org.aspectj.util.FuzzyBoolean;
  20. import org.aspectj.weaver.BCException;
  21. import org.aspectj.weaver.ISourceContext;
  22. import org.aspectj.weaver.IntMap;
  23. import org.aspectj.weaver.ResolvedType;
  24. import org.aspectj.weaver.TypeVariableReference;
  25. import org.aspectj.weaver.UnresolvedType;
  26. import org.aspectj.weaver.VersionedDataInputStream;
  27. import org.aspectj.weaver.WeaverMessages;
  28. import org.aspectj.weaver.World;
  29. /**
  30. * On creation, type pattern only contains WildTypePattern nodes, not BindingType or ExactType.
  31. *
  32. * <p>Then we call resolveBindings() during compilation
  33. * During concretization of enclosing pointcuts, we call remapAdviceFormals
  34. *
  35. * @author Erik Hilsdale
  36. * @author Jim Hugunin
  37. */
  38. public abstract class TypePattern extends PatternNode {
  39. public static class MatchKind {
  40. private String name;
  41. public MatchKind(String name) { this.name = name; }
  42. public String toString() { return name; }
  43. }
  44. public static final MatchKind STATIC = new MatchKind("STATIC");
  45. public static final MatchKind DYNAMIC = new MatchKind("DYNAMIC");
  46. public static final TypePattern ELLIPSIS = new EllipsisTypePattern();
  47. public static final TypePattern ANY = new AnyTypePattern();
  48. public static final TypePattern NO = new NoTypePattern();
  49. protected boolean includeSubtypes;
  50. protected boolean isVarArgs = false;
  51. protected AnnotationTypePattern annotationPattern = AnnotationTypePattern.ANY;
  52. protected TypePatternList typeParameters = TypePatternList.EMPTY;
  53. protected TypePattern(boolean includeSubtypes,boolean isVarArgs,TypePatternList typeParams) {
  54. this.includeSubtypes = includeSubtypes;
  55. this.isVarArgs = isVarArgs;
  56. this.typeParameters = (typeParams == null ? TypePatternList.EMPTY : typeParams);
  57. }
  58. protected TypePattern(boolean includeSubtypes, boolean isVarArgs) {
  59. this(includeSubtypes,isVarArgs,null);
  60. }
  61. public AnnotationTypePattern getAnnotationPattern() {
  62. return annotationPattern;
  63. }
  64. public boolean isVarArgs() {
  65. return isVarArgs;
  66. }
  67. public boolean isStarAnnotation() {
  68. return annotationPattern == AnnotationTypePattern.ANY;
  69. }
  70. public boolean isArray() {
  71. return false;
  72. }
  73. protected TypePattern(boolean includeSubtypes) {
  74. this(includeSubtypes,false);
  75. }
  76. public void setAnnotationTypePattern(AnnotationTypePattern annPatt) {
  77. this.annotationPattern = annPatt;
  78. }
  79. public void setTypeParameters(TypePatternList typeParams) {
  80. this.typeParameters = typeParams;
  81. }
  82. public TypePatternList getTypeParameters() {
  83. return this.typeParameters;
  84. }
  85. public void setIsVarArgs(boolean isVarArgs) {
  86. this.isVarArgs = isVarArgs;
  87. }
  88. // answer conservatively...
  89. protected boolean couldEverMatchSameTypesAs(TypePattern other) {
  90. if (this.includeSubtypes || other.includeSubtypes) return true;
  91. if (this.annotationPattern != AnnotationTypePattern.ANY) return true;
  92. if (other.annotationPattern != AnnotationTypePattern.ANY) return true;
  93. return false;
  94. }
  95. //XXX non-final for Not, && and ||
  96. public boolean matchesStatically(ResolvedType type) {
  97. if (includeSubtypes) {
  98. return matchesSubtypes(type);
  99. } else {
  100. return matchesExactly(type);
  101. }
  102. }
  103. public abstract FuzzyBoolean matchesInstanceof(ResolvedType type);
  104. public final FuzzyBoolean matches(ResolvedType type, MatchKind kind) {
  105. FuzzyBoolean typeMatch = null;
  106. //??? This is part of gracefully handling missing references
  107. if (type.isMissing()) return FuzzyBoolean.NO;
  108. if (kind == STATIC) {
  109. // typeMatch = FuzzyBoolean.fromBoolean(matchesStatically(type));
  110. // return typeMatch.and(annotationPattern.matches(type));
  111. return FuzzyBoolean.fromBoolean(matchesStatically(type));
  112. } else if (kind == DYNAMIC) {
  113. //System.err.println("matching: " + this + " with " + type);
  114. // typeMatch = matchesInstanceof(type);
  115. //System.err.println(" got: " + ret);
  116. // return typeMatch.and(annotationPattern.matches(type));
  117. return matchesInstanceof(type);
  118. } else {
  119. throw new IllegalArgumentException("kind must be DYNAMIC or STATIC");
  120. }
  121. }
  122. protected abstract boolean matchesExactly(ResolvedType type);
  123. protected abstract boolean matchesExactly(ResolvedType type, ResolvedType annotatedType);
  124. protected boolean matchesSubtypes(ResolvedType type) {
  125. //System.out.println("matching: " + this + " to " + type);
  126. if (matchesExactly(type)) {
  127. //System.out.println(" true");
  128. return true;
  129. }
  130. // pr124808
  131. Iterator typesIterator = null;
  132. if (type.isTypeVariableReference()) {
  133. typesIterator = ((TypeVariableReference)type).getTypeVariable().getFirstBound().resolve(type.getWorld()).getDirectSupertypes();
  134. } else {
  135. // pr223605
  136. if (type.isRawType()) {
  137. type = type.getGenericType();
  138. }
  139. typesIterator = type.getDirectSupertypes();
  140. }
  141. // FuzzyBoolean ret = FuzzyBoolean.NO; // ??? -eh
  142. for (Iterator i = typesIterator; i.hasNext(); ) {
  143. ResolvedType superType = (ResolvedType)i.next();
  144. // TODO asc generics, temporary whilst matching isnt aware..
  145. //if (superType.isParameterizedType()) superType = superType.getRawType().resolve(superType.getWorld());
  146. if (matchesSubtypes(superType,type)) return true;
  147. }
  148. return false;
  149. }
  150. protected boolean matchesSubtypes(ResolvedType superType, ResolvedType annotatedType) {
  151. //System.out.println("matching: " + this + " to " + type);
  152. if (matchesExactly(superType,annotatedType)) {
  153. //System.out.println(" true");
  154. return true;
  155. }
  156. // FuzzyBoolean ret = FuzzyBoolean.NO; // ??? -eh
  157. for (Iterator i = superType.getDirectSupertypes(); i.hasNext(); ) {
  158. ResolvedType superSuperType = (ResolvedType)i.next();
  159. if (matchesSubtypes(superSuperType,annotatedType)) return true;
  160. }
  161. return false;
  162. }
  163. public UnresolvedType resolveExactType(IScope scope, Bindings bindings) {
  164. TypePattern p = resolveBindings(scope, bindings, false, true);
  165. if (!(p instanceof ExactTypePattern)) return ResolvedType.MISSING;
  166. return ((ExactTypePattern)p).getType();
  167. }
  168. public UnresolvedType getExactType() {
  169. if (this instanceof ExactTypePattern) return ((ExactTypePattern)this).getType();
  170. else return ResolvedType.MISSING;
  171. }
  172. protected TypePattern notExactType(IScope s) {
  173. s.getMessageHandler().handleMessage(MessageUtil.error(
  174. WeaverMessages.format(WeaverMessages.EXACT_TYPE_PATTERN_REQD), getSourceLocation()));
  175. return NO;
  176. }
  177. // public boolean assertExactType(IMessageHandler m) {
  178. // if (this instanceof ExactTypePattern) return true;
  179. //
  180. // //XXX should try harder to avoid multiple errors for one problem
  181. // m.handleMessage(MessageUtil.error("exact type pattern required", getSourceLocation()));
  182. // return false;
  183. // }
  184. /**
  185. * This can modify in place, or return a new TypePattern if the type changes.
  186. */
  187. public TypePattern resolveBindings(IScope scope, Bindings bindings,
  188. boolean allowBinding, boolean requireExactType)
  189. {
  190. annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding);
  191. return this;
  192. }
  193. public void resolve(World world) {
  194. annotationPattern.resolve(world);
  195. }
  196. /**
  197. * return a version of this type pattern in which all type variable references have been
  198. * replaced by their corresponding entry in the map.
  199. */
  200. public abstract TypePattern parameterizeWith(Map typeVariableMap,World w);
  201. public void postRead(ResolvedType enclosingType) {
  202. }
  203. public boolean isStar() {
  204. return false;
  205. }
  206. /**
  207. * This is called during concretization of pointcuts, it is used by BindingTypePattern
  208. * to return a new BindingTypePattern with a formal index appropiate for the advice,
  209. * rather than for the lexical declaration, i.e. this handles transforamtions through
  210. * named pointcuts.
  211. * <pre>
  212. * pointcut foo(String name): args(name);
  213. * --&gt; This makes a BindingTypePattern(0) pointing to the 0th formal
  214. *
  215. * before(Foo f, String n): this(f) && foo(n) { ... }
  216. * --&gt; when resolveReferences is called on the args from the above, it
  217. * will return a BindingTypePattern(1)
  218. *
  219. * before(Foo f): this(f) && foo(*) { ... }
  220. * --&gt; when resolveReferences is called on the args from the above, it
  221. * will return an ExactTypePattern(String)
  222. * </pre>
  223. */
  224. public TypePattern remapAdviceFormals(IntMap bindings) {
  225. return this;
  226. }
  227. public static final byte WILD = 1;
  228. public static final byte EXACT = 2;
  229. public static final byte BINDING = 3;
  230. public static final byte ELLIPSIS_KEY = 4;
  231. public static final byte ANY_KEY = 5;
  232. public static final byte NOT = 6;
  233. public static final byte OR = 7;
  234. public static final byte AND = 8;
  235. public static final byte NO_KEY = 9;
  236. public static final byte ANY_WITH_ANNO = 10;
  237. public static final byte HAS_MEMBER = 11;
  238. public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  239. byte key = s.readByte();
  240. switch(key) {
  241. case WILD: return WildTypePattern.read(s, context);
  242. case EXACT: return ExactTypePattern.read(s, context);
  243. case BINDING: return BindingTypePattern.read(s, context);
  244. case ELLIPSIS_KEY: return ELLIPSIS;
  245. case ANY_KEY: return ANY;
  246. case NO_KEY: return NO;
  247. case NOT: return NotTypePattern.read(s, context);
  248. case OR: return OrTypePattern.read(s, context);
  249. case AND: return AndTypePattern.read(s, context);
  250. case ANY_WITH_ANNO: return AnyWithAnnotationTypePattern.read(s,context);
  251. case HAS_MEMBER: return HasMemberTypePattern.read(s,context);
  252. }
  253. throw new BCException("unknown TypePattern kind: " + key);
  254. }
  255. public boolean isIncludeSubtypes() {
  256. return includeSubtypes;
  257. }
  258. }
  259. class EllipsisTypePattern extends TypePattern {
  260. /**
  261. * Constructor for EllipsisTypePattern.
  262. * @param includeSubtypes
  263. */
  264. public EllipsisTypePattern() {
  265. super(false,false,new TypePatternList());
  266. }
  267. /* (non-Javadoc)
  268. * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
  269. */
  270. protected boolean couldEverMatchSameTypesAs(TypePattern other) {
  271. return true;
  272. }
  273. /**
  274. * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
  275. */
  276. protected boolean matchesExactly(ResolvedType type) {
  277. return false;
  278. }
  279. protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
  280. return false;
  281. }
  282. /**
  283. * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
  284. */
  285. public FuzzyBoolean matchesInstanceof(ResolvedType type) {
  286. return FuzzyBoolean.NO;
  287. }
  288. /**
  289. * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
  290. */
  291. public void write(DataOutputStream s) throws IOException {
  292. s.writeByte(ELLIPSIS_KEY);
  293. }
  294. public String toString() { return ".."; }
  295. /* (non-Javadoc)
  296. * @see java.lang.Object#equals(java.lang.Object)
  297. */
  298. public boolean equals(Object obj) {
  299. return (obj instanceof EllipsisTypePattern);
  300. }
  301. /* (non-Javadoc)
  302. * @see java.lang.Object#hashCode()
  303. */
  304. public int hashCode() {
  305. return 17 * 37;
  306. }
  307. public Object accept(PatternNodeVisitor visitor, Object data) {
  308. return visitor.visit(this, data);
  309. }
  310. public TypePattern parameterizeWith(Map typeVariableMap,World w) {
  311. return this;
  312. }
  313. }
  314. class AnyTypePattern extends TypePattern {
  315. /**
  316. * Constructor for EllipsisTypePattern.
  317. * @param includeSubtypes
  318. */
  319. public AnyTypePattern() {
  320. super(false,false,new TypePatternList());
  321. }
  322. /* (non-Javadoc)
  323. * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
  324. */
  325. protected boolean couldEverMatchSameTypesAs(TypePattern other) {
  326. return true;
  327. }
  328. /**
  329. * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
  330. */
  331. protected boolean matchesExactly(ResolvedType type) {
  332. return true;
  333. }
  334. protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
  335. return true;
  336. }
  337. /**
  338. * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
  339. */
  340. public FuzzyBoolean matchesInstanceof(ResolvedType type) {
  341. return FuzzyBoolean.YES;
  342. }
  343. /**
  344. * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
  345. */
  346. public void write(DataOutputStream s) throws IOException {
  347. s.writeByte(ANY_KEY);
  348. }
  349. /**
  350. * @see org.aspectj.weaver.patterns.TypePattern#matches(IType, MatchKind)
  351. */
  352. // public FuzzyBoolean matches(IType type, MatchKind kind) {
  353. // return FuzzyBoolean.YES;
  354. // }
  355. /**
  356. * @see org.aspectj.weaver.patterns.TypePattern#matchesSubtypes(IType)
  357. */
  358. protected boolean matchesSubtypes(ResolvedType type) {
  359. return true;
  360. }
  361. public boolean isStar() {
  362. return true;
  363. }
  364. public String toString() { return "*"; }
  365. public boolean equals(Object obj) {
  366. return (obj instanceof AnyTypePattern);
  367. }
  368. public int hashCode() {
  369. return 37;
  370. }
  371. public Object accept(PatternNodeVisitor visitor, Object data) {
  372. return visitor.visit(this, data);
  373. }
  374. public TypePattern parameterizeWith(Map arg0,World w) {
  375. return this;
  376. }
  377. }
  378. /**
  379. * This type represents a type pattern of '*' but with an annotation specified,
  380. * e.g. '@Color *'
  381. */
  382. class AnyWithAnnotationTypePattern extends TypePattern {
  383. public AnyWithAnnotationTypePattern(AnnotationTypePattern atp) {
  384. super(false,false);
  385. annotationPattern = atp;
  386. }
  387. public Object accept(PatternNodeVisitor visitor, Object data) {
  388. return visitor.visit(this,data);
  389. }
  390. protected boolean couldEverMatchSameTypesAs(TypePattern other) {
  391. return true;
  392. }
  393. protected boolean matchesExactly(ResolvedType type) {
  394. annotationPattern.resolve(type.getWorld());
  395. boolean b = false;
  396. if (type.temporaryAnnotationTypes!=null) {
  397. b = annotationPattern.matches(type,type.temporaryAnnotationTypes).alwaysTrue();
  398. } else {
  399. b = annotationPattern.matches(type).alwaysTrue();
  400. }
  401. return b;
  402. }
  403. protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
  404. annotationPattern.resolve(type.getWorld());
  405. return annotationPattern.matches(annotatedType).alwaysTrue();
  406. }
  407. public FuzzyBoolean matchesInstanceof(ResolvedType type) {
  408. if (Modifier.isFinal(type.getModifiers())) {
  409. return FuzzyBoolean.fromBoolean(matchesExactly(type));
  410. }
  411. return FuzzyBoolean.MAYBE;
  412. }
  413. public TypePattern parameterizeWith(Map typeVariableMap,World w) {
  414. AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(this.annotationPattern.parameterizeWith(typeVariableMap,w));
  415. ret.copyLocationFrom(this);
  416. return ret;
  417. }
  418. public void write(DataOutputStream s) throws IOException {
  419. s.writeByte(TypePattern.ANY_WITH_ANNO);
  420. annotationPattern.write(s);
  421. writeLocation(s);
  422. }
  423. public static TypePattern read(VersionedDataInputStream s,ISourceContext c) throws IOException {
  424. AnnotationTypePattern annPatt = AnnotationTypePattern.read(s,c);
  425. AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(annPatt);
  426. ret.readLocation(c, s);
  427. return ret;
  428. }
  429. // public FuzzyBoolean matches(IType type, MatchKind kind) {
  430. // return FuzzyBoolean.YES;
  431. // }
  432. protected boolean matchesSubtypes(ResolvedType type) {
  433. return true;
  434. }
  435. public boolean isStar() {
  436. return false;
  437. }
  438. public String toString() { return annotationPattern+" *"; }
  439. public boolean equals(Object obj) {
  440. if (!(obj instanceof AnyWithAnnotationTypePattern)) return false;
  441. AnyWithAnnotationTypePattern awatp = (AnyWithAnnotationTypePattern) obj;
  442. return (annotationPattern.equals(awatp.annotationPattern));
  443. }
  444. public int hashCode() {
  445. return annotationPattern.hashCode();
  446. }
  447. }
  448. class NoTypePattern extends TypePattern {
  449. public NoTypePattern() {
  450. super(false,false,new TypePatternList());
  451. }
  452. /* (non-Javadoc)
  453. * @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
  454. */
  455. protected boolean couldEverMatchSameTypesAs(TypePattern other) {
  456. return false;
  457. }
  458. /**
  459. * @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
  460. */
  461. protected boolean matchesExactly(ResolvedType type) {
  462. return false;
  463. }
  464. protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
  465. return false;
  466. }
  467. /**
  468. * @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
  469. */
  470. public FuzzyBoolean matchesInstanceof(ResolvedType type) {
  471. return FuzzyBoolean.NO;
  472. }
  473. /**
  474. * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
  475. */
  476. public void write(DataOutputStream s) throws IOException {
  477. s.writeByte(NO_KEY);
  478. }
  479. /**
  480. * @see org.aspectj.weaver.patterns.TypePattern#matches(IType, MatchKind)
  481. */
  482. // public FuzzyBoolean matches(IType type, MatchKind kind) {
  483. // return FuzzyBoolean.YES;
  484. // }
  485. /**
  486. * @see org.aspectj.weaver.patterns.TypePattern#matchesSubtypes(IType)
  487. */
  488. protected boolean matchesSubtypes(ResolvedType type) {
  489. return false;
  490. }
  491. public boolean isStar() {
  492. return false;
  493. }
  494. public String toString() { return "<nothing>"; }//FIXME AV - bad! toString() cannot be parsed back (not idempotent)
  495. /* (non-Javadoc)
  496. * @see java.lang.Object#equals(java.lang.Object)
  497. */
  498. public boolean equals(Object obj) {
  499. return (obj instanceof NoTypePattern);
  500. }
  501. /* (non-Javadoc)
  502. * @see java.lang.Object#hashCode()
  503. */
  504. public int hashCode() {
  505. return 17 * 37 * 37;
  506. }
  507. public Object accept(PatternNodeVisitor visitor, Object data) {
  508. return visitor.visit(this, data);
  509. }
  510. public TypePattern parameterizeWith(Map arg0,World w) {
  511. return this;
  512. }
  513. }