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.

ArgsAnnotationPointcut.java 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /* *******************************************************************
  2. * Copyright (c) 2004 IBM Corporation.
  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. * ******************************************************************/
  10. package org.aspectj.weaver.patterns;
  11. import java.io.IOException;
  12. import java.util.ArrayList;
  13. import java.util.Collections;
  14. import java.util.List;
  15. import java.util.Map;
  16. import org.aspectj.bridge.IMessage;
  17. import org.aspectj.bridge.ISourceLocation;
  18. import org.aspectj.bridge.MessageUtil;
  19. import org.aspectj.util.FuzzyBoolean;
  20. import org.aspectj.weaver.CompressingDataOutputStream;
  21. import org.aspectj.weaver.ISourceContext;
  22. import org.aspectj.weaver.IntMap;
  23. import org.aspectj.weaver.ResolvedType;
  24. import org.aspectj.weaver.Shadow;
  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. import org.aspectj.weaver.ast.Literal;
  30. import org.aspectj.weaver.ast.Test;
  31. import org.aspectj.weaver.ast.Var;
  32. /**
  33. * @author colyer
  34. *
  35. * TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code
  36. * Templates
  37. */
  38. public class ArgsAnnotationPointcut extends NameBindingPointcut {
  39. private AnnotationPatternList arguments;
  40. private String declarationText;
  41. /**
  42. *
  43. */
  44. public ArgsAnnotationPointcut(AnnotationPatternList arguments) {
  45. super();
  46. this.arguments = arguments;
  47. this.pointcutKind = ATARGS;
  48. buildDeclarationText();
  49. }
  50. public AnnotationPatternList getArguments() {
  51. return arguments;
  52. }
  53. public int couldMatchKinds() {
  54. return Shadow.ALL_SHADOW_KINDS_BITS; // empty args() matches jps with no args
  55. }
  56. public Pointcut parameterizeWith(Map typeVariableMap, World w) {
  57. ArgsAnnotationPointcut ret = new ArgsAnnotationPointcut(arguments.parameterizeWith(typeVariableMap, w));
  58. ret.copyLocationFrom(this);
  59. return ret;
  60. }
  61. /*
  62. * (non-Javadoc)
  63. *
  64. * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
  65. */
  66. public FuzzyBoolean fastMatch(FastMatchInfo info) {
  67. return FuzzyBoolean.MAYBE;
  68. }
  69. /*
  70. * (non-Javadoc)
  71. *
  72. * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
  73. */
  74. protected FuzzyBoolean matchInternal(Shadow shadow) {
  75. arguments.resolve(shadow.getIWorld());
  76. FuzzyBoolean ret = arguments.matches(shadow.getIWorld().resolve(shadow.getArgTypes()));
  77. return ret;
  78. }
  79. /*
  80. * (non-Javadoc)
  81. *
  82. * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope,
  83. * org.aspectj.weaver.patterns.Bindings)
  84. */
  85. protected void resolveBindings(IScope scope, Bindings bindings) {
  86. if (!scope.getWorld().isInJava5Mode()) {
  87. scope.message(MessageUtil.error(WeaverMessages.format(WeaverMessages.ATARGS_ONLY_SUPPORTED_AT_JAVA5_LEVEL),
  88. getSourceLocation()));
  89. return;
  90. }
  91. arguments.resolveBindings(scope, bindings, true);
  92. if (arguments.ellipsisCount > 1) {
  93. scope.message(IMessage.ERROR, this, "uses more than one .. in args (compiler limitation)");
  94. }
  95. }
  96. /*
  97. * (non-Javadoc)
  98. *
  99. * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedType, org.aspectj.weaver.IntMap)
  100. */
  101. protected Pointcut concretize1(ResolvedType inAspect, ResolvedType declaringType, IntMap bindings) {
  102. if (isDeclare(bindings.getEnclosingAdvice())) {
  103. // Enforce rule about which designators are supported in declare
  104. inAspect.getWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.ARGS_IN_DECLARE),
  105. bindings.getEnclosingAdvice().getSourceLocation(), null);
  106. return Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
  107. }
  108. AnnotationPatternList list = arguments.resolveReferences(bindings);
  109. Pointcut ret = new ArgsAnnotationPointcut(list);
  110. ret.copyLocationFrom(this);
  111. return ret;
  112. }
  113. /*
  114. * (non-Javadoc)
  115. *
  116. * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
  117. */
  118. protected Test findResidueInternal(Shadow shadow, ExposedState state) {
  119. int len = shadow.getArgCount();
  120. // do some quick length tests first
  121. int numArgsMatchedByEllipsis = (len + arguments.ellipsisCount) - arguments.size();
  122. if (numArgsMatchedByEllipsis < 0) {
  123. return Literal.FALSE; // should never happen
  124. }
  125. if ((numArgsMatchedByEllipsis > 0) && (arguments.ellipsisCount == 0)) {
  126. return Literal.FALSE; // should never happen
  127. }
  128. // now work through the args and the patterns, skipping at ellipsis
  129. Test ret = Literal.TRUE;
  130. int argsIndex = 0;
  131. for (int i = 0; i < arguments.size(); i++) {
  132. if (arguments.get(i) == AnnotationTypePattern.ELLIPSIS) {
  133. // match ellipsisMatchCount args
  134. argsIndex += numArgsMatchedByEllipsis;
  135. } else if (arguments.get(i) == AnnotationTypePattern.ANY) {
  136. argsIndex++;
  137. } else {
  138. // match the argument type at argsIndex with the ExactAnnotationTypePattern
  139. // we know it is exact because nothing else is allowed in args
  140. ExactAnnotationTypePattern ap = (ExactAnnotationTypePattern) arguments.get(i);
  141. UnresolvedType argType = shadow.getArgType(argsIndex);
  142. ResolvedType rArgType = argType.resolve(shadow.getIWorld());
  143. if (rArgType.isMissing()) {
  144. shadow.getIWorld().getLint().cantFindType.signal(new String[] { WeaverMessages.format(
  145. WeaverMessages.CANT_FIND_TYPE_ARG_TYPE, argType.getName()) }, shadow.getSourceLocation(),
  146. new ISourceLocation[] { getSourceLocation() });
  147. // IMessage msg = new Message(
  148. // WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_ARG_TYPE,argType.getName()),
  149. // "",IMessage.ERROR,shadow.getSourceLocation(),null,new ISourceLocation[]{getSourceLocation()});
  150. }
  151. ResolvedType rAnnType = ap.getAnnotationType().resolve(shadow.getIWorld());
  152. if (ap instanceof BindingAnnotationTypePattern) {
  153. BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern) ap;
  154. Var annvar = shadow.getArgAnnotationVar(argsIndex, rAnnType);
  155. state.set(btp.getFormalIndex(), annvar);
  156. }
  157. if (!ap.matches(rArgType).alwaysTrue()) {
  158. // we need a test...
  159. ret = Test.makeAnd(ret, Test.makeHasAnnotation(shadow.getArgVar(argsIndex), rAnnType));
  160. }
  161. argsIndex++;
  162. }
  163. }
  164. return ret;
  165. }
  166. public List<BindingPattern> getBindingAnnotationTypePatterns() {
  167. List<BindingPattern> l = new ArrayList<>();
  168. AnnotationTypePattern[] pats = arguments.getAnnotationPatterns();
  169. for (AnnotationTypePattern pat : pats) {
  170. if (pat instanceof BindingAnnotationTypePattern) {
  171. l.add((BindingPattern) pat);
  172. }
  173. }
  174. return l;
  175. }
  176. public List<BindingTypePattern> getBindingTypePatterns() {
  177. return Collections.emptyList();
  178. }
  179. public void write(CompressingDataOutputStream s) throws IOException {
  180. s.writeByte(Pointcut.ATARGS);
  181. arguments.write(s);
  182. writeLocation(s);
  183. }
  184. public static Pointcut read(VersionedDataInputStream s, ISourceContext context) throws IOException {
  185. AnnotationPatternList annotationPatternList = AnnotationPatternList.read(s, context);
  186. ArgsAnnotationPointcut ret = new ArgsAnnotationPointcut(annotationPatternList);
  187. ret.readLocation(context, s);
  188. return ret;
  189. }
  190. /*
  191. * (non-Javadoc)
  192. *
  193. * @see java.lang.Object#equals(java.lang.Object)
  194. */
  195. public boolean equals(Object obj) {
  196. if (!(obj instanceof ArgsAnnotationPointcut)) {
  197. return false;
  198. }
  199. ArgsAnnotationPointcut other = (ArgsAnnotationPointcut) obj;
  200. return other.arguments.equals(arguments);
  201. }
  202. /*
  203. * (non-Javadoc)
  204. *
  205. * @see java.lang.Object#hashCode()
  206. */
  207. public int hashCode() {
  208. return 17 + 37 * arguments.hashCode();
  209. }
  210. /*
  211. * (non-Javadoc)
  212. *
  213. * @see java.lang.Object#toString()
  214. */
  215. private void buildDeclarationText() {
  216. StringBuilder buf = new StringBuilder("@args");
  217. buf.append(arguments.toString());
  218. this.declarationText = buf.toString();
  219. }
  220. public String toString() {
  221. return this.declarationText;
  222. }
  223. public Object accept(PatternNodeVisitor visitor, Object data) {
  224. return visitor.visit(this, data);
  225. }
  226. }