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.

Shadow.java 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  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;
  13. import java.io.DataInputStream;
  14. import java.io.IOException;
  15. import java.lang.reflect.Modifier;
  16. import java.util.ArrayList;
  17. import java.util.Collections;
  18. import java.util.HashSet;
  19. import java.util.List;
  20. import java.util.Set;
  21. import org.aspectj.bridge.IMessage;
  22. import org.aspectj.bridge.ISourceLocation;
  23. import org.aspectj.bridge.MessageUtil;
  24. import org.aspectj.util.PartialOrder;
  25. import org.aspectj.util.TypeSafeEnum;
  26. import org.aspectj.weaver.ast.Var;
  27. /*
  28. * The superclass of anything representing a the shadow of a join point. A shadow represents
  29. * some bit of code, and encompasses both entry and exit from that code. All shadows have a kind
  30. * and a signature.
  31. */
  32. public abstract class Shadow {
  33. // every Shadow has a unique id, doesn't matter if it wraps...
  34. private static int nextShadowID = 100; // easier to spot than zero. // OPTIMIZE is this a bug? static?
  35. private final Kind kind;
  36. private final Member signature;
  37. private Member matchingSignature;
  38. private ResolvedMember resolvedSignature;
  39. protected final Shadow enclosingShadow;
  40. protected List<ShadowMunger> mungers = Collections.emptyList();
  41. protected boolean needAroundClosureStacking = false;
  42. public int shadowId = nextShadowID++; // every time we build a shadow, it gets a new id
  43. // ----
  44. protected Shadow(Kind kind, Member signature, Shadow enclosingShadow) {
  45. this.kind = kind;
  46. this.signature = signature;
  47. this.enclosingShadow = enclosingShadow;
  48. }
  49. // ----
  50. public abstract World getIWorld();
  51. public List<ShadowMunger> getMungers() {
  52. return mungers;
  53. }
  54. /**
  55. * could this(*) pcd ever match
  56. */
  57. public final boolean hasThis() {
  58. if (getKind().neverHasThis()) {
  59. return false;
  60. } else if (getKind().isEnclosingKind()) {
  61. return !Modifier.isStatic(getSignature().getModifiers());
  62. } else if (enclosingShadow == null) {
  63. return false;
  64. } else {
  65. return enclosingShadow.hasThis();
  66. }
  67. }
  68. /**
  69. * the type of the this object here
  70. *
  71. * @throws IllegalStateException if there is no this here
  72. */
  73. public final UnresolvedType getThisType() {
  74. if (!hasThis()) {
  75. throw new IllegalStateException("no this");
  76. }
  77. if (getKind().isEnclosingKind()) {
  78. return getSignature().getDeclaringType();
  79. } else {
  80. return enclosingShadow.getThisType();
  81. }
  82. }
  83. /**
  84. * a var referencing this
  85. *
  86. * @throws IllegalStateException if there is no target here
  87. */
  88. public abstract Var getThisVar();
  89. /**
  90. * could target(*) pcd ever match
  91. */
  92. public final boolean hasTarget() {
  93. if (getKind().neverHasTarget()) {
  94. return false;
  95. } else if (getKind().isTargetSameAsThis()) {
  96. return hasThis();
  97. } else {
  98. return !Modifier.isStatic(getSignature().getModifiers());
  99. }
  100. }
  101. /**
  102. * the type of the target object here
  103. *
  104. * @throws IllegalStateException if there is no target here
  105. */
  106. public final UnresolvedType getTargetType() {
  107. if (!hasTarget()) {
  108. throw new IllegalStateException("no target");
  109. }
  110. return getSignature().getDeclaringType();
  111. }
  112. /**
  113. * a var referencing the target
  114. *
  115. * @throws IllegalStateException if there is no target here
  116. */
  117. public abstract Var getTargetVar();
  118. public UnresolvedType[] getArgTypes() {
  119. if (getKind() == FieldSet) {
  120. return new UnresolvedType[] { getSignature().getReturnType() };
  121. }
  122. return getSignature().getParameterTypes();
  123. }
  124. public boolean isShadowForArrayConstructionJoinpoint() {
  125. return (getKind() == ConstructorCall && signature.getDeclaringType().isArray());
  126. }
  127. public boolean isShadowForMonitor() {
  128. return (getKind() == SynchronizationLock || getKind() == SynchronizationUnlock);
  129. }
  130. // will return the right length array of ints depending on how many dimensions the array has
  131. public ResolvedType[] getArgumentTypesForArrayConstructionShadow() {
  132. String s = signature.getDeclaringType().getSignature();
  133. int pos = s.indexOf("[");
  134. int dims = 1;
  135. while (pos < s.length()) {
  136. pos++;
  137. if (pos < s.length()) {
  138. dims += (s.charAt(pos) == '[' ? 1 : 0);
  139. }
  140. }
  141. ResolvedType intType = UnresolvedType.INT.resolve(this.getIWorld());
  142. if (dims == 1) {
  143. return new ResolvedType[] { intType };
  144. }
  145. ResolvedType[] someInts = new ResolvedType[dims];
  146. for (int i = 0; i < dims; i++) {
  147. someInts[i] = intType;
  148. }
  149. return someInts;
  150. }
  151. public UnresolvedType[] getGenericArgTypes() {
  152. if (isShadowForArrayConstructionJoinpoint()) {
  153. return getArgumentTypesForArrayConstructionShadow();
  154. }
  155. if (isShadowForMonitor()) {
  156. return UnresolvedType.ARRAY_WITH_JUST_OBJECT;
  157. }
  158. ResolvedMember resolvedSig = getResolvedSignature();
  159. if (getKind() == FieldSet) {
  160. return new UnresolvedType[] { resolvedSig == null ? null : resolvedSig.getGenericReturnType() };
  161. }
  162. return resolvedSig == null ? null : resolvedSig.getGenericParameterTypes();
  163. }
  164. public UnresolvedType getArgType(int arg) {
  165. if (getKind() == FieldSet) {
  166. return getSignature().getReturnType();
  167. }
  168. return getSignature().getParameterTypes()[arg];
  169. }
  170. public int getArgCount() {
  171. if (getKind() == FieldSet) {
  172. return 1;
  173. }
  174. return getSignature().getParameterTypes().length;
  175. }
  176. // /**
  177. // * Return name of the argument at position 'i' at this shadow. This does not make sense for all shadows - but can be useful in
  178. // * the case of, for example, method-execution.
  179. // *
  180. // * @return null if it cannot be determined
  181. // */
  182. // public String getArgName(int i, World w) {
  183. // String[] names = getSignature().getParameterNames(w);
  184. // if (names == null || i >= names.length)
  185. // return null;
  186. // return names[i];
  187. // }
  188. public abstract UnresolvedType getEnclosingType();
  189. public abstract Var getArgVar(int i);
  190. public abstract Var getThisJoinPointVar();
  191. public abstract Var getThisJoinPointStaticPartVar();
  192. public abstract Var getThisEnclosingJoinPointStaticPartVar();
  193. public abstract Var getThisAspectInstanceVar(ResolvedType aspectType);
  194. // annotation variables
  195. public abstract Var getKindedAnnotationVar(UnresolvedType forAnnotationType);
  196. public abstract Var getWithinAnnotationVar(UnresolvedType forAnnotationType);
  197. public abstract Var getWithinCodeAnnotationVar(UnresolvedType forAnnotationType);
  198. public abstract Var getThisAnnotationVar(UnresolvedType forAnnotationType);
  199. public abstract Var getTargetAnnotationVar(UnresolvedType forAnnotationType);
  200. public abstract Var getArgAnnotationVar(int i, UnresolvedType forAnnotationType);
  201. public abstract Member getEnclosingCodeSignature();
  202. /**
  203. * returns the kind of shadow this is, representing what happens under this shadow
  204. */
  205. public Kind getKind() {
  206. return kind;
  207. }
  208. /**
  209. * returns the signature of the thing under this shadow
  210. */
  211. public Member getSignature() {
  212. return signature;
  213. }
  214. /**
  215. * returns the signature of the thing under this shadow, with any synthetic arguments removed
  216. */
  217. public Member getMatchingSignature() {
  218. return matchingSignature != null ? matchingSignature : signature;
  219. }
  220. public void setMatchingSignature(Member member) {
  221. this.matchingSignature = member;
  222. }
  223. /**
  224. * returns the resolved signature of the thing under this shadow
  225. *
  226. */
  227. public ResolvedMember getResolvedSignature() {
  228. if (resolvedSignature == null) {
  229. resolvedSignature = signature.resolve(getIWorld());
  230. }
  231. return resolvedSignature;
  232. }
  233. public UnresolvedType getReturnType() {
  234. if (kind == ConstructorCall) {
  235. return getSignature().getDeclaringType();
  236. } else if (kind == FieldSet) {
  237. return UnresolvedType.VOID;
  238. } else if (kind == SynchronizationLock || kind == SynchronizationUnlock) {
  239. return UnresolvedType.VOID;
  240. }
  241. ResolvedMember resolvedSig = getResolvedSignature();
  242. return resolvedSig == null ? null : resolvedSig.getGenericReturnType();
  243. }
  244. public static String METHOD_EXECUTION = "method-execution";
  245. public static String METHOD_CALL = "method-call";
  246. public static String CONSTRUCTOR_EXECUTION = "constructor-execution";
  247. public static String CONSTRUCTOR_CALL = "constructor-call";
  248. public static String FIELD_GET = "field-get";
  249. public static String FIELD_SET = "field-set";
  250. public static String STATICINITIALIZATION = "staticinitialization";
  251. public static String PREINITIALIZATION = "preinitialization";
  252. public static String INITIALIZATION = "initialization";
  253. public static String EXCEPTION_HANDLER = "exception-handler";
  254. public static String SYNCHRONIZATION_LOCK = "lock";
  255. public static String SYNCHRONIZATION_UNLOCK = "unlock";
  256. public static String ADVICE_EXECUTION = "adviceexecution";
  257. /**
  258. * These names are the ones that will be returned by thisJoinPoint.getKind() Those need to be documented somewhere
  259. */
  260. public static final Kind MethodCall = new Kind(METHOD_CALL, 1, true);
  261. public static final Kind ConstructorCall = new Kind(CONSTRUCTOR_CALL, 2, true);
  262. public static final Kind MethodExecution = new Kind(METHOD_EXECUTION, 3, false);
  263. public static final Kind ConstructorExecution = new Kind(CONSTRUCTOR_EXECUTION, 4, false);
  264. public static final Kind FieldGet = new Kind(FIELD_GET, 5, true);
  265. public static final Kind FieldSet = new Kind(FIELD_SET, 6, true);
  266. public static final Kind StaticInitialization = new Kind(STATICINITIALIZATION, 7, false);
  267. public static final Kind PreInitialization = new Kind(PREINITIALIZATION, 8, false);
  268. public static final Kind AdviceExecution = new Kind(ADVICE_EXECUTION, 9, false);
  269. public static final Kind Initialization = new Kind(INITIALIZATION, 10, false);
  270. public static final Kind ExceptionHandler = new Kind(EXCEPTION_HANDLER, 11, true);
  271. public static final Kind SynchronizationLock = new Kind(SYNCHRONIZATION_LOCK, 12, true);
  272. public static final Kind SynchronizationUnlock = new Kind(SYNCHRONIZATION_UNLOCK, 13, true);
  273. // Bits here are 1<<(Kind.getKey()) - and unfortunately keys didn't start at zero so bits here start at 2
  274. public static final int MethodCallBit = 0x002;
  275. public static final int ConstructorCallBit = 0x004;
  276. public static final int MethodExecutionBit = 0x008;
  277. public static final int ConstructorExecutionBit = 0x010;
  278. public static final int FieldGetBit = 0x020;
  279. public static final int FieldSetBit = 0x040;
  280. public static final int StaticInitializationBit = 0x080;
  281. public static final int PreInitializationBit = 0x100;
  282. public static final int AdviceExecutionBit = 0x200;
  283. public static final int InitializationBit = 0x400;
  284. public static final int ExceptionHandlerBit = 0x800;
  285. public static final int SynchronizationLockBit = 0x1000;
  286. public static final int SynchronizationUnlockBit = 0x2000;
  287. public static final int MAX_SHADOW_KIND = 13;
  288. public static final Kind[] SHADOW_KINDS = new Kind[] { MethodCall, ConstructorCall, MethodExecution, ConstructorExecution,
  289. FieldGet, FieldSet, StaticInitialization, PreInitialization, AdviceExecution, Initialization, ExceptionHandler,
  290. SynchronizationLock, SynchronizationUnlock };
  291. public static final int ALL_SHADOW_KINDS_BITS;
  292. public static final int NO_SHADOW_KINDS_BITS;
  293. static {
  294. ALL_SHADOW_KINDS_BITS = 0x3ffe;
  295. NO_SHADOW_KINDS_BITS = 0x0000;
  296. }
  297. /**
  298. * Return count of how many bits set in the supplied parameter.
  299. */
  300. public static int howMany(int i) {
  301. int count = 0;
  302. for (Kind shadowKind : SHADOW_KINDS) {
  303. if ((i & shadowKind.bit) != 0) {
  304. count++;
  305. }
  306. }
  307. return count;
  308. }
  309. /**
  310. * A type-safe enum representing the kind of shadows
  311. */
  312. public static final class Kind extends TypeSafeEnum {
  313. // private boolean argsOnStack; //XXX unused
  314. public int bit;
  315. public Kind(String name, int key, boolean argsOnStack) {
  316. super(name, key);
  317. bit = 1 << key;
  318. // this.argsOnStack = argsOnStack;
  319. }
  320. public String toLegalJavaIdentifier() {
  321. return getName().replace('-', '_');
  322. }
  323. public boolean argsOnStack() {
  324. return !isTargetSameAsThis();
  325. }
  326. // false for handlers
  327. public boolean allowsExtraction() {
  328. return true;
  329. }
  330. public boolean isSet(int i) {
  331. return (i & bit) != 0;
  332. }
  333. // XXX revisit along with removal of priorities
  334. public boolean hasHighPriorityExceptions() {
  335. return !isTargetSameAsThis();
  336. }
  337. private final static int hasReturnValueFlag = MethodCallBit | ConstructorCallBit | MethodExecutionBit | FieldGetBit
  338. | AdviceExecutionBit;
  339. /**
  340. * These shadow kinds have return values that can be bound in after returning(Dooberry doo) advice.
  341. *
  342. * @return
  343. */
  344. public boolean hasReturnValue() {
  345. return (bit & hasReturnValueFlag) != 0;
  346. }
  347. private final static int isEnclosingKindFlag = MethodExecutionBit | ConstructorExecutionBit | AdviceExecutionBit
  348. | StaticInitializationBit | InitializationBit;
  349. /**
  350. * These are all the shadows that contains other shadows within them and are often directly associated with methods.
  351. */
  352. public boolean isEnclosingKind() {
  353. return (bit & isEnclosingKindFlag) != 0;
  354. }
  355. private final static int isTargetSameAsThisFlag = MethodExecutionBit | ConstructorExecutionBit | StaticInitializationBit
  356. | PreInitializationBit | AdviceExecutionBit | InitializationBit;
  357. public boolean isTargetSameAsThis() {
  358. return (bit & isTargetSameAsThisFlag) != 0;
  359. }
  360. private final static int neverHasTargetFlag = ConstructorCallBit | ExceptionHandlerBit | PreInitializationBit
  361. | StaticInitializationBit | SynchronizationLockBit | SynchronizationUnlockBit;
  362. public boolean neverHasTarget() {
  363. return (bit & neverHasTargetFlag) != 0;
  364. }
  365. private final static int neverHasThisFlag = PreInitializationBit | StaticInitializationBit;
  366. public boolean neverHasThis() {
  367. return (bit & neverHasThisFlag) != 0;
  368. }
  369. public String getSimpleName() {
  370. int dash = getName().lastIndexOf('-');
  371. if (dash == -1) {
  372. return getName();
  373. } else {
  374. return getName().substring(dash + 1);
  375. }
  376. }
  377. public static Kind read(DataInputStream s) throws IOException {
  378. int key = s.readByte();
  379. switch (key) {
  380. case 1:
  381. return MethodCall;
  382. case 2:
  383. return ConstructorCall;
  384. case 3:
  385. return MethodExecution;
  386. case 4:
  387. return ConstructorExecution;
  388. case 5:
  389. return FieldGet;
  390. case 6:
  391. return FieldSet;
  392. case 7:
  393. return StaticInitialization;
  394. case 8:
  395. return PreInitialization;
  396. case 9:
  397. return AdviceExecution;
  398. case 10:
  399. return Initialization;
  400. case 11:
  401. return ExceptionHandler;
  402. case 12:
  403. return SynchronizationLock;
  404. case 13:
  405. return SynchronizationUnlock;
  406. }
  407. throw new BCException("unknown kind: " + key);
  408. }
  409. }
  410. /**
  411. * Only does the check if the munger requires it (@AJ aspects don't)
  412. *
  413. * @param munger
  414. * @return
  415. */
  416. protected boolean checkMunger(ShadowMunger munger) {
  417. if (munger.mustCheckExceptions()) {
  418. for (ResolvedType resolvedType : munger.getThrownExceptions()) {
  419. if (!checkCanThrow(munger, resolvedType)) {
  420. return false;
  421. }
  422. }
  423. }
  424. return true;
  425. }
  426. protected boolean checkCanThrow(ShadowMunger munger, ResolvedType resolvedTypeX) {
  427. if (getKind() == ExceptionHandler) {
  428. // XXX much too lenient rules here, need to walk up exception handlers
  429. return true;
  430. }
  431. if (!isDeclaredException(resolvedTypeX, getSignature())) {
  432. getIWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CANT_THROW_CHECKED, resolvedTypeX, this), // from
  433. // advice
  434. // in
  435. // \
  436. // '"
  437. // +
  438. // munger
  439. // .
  440. // +
  441. // "\'"
  442. // ,
  443. getSourceLocation(), munger.getSourceLocation());
  444. }
  445. return true;
  446. }
  447. private boolean isDeclaredException(ResolvedType resolvedTypeX, Member member) {
  448. ResolvedType[] excs = getIWorld().resolve(member.getExceptions(getIWorld()));
  449. for (ResolvedType exc : excs) {
  450. if (exc.isAssignableFrom(resolvedTypeX)) {
  451. return true;
  452. }
  453. }
  454. return false;
  455. }
  456. public void addMunger(ShadowMunger munger) {
  457. if (checkMunger(munger)) {
  458. if (mungers == Collections.EMPTY_LIST) {
  459. mungers = new ArrayList<>();
  460. }
  461. this.mungers.add(munger);
  462. }
  463. }
  464. public final void implement() {
  465. sortMungers();
  466. if (mungers == null) {
  467. return;
  468. }
  469. prepareForMungers();
  470. implementMungers();
  471. }
  472. private void sortMungers() {
  473. List<ShadowMunger> sorted = PartialOrder.sort(mungers);
  474. // Bunch of code to work out whether to report xlints for advice that isn't ordered at this Joinpoint
  475. possiblyReportUnorderedAdvice(sorted);
  476. if (sorted == null) {
  477. // this means that we have circular dependencies
  478. for (ShadowMunger m : mungers) {
  479. getIWorld().getMessageHandler().handleMessage(
  480. MessageUtil.error(WeaverMessages.format(WeaverMessages.CIRCULAR_DEPENDENCY, this), m.getSourceLocation()));
  481. }
  482. }
  483. mungers = sorted;
  484. }
  485. // not quite optimal... but the xlint is ignore by default
  486. private void possiblyReportUnorderedAdvice(List<ShadowMunger> sorted) {
  487. if (sorted != null && getIWorld().getLint().unorderedAdviceAtShadow.isEnabled() && mungers.size() > 1) {
  488. // Stores a set of strings of the form 'aspect1:aspect2' which indicates there is no
  489. // precedence specified between the two aspects at this shadow.
  490. Set<String> clashingAspects = new HashSet<>();
  491. int max = mungers.size();
  492. // Compare every pair of advice mungers
  493. for (int i = max - 1; i >= 0; i--) {
  494. for (int j = 0; j < i; j++) {
  495. ShadowMunger a = mungers.get(i);
  496. ShadowMunger b = mungers.get(j);
  497. // Make sure they are the right type
  498. if (a instanceof Advice && b instanceof Advice) {
  499. Advice adviceA = (Advice) a;
  500. Advice adviceB = (Advice) b;
  501. if (!adviceA.concreteAspect.equals(adviceB.concreteAspect)) {
  502. AdviceKind adviceKindA = adviceA.getKind();
  503. AdviceKind adviceKindB = adviceB.getKind();
  504. // make sure they are the nice ones (<6) and not any synthetic advice ones we
  505. // create to support other features of the language.
  506. if (adviceKindA.getKey() < (byte) 6 && adviceKindB.getKey() < (byte) 6
  507. && adviceKindA.getPrecedence() == adviceKindB.getPrecedence()) {
  508. // Ask the world if it knows about precedence between these
  509. Integer order = getIWorld().getPrecedenceIfAny(adviceA.concreteAspect, adviceB.concreteAspect);
  510. if (order != null && order.equals(0)) {
  511. String key = adviceA.getDeclaringAspect() + ":" + adviceB.getDeclaringAspect();
  512. String possibleExistingKey = adviceB.getDeclaringAspect() + ":" + adviceA.getDeclaringAspect();
  513. if (!clashingAspects.contains(possibleExistingKey)) {
  514. clashingAspects.add(key);
  515. }
  516. }
  517. }
  518. }
  519. }
  520. }
  521. }
  522. for (String element : clashingAspects) {
  523. String aspect1 = element.substring(0, element.indexOf(":"));
  524. String aspect2 = element.substring(element.indexOf(":") + 1);
  525. getIWorld().getLint().unorderedAdviceAtShadow.signal(new String[]{this.toString(), aspect1, aspect2},
  526. this.getSourceLocation(), null);
  527. }
  528. }
  529. }
  530. /**
  531. * Prepare the shadow for implementation. After this is done, the shadow should be in such a position that each munger simply
  532. * needs to be implemented.
  533. */
  534. protected void prepareForMungers() {
  535. throw new RuntimeException("Generic shadows cannot be prepared");
  536. }
  537. /** Actually implement the (non-empty) mungers associated with this shadow */
  538. private void implementMungers() {
  539. World world = getIWorld();
  540. needAroundClosureStacking = false;
  541. int annotationStyleWithAroundAndProceedCount = 0;
  542. for (ShadowMunger munger: mungers) {
  543. if (munger.getDeclaringType()!= null &&
  544. munger.getDeclaringType().isAnnotationStyleAspect() &&
  545. munger.isAroundAdvice() &&
  546. munger.bindsProceedingJoinPoint()) {
  547. annotationStyleWithAroundAndProceedCount++;
  548. if (annotationStyleWithAroundAndProceedCount>1) {
  549. needAroundClosureStacking = true;
  550. break;
  551. }
  552. }
  553. }
  554. for (ShadowMunger munger : mungers) {
  555. if (munger.implementOn(this)) {
  556. world.reportMatch(munger, this);
  557. }
  558. }
  559. }
  560. public abstract ISourceLocation getSourceLocation();
  561. // ---- utility
  562. public String toString() {
  563. return getKind() + "(" + getSignature() + ")"; // + getSourceLines();
  564. }
  565. public String toResolvedString(World world) {
  566. StringBuilder sb = new StringBuilder();
  567. sb.append(getKind());
  568. sb.append("(");
  569. Member m = getSignature();
  570. if (m == null) {
  571. sb.append("<<missing signature>>");
  572. } else {
  573. ResolvedMember rm = world.resolve(m);
  574. if (rm == null) {
  575. sb.append("<<unresolvableMember:").append(m).append(">>");
  576. } else {
  577. String genString = rm.toGenericString();
  578. if (genString == null) {
  579. sb.append("<<unableToGetGenericStringFor:").append(rm).append(">>");
  580. } else {
  581. sb.append(genString);
  582. }
  583. }
  584. }
  585. sb.append(")");
  586. return sb.toString();
  587. // was: return getKind() + "(" + world.resolve(getSignature()).toGenericString() + ")";
  588. }
  589. /**
  590. * Convert a bit array for the shadow kinds into a set of them... should only be used for testing - mainline code should do bit
  591. * manipulation!
  592. */
  593. public static Set<Kind> toSet(int i) {
  594. Set<Kind> results = new HashSet<>();
  595. for (int j = 0; j < Shadow.SHADOW_KINDS.length; j++) {
  596. Kind k = Shadow.SHADOW_KINDS[j];
  597. if (k.isSet(i)) {
  598. results.add(k);
  599. }
  600. }
  601. return results;
  602. }
  603. }