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.

KindedPointcut.java 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  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 static org.aspectj.util.FuzzyBoolean.MAYBE;
  14. import java.io.IOException;
  15. import java.util.Iterator;
  16. import java.util.Map;
  17. import org.aspectj.bridge.ISourceLocation;
  18. import org.aspectj.bridge.MessageUtil;
  19. import org.aspectj.util.FuzzyBoolean;
  20. import org.aspectj.weaver.Checker;
  21. import org.aspectj.weaver.CompressingDataOutputStream;
  22. import org.aspectj.weaver.ISourceContext;
  23. import org.aspectj.weaver.IntMap;
  24. import org.aspectj.weaver.Member;
  25. import org.aspectj.weaver.ResolvedMember;
  26. import org.aspectj.weaver.ResolvedType;
  27. import org.aspectj.weaver.Shadow;
  28. import org.aspectj.weaver.ShadowMunger;
  29. import org.aspectj.weaver.UnresolvedType;
  30. import org.aspectj.weaver.VersionedDataInputStream;
  31. import org.aspectj.weaver.WeaverMessages;
  32. import org.aspectj.weaver.World;
  33. import org.aspectj.weaver.ast.Literal;
  34. import org.aspectj.weaver.ast.Test;
  35. public class KindedPointcut extends Pointcut {
  36. Shadow.Kind kind;
  37. private SignaturePattern signature;
  38. private int matchKinds;
  39. private ShadowMunger munger = null; // only set after concretization
  40. public KindedPointcut(Shadow.Kind kind, SignaturePattern signature) {
  41. this.kind = kind;
  42. this.signature = signature;
  43. this.pointcutKind = KINDED;
  44. this.matchKinds = kind.bit;
  45. }
  46. public KindedPointcut(Shadow.Kind kind, SignaturePattern signature, ShadowMunger munger) {
  47. this(kind, signature);
  48. this.munger = munger;
  49. }
  50. public SignaturePattern getSignature() {
  51. return signature;
  52. }
  53. /*
  54. * (non-Javadoc)
  55. *
  56. * @see org.aspectj.weaver.patterns.Pointcut#couldMatchKinds()
  57. */
  58. @Override
  59. public int couldMatchKinds() {
  60. return matchKinds;
  61. }
  62. public boolean couldEverMatchSameJoinPointsAs(KindedPointcut other) {
  63. if (this.kind != other.kind) {
  64. return false;
  65. }
  66. String myName = signature.getName().maybeGetSimpleName();
  67. String yourName = other.signature.getName().maybeGetSimpleName();
  68. if (myName != null && yourName != null) {
  69. if (!myName.equals(yourName)) {
  70. return false;
  71. }
  72. }
  73. if (signature.getParameterTypes().ellipsisCount == 0) {
  74. if (other.signature.getParameterTypes().ellipsisCount == 0) {
  75. if (signature.getParameterTypes().getTypePatterns().length != other.signature.getParameterTypes().getTypePatterns().length) {
  76. return false;
  77. }
  78. }
  79. }
  80. return true;
  81. }
  82. @Override
  83. public FuzzyBoolean fastMatch(FastMatchInfo info) {
  84. // info.getKind()==null means all kinds
  85. if (info.getKind() != null) {
  86. if (info.getKind() != kind) {
  87. return FuzzyBoolean.NO;
  88. }
  89. }
  90. // KindedPointcut represents these join points:
  91. // method-execution/ctor-execution/method-call/ctor-call/field-get/field-set/advice-execution/static-initialization
  92. // initialization/pre-initialization
  93. // Check if the global fastmatch flag is on - the flag can be removed (and this made default) once it proves stable!
  94. if (info.world.optimizedMatching) {
  95. // For now, just consider MethodExecution and Initialization
  96. if ((kind == Shadow.MethodExecution || kind == Shadow.Initialization) && info.getKind() == null) {
  97. boolean fastMatchingOnAspect = info.getType().isAspect();
  98. // an Aspect may define ITDs, and although our signature declaring type pattern may not match on the
  99. // aspect, the ITDs may have a different signature as we iterate through the members of the aspect. Let's not
  100. // try and work through that here and just say MAYBE
  101. if (fastMatchingOnAspect) {
  102. return MAYBE;
  103. }
  104. // Aim here is to do the same test as is done for signature pattern declaring type pattern matching
  105. if (this.getSignature().isExactDeclaringTypePattern()) {
  106. ExactTypePattern typePattern = (ExactTypePattern) this.getSignature().getDeclaringType();
  107. // Interface checks are more expensive, they could be anywhere...
  108. ResolvedType patternExactType = typePattern.getResolvedExactType(info.world);
  109. if (patternExactType.isInterface()) {
  110. ResolvedType curr = info.getType();
  111. Iterator<ResolvedType> hierarchyWalker = curr.getHierarchy(true, true);
  112. boolean found = false;
  113. while (hierarchyWalker.hasNext()) {
  114. curr = hierarchyWalker.next();
  115. if (typePattern.matchesStatically(curr)) {
  116. found = true;
  117. break;
  118. }
  119. }
  120. if (!found) {
  121. return FuzzyBoolean.NO;
  122. }
  123. } else if (patternExactType.isClass()) {
  124. ResolvedType curr = info.getType();
  125. do {
  126. if (typePattern.matchesStatically(curr)) {
  127. break;
  128. }
  129. curr = curr.getSuperclass();
  130. } while (curr != null);
  131. if (curr == null) {
  132. return FuzzyBoolean.NO;
  133. }
  134. }
  135. } else if (this.getSignature().getDeclaringType() instanceof AnyWithAnnotationTypePattern) {
  136. // aim here is to say NO if the annotation is not possible in the hierarchy here
  137. ResolvedType type = info.getType();
  138. AnnotationTypePattern annotationTypePattern = ((AnyWithAnnotationTypePattern) getSignature().getDeclaringType())
  139. .getAnnotationPattern();
  140. if (annotationTypePattern instanceof ExactAnnotationTypePattern) {
  141. ExactAnnotationTypePattern exactAnnotationTypePattern = (ExactAnnotationTypePattern) annotationTypePattern;
  142. if (exactAnnotationTypePattern.getAnnotationValues() == null
  143. || exactAnnotationTypePattern.getAnnotationValues().size() == 0) {
  144. ResolvedType annotationType = exactAnnotationTypePattern.getAnnotationType().resolve(info.world);
  145. if (type.hasAnnotation(annotationType)) {
  146. return FuzzyBoolean.MAYBE;
  147. }
  148. if (annotationType.isInheritedAnnotation()) {
  149. // ok - we may be picking it up from further up the hierarchy (but only a super*class*)
  150. ResolvedType toMatchAgainst = type.getSuperclass();
  151. boolean found = false;
  152. while (toMatchAgainst != null) {
  153. if (toMatchAgainst.hasAnnotation(annotationType)) {
  154. found = true;
  155. break;
  156. }
  157. toMatchAgainst = toMatchAgainst.getSuperclass();
  158. }
  159. if (!found) {
  160. return FuzzyBoolean.NO;
  161. }
  162. } else {
  163. return FuzzyBoolean.NO;
  164. }
  165. }
  166. }
  167. }
  168. }
  169. }
  170. return FuzzyBoolean.MAYBE;
  171. }
  172. @Override
  173. protected FuzzyBoolean matchInternal(Shadow shadow) {
  174. if (shadow.getKind() != kind) {
  175. return FuzzyBoolean.NO;
  176. }
  177. if (shadow.getKind() == Shadow.SynchronizationLock && kind == Shadow.SynchronizationLock) {
  178. return FuzzyBoolean.YES;
  179. }
  180. if (shadow.getKind() == Shadow.SynchronizationUnlock && kind == Shadow.SynchronizationUnlock) {
  181. return FuzzyBoolean.YES;
  182. }
  183. if (!signature.matches(shadow.getMatchingSignature(), shadow.getIWorld(), this.kind == Shadow.MethodCall)) {
  184. if (kind == Shadow.MethodCall) {
  185. warnOnConfusingSig(shadow);
  186. // warnOnBridgeMethod(shadow);
  187. }
  188. return FuzzyBoolean.NO;
  189. }
  190. return FuzzyBoolean.YES;
  191. }
  192. // private void warnOnBridgeMethod(Shadow shadow) {
  193. // if (shadow.getIWorld().getLint().noJoinpointsForBridgeMethods.isEnabled()) {
  194. // ResolvedMember rm = shadow.getSignature().resolve(shadow.getIWorld());
  195. // if (rm!=null) {
  196. // int shadowModifiers = rm.getModifiers(); //shadow.getSignature().getModifiers(shadow.getIWorld());
  197. // if (ResolvedType.hasBridgeModifier(shadowModifiers)) {
  198. // shadow.getIWorld().getLint().noJoinpointsForBridgeMethods.signal(new String[]{},getSourceLocation(),
  199. // new ISourceLocation[]{shadow.getSourceLocation()});
  200. // }
  201. // }
  202. // }
  203. // }
  204. private void warnOnConfusingSig(Shadow shadow) {
  205. // Don't do all this processing if we don't need to !
  206. if (!shadow.getIWorld().getLint().unmatchedSuperTypeInCall.isEnabled()) {
  207. return;
  208. }
  209. // no warnings for declare error/warning
  210. if (munger instanceof Checker) {
  211. return;
  212. }
  213. World world = shadow.getIWorld();
  214. // warning never needed if the declaring type is any
  215. UnresolvedType exactDeclaringType = signature.getDeclaringType().getExactType();
  216. ResolvedType shadowDeclaringType = shadow.getSignature().getDeclaringType().resolve(world);
  217. if (signature.getDeclaringType().isStar() || ResolvedType.isMissing(exactDeclaringType)
  218. || exactDeclaringType.resolve(world).isMissing()) {
  219. return;
  220. }
  221. // warning not needed if match type couldn't ever be the declaring type
  222. if (!shadowDeclaringType.isAssignableFrom(exactDeclaringType.resolve(world))) {
  223. return;
  224. }
  225. // if the method in the declaring type is *not* visible to the
  226. // exact declaring type then warning not needed.
  227. ResolvedMember rm = shadow.getSignature().resolve(world);
  228. // rm can be null in the case where we are binary weaving, and looking at a class with a call to a method in another class,
  229. // but because of class incompatibilities, the method does not exist on the target class anymore.
  230. // this will be reported elsewhere.
  231. if (rm == null) {
  232. return;
  233. }
  234. int shadowModifiers = rm.getModifiers();
  235. if (!ResolvedType.isVisible(shadowModifiers, shadowDeclaringType, exactDeclaringType.resolve(world))) {
  236. return;
  237. }
  238. if (!signature.getReturnType().matchesStatically(shadow.getSignature().getReturnType().resolve(world))) {
  239. // Covariance issue...
  240. // The reason we didn't match is that the type pattern for the pointcut (Car) doesn't match the
  241. // return type for the specific declaration at the shadow. (FastCar Sub.getCar())
  242. // XXX Put out another XLINT in this case?
  243. return;
  244. }
  245. // PR60015 - Don't report the warning if the declaring type is object and 'this' is an interface
  246. if (exactDeclaringType.resolve(world).isInterface() && shadowDeclaringType.equals(world.resolve("java.lang.Object"))) {
  247. return;
  248. }
  249. SignaturePattern nonConfusingPattern = new SignaturePattern(signature.getKind(), signature.getModifiers(),
  250. signature.getReturnType(), TypePattern.ANY, signature.getName(), signature.getParameterTypes(),
  251. signature.getThrowsPattern(), signature.getAnnotationPattern());
  252. if (nonConfusingPattern.matches(shadow.getSignature(), shadow.getIWorld(), true)) {
  253. shadow.getIWorld().getLint().unmatchedSuperTypeInCall.signal(new String[] {
  254. shadow.getSignature().getDeclaringType().toString(), signature.getDeclaringType().toString() },
  255. this.getSourceLocation(), new ISourceLocation[] { shadow.getSourceLocation() });
  256. }
  257. }
  258. @Override
  259. public boolean equals(Object other) {
  260. if (!(other instanceof KindedPointcut)) {
  261. return false;
  262. }
  263. KindedPointcut o = (KindedPointcut) other;
  264. return o.kind == this.kind && o.signature.equals(this.signature);
  265. }
  266. @Override
  267. public int hashCode() {
  268. int result = 17;
  269. result = 37 * result + kind.hashCode();
  270. result = 37 * result + signature.hashCode();
  271. return result;
  272. }
  273. @Override
  274. public String toString() {
  275. StringBuffer buf = new StringBuffer();
  276. buf.append(kind.getSimpleName());
  277. buf.append("(");
  278. buf.append(signature.toString());
  279. buf.append(")");
  280. return buf.toString();
  281. }
  282. @Override
  283. public void postRead(ResolvedType enclosingType) {
  284. signature.postRead(enclosingType);
  285. }
  286. @Override
  287. public void write(CompressingDataOutputStream s) throws IOException {
  288. s.writeByte(Pointcut.KINDED);
  289. kind.write(s);
  290. signature.write(s);
  291. writeLocation(s);
  292. }
  293. public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  294. Shadow.Kind kind = Shadow.Kind.read(s);
  295. SignaturePattern sig = SignaturePattern.read(s, context);
  296. KindedPointcut ret = new KindedPointcut(kind, sig);
  297. ret.readLocation(context, s);
  298. return ret;
  299. }
  300. // XXX note: there is no namebinding in any kinded pointcut.
  301. // still might want to do something for better error messages
  302. // We want to do something here to make sure we don't sidestep the parameter
  303. // list in capturing type identifiers.
  304. @Override
  305. public void resolveBindings(IScope scope, Bindings bindings) {
  306. if (kind == Shadow.Initialization) {
  307. // scope.getMessageHandler().handleMessage(
  308. // MessageUtil.error(
  309. // "initialization unimplemented in 1.1beta1",
  310. // this.getSourceLocation()));
  311. }
  312. signature = signature.resolveBindings(scope, bindings);
  313. if (kind == Shadow.ConstructorExecution) { // Bug fix 60936
  314. if (signature.getDeclaringType() != null) {
  315. World world = scope.getWorld();
  316. UnresolvedType exactType = signature.getDeclaringType().getExactType();
  317. if (signature.getKind() == Member.CONSTRUCTOR && !ResolvedType.isMissing(exactType)
  318. && exactType.resolve(world).isInterface() && !signature.getDeclaringType().isIncludeSubtypes()) {
  319. world.getLint().noInterfaceCtorJoinpoint.signal(exactType.toString(), getSourceLocation());
  320. }
  321. }
  322. }
  323. // no parameterized types
  324. if (kind == Shadow.StaticInitialization) {
  325. HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
  326. signature.getDeclaringType().traverse(visitor, null);
  327. if (visitor.wellHasItThen/* ? */()) {
  328. scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.NO_STATIC_INIT_JPS_FOR_PARAMETERIZED_TYPES),
  329. getSourceLocation()));
  330. }
  331. }
  332. // no parameterized types in declaring type position
  333. if ((kind == Shadow.FieldGet) || (kind == Shadow.FieldSet)) {
  334. HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
  335. signature.getDeclaringType().traverse(visitor, null);
  336. if (visitor.wellHasItThen/* ? */()) {
  337. scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.GET_AND_SET_DONT_SUPPORT_DEC_TYPE_PARAMETERS),
  338. getSourceLocation()));
  339. }
  340. // fields can't have a void type!
  341. UnresolvedType returnType = signature.getReturnType().getExactType();
  342. if (returnType.equals(UnresolvedType.VOID)) {
  343. scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.FIELDS_CANT_HAVE_VOID_TYPE),
  344. getSourceLocation()));
  345. }
  346. }
  347. // no join points for initialization and preinitialization of parameterized types
  348. // no throwable parameterized types
  349. if ((kind == Shadow.Initialization) || (kind == Shadow.PreInitialization)) {
  350. HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
  351. signature.getDeclaringType().traverse(visitor, null);
  352. if (visitor.wellHasItThen/* ? */()) {
  353. scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.NO_INIT_JPS_FOR_PARAMETERIZED_TYPES),
  354. getSourceLocation()));
  355. }
  356. visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
  357. signature.getThrowsPattern().traverse(visitor, null);
  358. if (visitor.wellHasItThen/* ? */()) {
  359. scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.NO_GENERIC_THROWABLES), getSourceLocation()));
  360. }
  361. }
  362. // no parameterized types in declaring type position
  363. // no throwable parameterized types
  364. if ((kind == Shadow.MethodExecution) || (kind == Shadow.ConstructorExecution)) {
  365. HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
  366. signature.getDeclaringType().traverse(visitor, null);
  367. if (visitor.wellHasItThen/* ? */()) {
  368. scope.message(MessageUtil.error(
  369. WeaverMessages.format(WeaverMessages.EXECUTION_DOESNT_SUPPORT_PARAMETERIZED_DECLARING_TYPES),
  370. getSourceLocation()));
  371. }
  372. visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
  373. signature.getThrowsPattern().traverse(visitor, null);
  374. if (visitor.wellHasItThen/* ? */()) {
  375. scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.NO_GENERIC_THROWABLES), getSourceLocation()));
  376. }
  377. }
  378. // no parameterized types in declaring type position
  379. // no throwable parameterized types
  380. if ((kind == Shadow.MethodCall) || (kind == Shadow.ConstructorCall)) {
  381. HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
  382. signature.getDeclaringType().traverse(visitor, null);
  383. if (visitor.wellHasItThen/* ? */()) {
  384. scope.message(MessageUtil.error(
  385. WeaverMessages.format(WeaverMessages.CALL_DOESNT_SUPPORT_PARAMETERIZED_DECLARING_TYPES),
  386. getSourceLocation()));
  387. }
  388. visitor = new HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor();
  389. signature.getThrowsPattern().traverse(visitor, null);
  390. if (visitor.wellHasItThen/* ? */()) {
  391. scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.NO_GENERIC_THROWABLES), getSourceLocation()));
  392. }
  393. if (!scope.getWorld().isJoinpointArrayConstructionEnabled() && kind == Shadow.ConstructorCall
  394. && signature.getDeclaringType().isArray()) {
  395. scope.message(MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_NEWARRAY_JOINPOINTS_BY_DEFAULT),
  396. getSourceLocation()));
  397. }
  398. }
  399. }
  400. @Override
  401. protected Test findResidueInternal(Shadow shadow, ExposedState state) {
  402. return match(shadow).alwaysTrue() ? Literal.TRUE : Literal.FALSE;
  403. }
  404. @Override
  405. public Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
  406. Pointcut ret = new KindedPointcut(kind, signature, bindings.getEnclosingAdvice());
  407. ret.copyLocationFrom(this);
  408. return ret;
  409. }
  410. @Override
  411. public Pointcut parameterizeWith(Map typeVariableMap, World w) {
  412. Pointcut ret = new KindedPointcut(kind, signature.parameterizeWith(typeVariableMap, w), munger);
  413. ret.copyLocationFrom(this);
  414. return ret;
  415. }
  416. public Shadow.Kind getKind() {
  417. return kind;
  418. }
  419. @Override
  420. public Object accept(PatternNodeVisitor visitor, Object data) {
  421. return visitor.visit(this, data);
  422. }
  423. }