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 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;
  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.Iterator;
  20. import java.util.List;
  21. import java.util.Set;
  22. import org.aspectj.bridge.IMessage;
  23. import org.aspectj.bridge.ISourceLocation;
  24. import org.aspectj.bridge.MessageUtil;
  25. import org.aspectj.util.PartialOrder;
  26. import org.aspectj.util.TypeSafeEnum;
  27. import org.aspectj.weaver.ast.Var;
  28. /*
  29. * The superclass of anything representing a the shadow of a join point. A shadow represents
  30. * some bit of code, and encompasses both entry and exit from that code. All shadows have a kind
  31. * and a signature.
  32. */
  33. public abstract class Shadow {
  34. // every Shadow has a unique id, doesn't matter if it wraps...
  35. private static int nextShadowID = 100; // easier to spot than zero. // OPTIMIZE is this a bug? static?
  36. private final Kind kind;
  37. private final Member signature;
  38. private Member matchingSignature;
  39. private ResolvedMember resolvedSignature;
  40. protected final Shadow enclosingShadow;
  41. protected List<ShadowMunger> mungers = Collections.emptyList();
  42. protected boolean needAroundClosureStacking = false;
  43. public int shadowId = nextShadowID++; // every time we build a shadow, it gets a new id
  44. // ----
  45. protected Shadow(Kind kind, Member signature, Shadow enclosingShadow) {
  46. this.kind = kind;
  47. this.signature = signature;
  48. this.enclosingShadow = enclosingShadow;
  49. }
  50. // ----
  51. public abstract World getIWorld();
  52. public List<ShadowMunger> getMungers() {
  53. return mungers;
  54. }
  55. /**
  56. * could this(*) pcd ever match
  57. */
  58. public final boolean hasThis() {
  59. if (getKind().neverHasThis()) {
  60. return false;
  61. } else if (getKind().isEnclosingKind()) {
  62. return !Modifier.isStatic(getSignature().getModifiers());
  63. } else if (enclosingShadow == null) {
  64. return false;
  65. } else {
  66. return enclosingShadow.hasThis();
  67. }
  68. }
  69. /**
  70. * the type of the this object here
  71. *
  72. * @throws IllegalStateException if there is no this here
  73. */
  74. public final UnresolvedType getThisType() {
  75. if (!hasThis()) {
  76. throw new IllegalStateException("no this");
  77. }
  78. if (getKind().isEnclosingKind()) {
  79. return getSignature().getDeclaringType();
  80. } else {
  81. return enclosingShadow.getThisType();
  82. }
  83. }
  84. /**
  85. * a var referencing this
  86. *
  87. * @throws IllegalStateException if there is no target here
  88. */
  89. public abstract Var getThisVar();
  90. /**
  91. * could target(*) pcd ever match
  92. */
  93. public final boolean hasTarget() {
  94. if (getKind().neverHasTarget()) {
  95. return false;
  96. } else if (getKind().isTargetSameAsThis()) {
  97. return hasThis();
  98. } else {
  99. return !Modifier.isStatic(getSignature().getModifiers());
  100. }
  101. }
  102. /**
  103. * the type of the target object here
  104. *
  105. * @throws IllegalStateException if there is no target here
  106. */
  107. public final UnresolvedType getTargetType() {
  108. if (!hasTarget()) {
  109. throw new IllegalStateException("no target");
  110. }
  111. return getSignature().getDeclaringType();
  112. }
  113. /**
  114. * a var referencing the target
  115. *
  116. * @throws IllegalStateException if there is no target here
  117. */
  118. public abstract Var getTargetVar();
  119. public UnresolvedType[] getArgTypes() {
  120. if (getKind() == FieldSet) {
  121. return new UnresolvedType[] { getSignature().getReturnType() };
  122. }
  123. return getSignature().getParameterTypes();
  124. }
  125. public boolean isShadowForArrayConstructionJoinpoint() {
  126. return (getKind() == ConstructorCall && signature.getDeclaringType().isArray());
  127. }
  128. public boolean isShadowForMonitor() {
  129. return (getKind() == SynchronizationLock || getKind() == SynchronizationUnlock);
  130. }
  131. // will return the right length array of ints depending on how many dimensions the array has
  132. public ResolvedType[] getArgumentTypesForArrayConstructionShadow() {
  133. String s = signature.getDeclaringType().getSignature();
  134. int pos = s.indexOf("[");
  135. int dims = 1;
  136. while (pos < s.length()) {
  137. pos++;
  138. if (pos < s.length()) {
  139. dims += (s.charAt(pos) == '[' ? 1 : 0);
  140. }
  141. }
  142. ResolvedType intType = UnresolvedType.INT.resolve(this.getIWorld());
  143. if (dims == 1) {
  144. return new ResolvedType[] { intType };
  145. }
  146. ResolvedType[] someInts = new ResolvedType[dims];
  147. for (int i = 0; i < dims; i++) {
  148. someInts[i] = intType;
  149. }
  150. return someInts;
  151. }
  152. public UnresolvedType[] getGenericArgTypes() {
  153. if (isShadowForArrayConstructionJoinpoint()) {
  154. return getArgumentTypesForArrayConstructionShadow();
  155. }
  156. if (isShadowForMonitor()) {
  157. return UnresolvedType.ARRAY_WITH_JUST_OBJECT;
  158. }
  159. if (getKind() == FieldSet) {
  160. return new UnresolvedType[] { getResolvedSignature().getGenericReturnType() };
  161. }
  162. return getResolvedSignature().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. return getResolvedSignature().getGenericReturnType();
  242. }
  243. public static String METHOD_EXECUTION = "method-execution";
  244. public static String METHOD_CALL = "method-call";
  245. public static String CONSTRUCTOR_EXECUTION = "constructor-execution";
  246. public static String CONSTRUCTOR_CALL = "constructor-call";
  247. public static String FIELD_GET = "field-get";
  248. public static String FIELD_SET = "field-set";
  249. public static String STATICINITIALIZATION = "staticinitialization";
  250. public static String PREINITIALIZATION = "preinitialization";
  251. public static String INITIALIZATION = "initialization";
  252. public static String EXCEPTION_HANDLER = "exception-handler";
  253. public static String SYNCHRONIZATION_LOCK = "lock";
  254. public static String SYNCHRONIZATION_UNLOCK = "unlock";
  255. public static String ADVICE_EXECUTION = "adviceexecution";
  256. /**
  257. * These names are the ones that will be returned by thisJoinPoint.getKind() Those need to be documented somewhere
  258. */
  259. public static final Kind MethodCall = new Kind(METHOD_CALL, 1, true);
  260. public static final Kind ConstructorCall = new Kind(CONSTRUCTOR_CALL, 2, true);
  261. public static final Kind MethodExecution = new Kind(METHOD_EXECUTION, 3, false);
  262. public static final Kind ConstructorExecution = new Kind(CONSTRUCTOR_EXECUTION, 4, false);
  263. public static final Kind FieldGet = new Kind(FIELD_GET, 5, true);
  264. public static final Kind FieldSet = new Kind(FIELD_SET, 6, true);
  265. public static final Kind StaticInitialization = new Kind(STATICINITIALIZATION, 7, false);
  266. public static final Kind PreInitialization = new Kind(PREINITIALIZATION, 8, false);
  267. public static final Kind AdviceExecution = new Kind(ADVICE_EXECUTION, 9, false);
  268. public static final Kind Initialization = new Kind(INITIALIZATION, 10, false);
  269. public static final Kind ExceptionHandler = new Kind(EXCEPTION_HANDLER, 11, true);
  270. public static final Kind SynchronizationLock = new Kind(SYNCHRONIZATION_LOCK, 12, true);
  271. public static final Kind SynchronizationUnlock = new Kind(SYNCHRONIZATION_UNLOCK, 13, true);
  272. // Bits here are 1<<(Kind.getKey()) - and unfortunately keys didn't start at zero so bits here start at 2
  273. public static final int MethodCallBit = 0x002;
  274. public static final int ConstructorCallBit = 0x004;
  275. public static final int MethodExecutionBit = 0x008;
  276. public static final int ConstructorExecutionBit = 0x010;
  277. public static final int FieldGetBit = 0x020;
  278. public static final int FieldSetBit = 0x040;
  279. public static final int StaticInitializationBit = 0x080;
  280. public static final int PreInitializationBit = 0x100;
  281. public static final int AdviceExecutionBit = 0x200;
  282. public static final int InitializationBit = 0x400;
  283. public static final int ExceptionHandlerBit = 0x800;
  284. public static final int SynchronizationLockBit = 0x1000;
  285. public static final int SynchronizationUnlockBit = 0x2000;
  286. public static final int MAX_SHADOW_KIND = 13;
  287. public static final Kind[] SHADOW_KINDS = new Kind[] { MethodCall, ConstructorCall, MethodExecution, ConstructorExecution,
  288. FieldGet, FieldSet, StaticInitialization, PreInitialization, AdviceExecution, Initialization, ExceptionHandler,
  289. SynchronizationLock, SynchronizationUnlock };
  290. public static final int ALL_SHADOW_KINDS_BITS;
  291. public static final int NO_SHADOW_KINDS_BITS;
  292. static {
  293. ALL_SHADOW_KINDS_BITS = 0x3ffe;
  294. NO_SHADOW_KINDS_BITS = 0x0000;
  295. }
  296. /**
  297. * Return count of how many bits set in the supplied parameter.
  298. */
  299. public static int howMany(int i) {
  300. int count = 0;
  301. for (int j = 0; j < SHADOW_KINDS.length; j++) {
  302. if ((i & SHADOW_KINDS[j].bit) != 0) {
  303. count++;
  304. }
  305. }
  306. return count;
  307. }
  308. /**
  309. * A type-safe enum representing the kind of shadows
  310. */
  311. public static final class Kind extends TypeSafeEnum {
  312. // private boolean argsOnStack; //XXX unused
  313. public int bit;
  314. public Kind(String name, int key, boolean argsOnStack) {
  315. super(name, key);
  316. bit = 1 << key;
  317. // this.argsOnStack = argsOnStack;
  318. }
  319. public String toLegalJavaIdentifier() {
  320. return getName().replace('-', '_');
  321. }
  322. public boolean argsOnStack() {
  323. return !isTargetSameAsThis();
  324. }
  325. // false for handlers
  326. public boolean allowsExtraction() {
  327. return true;
  328. }
  329. public boolean isSet(int i) {
  330. return (i & bit) != 0;
  331. }
  332. // XXX revisit along with removal of priorities
  333. public boolean hasHighPriorityExceptions() {
  334. return !isTargetSameAsThis();
  335. }
  336. private final static int hasReturnValueFlag = MethodCallBit | ConstructorCallBit | MethodExecutionBit | FieldGetBit
  337. | AdviceExecutionBit;
  338. /**
  339. * These shadow kinds have return values that can be bound in after returning(Dooberry doo) advice.
  340. *
  341. * @return
  342. */
  343. public boolean hasReturnValue() {
  344. return (bit & hasReturnValueFlag) != 0;
  345. }
  346. private final static int isEnclosingKindFlag = MethodExecutionBit | ConstructorExecutionBit | AdviceExecutionBit
  347. | StaticInitializationBit | InitializationBit;
  348. /**
  349. * These are all the shadows that contains other shadows within them and are often directly associated with methods.
  350. */
  351. public boolean isEnclosingKind() {
  352. return (bit & isEnclosingKindFlag) != 0;
  353. }
  354. private final static int isTargetSameAsThisFlag = MethodExecutionBit | ConstructorExecutionBit | StaticInitializationBit
  355. | PreInitializationBit | AdviceExecutionBit | InitializationBit;
  356. public boolean isTargetSameAsThis() {
  357. return (bit & isTargetSameAsThisFlag) != 0;
  358. }
  359. private final static int neverHasTargetFlag = ConstructorCallBit | ExceptionHandlerBit | PreInitializationBit
  360. | StaticInitializationBit | SynchronizationLockBit | SynchronizationUnlockBit;
  361. public boolean neverHasTarget() {
  362. return (bit & neverHasTargetFlag) != 0;
  363. }
  364. private final static int neverHasThisFlag = PreInitializationBit | StaticInitializationBit;
  365. public boolean neverHasThis() {
  366. return (bit & neverHasThisFlag) != 0;
  367. }
  368. public String getSimpleName() {
  369. int dash = getName().lastIndexOf('-');
  370. if (dash == -1) {
  371. return getName();
  372. } else {
  373. return getName().substring(dash + 1);
  374. }
  375. }
  376. public static Kind read(DataInputStream s) throws IOException {
  377. int key = s.readByte();
  378. switch (key) {
  379. case 1:
  380. return MethodCall;
  381. case 2:
  382. return ConstructorCall;
  383. case 3:
  384. return MethodExecution;
  385. case 4:
  386. return ConstructorExecution;
  387. case 5:
  388. return FieldGet;
  389. case 6:
  390. return FieldSet;
  391. case 7:
  392. return StaticInitialization;
  393. case 8:
  394. return PreInitialization;
  395. case 9:
  396. return AdviceExecution;
  397. case 10:
  398. return Initialization;
  399. case 11:
  400. return ExceptionHandler;
  401. case 12:
  402. return SynchronizationLock;
  403. case 13:
  404. return SynchronizationUnlock;
  405. }
  406. throw new BCException("unknown kind: " + key);
  407. }
  408. }
  409. /**
  410. * Only does the check if the munger requires it (@AJ aspects don't)
  411. *
  412. * @param munger
  413. * @return
  414. */
  415. protected boolean checkMunger(ShadowMunger munger) {
  416. if (munger.mustCheckExceptions()) {
  417. for (Iterator<ResolvedType> i = munger.getThrownExceptions().iterator(); i.hasNext();) {
  418. if (!checkCanThrow(munger, i.next())) {
  419. return false;
  420. }
  421. }
  422. }
  423. return true;
  424. }
  425. protected boolean checkCanThrow(ShadowMunger munger, ResolvedType resolvedTypeX) {
  426. if (getKind() == ExceptionHandler) {
  427. // XXX much too lenient rules here, need to walk up exception handlers
  428. return true;
  429. }
  430. if (!isDeclaredException(resolvedTypeX, getSignature())) {
  431. getIWorld().showMessage(IMessage.ERROR, WeaverMessages.format(WeaverMessages.CANT_THROW_CHECKED, resolvedTypeX, this), // from
  432. // advice
  433. // in
  434. // \
  435. // '"
  436. // +
  437. // munger
  438. // .
  439. // +
  440. // "\'"
  441. // ,
  442. getSourceLocation(), munger.getSourceLocation());
  443. }
  444. return true;
  445. }
  446. private boolean isDeclaredException(ResolvedType resolvedTypeX, Member member) {
  447. ResolvedType[] excs = getIWorld().resolve(member.getExceptions(getIWorld()));
  448. for (int i = 0, len = excs.length; i < len; i++) {
  449. if (excs[i].isAssignableFrom(resolvedTypeX)) {
  450. return true;
  451. }
  452. }
  453. return false;
  454. }
  455. public void addMunger(ShadowMunger munger) {
  456. if (checkMunger(munger)) {
  457. if (mungers == Collections.EMPTY_LIST) {
  458. mungers = new ArrayList<ShadowMunger>();
  459. }
  460. this.mungers.add(munger);
  461. }
  462. }
  463. public final void implement() {
  464. sortMungers();
  465. if (mungers == null) {
  466. return;
  467. }
  468. prepareForMungers();
  469. implementMungers();
  470. }
  471. private void sortMungers() {
  472. List sorted = PartialOrder.sort(mungers);
  473. // Bunch of code to work out whether to report xlints for advice that isn't ordered at this Joinpoint
  474. possiblyReportUnorderedAdvice(sorted);
  475. if (sorted == null) {
  476. // this means that we have circular dependencies
  477. for (ShadowMunger m : mungers) {
  478. getIWorld().getMessageHandler().handleMessage(
  479. MessageUtil.error(WeaverMessages.format(WeaverMessages.CIRCULAR_DEPENDENCY, this), m.getSourceLocation()));
  480. }
  481. }
  482. mungers = sorted;
  483. }
  484. // not quite optimal... but the xlint is ignore by default
  485. private void possiblyReportUnorderedAdvice(List sorted) {
  486. if (sorted != null && getIWorld().getLint().unorderedAdviceAtShadow.isEnabled() && mungers.size() > 1) {
  487. // Stores a set of strings of the form 'aspect1:aspect2' which indicates there is no
  488. // precedence specified between the two aspects at this shadow.
  489. Set<String> clashingAspects = new HashSet<String>();
  490. int max = mungers.size();
  491. // Compare every pair of advice mungers
  492. for (int i = max - 1; i >= 0; i--) {
  493. for (int j = 0; j < i; j++) {
  494. Object a = mungers.get(i);
  495. Object b = mungers.get(j);
  496. // Make sure they are the right type
  497. if (a instanceof Advice && b instanceof Advice) {
  498. Advice adviceA = (Advice) a;
  499. Advice adviceB = (Advice) b;
  500. if (!adviceA.concreteAspect.equals(adviceB.concreteAspect)) {
  501. AdviceKind adviceKindA = adviceA.getKind();
  502. AdviceKind adviceKindB = adviceB.getKind();
  503. // make sure they are the nice ones (<6) and not any synthetic advice ones we
  504. // create to support other features of the language.
  505. if (adviceKindA.getKey() < (byte) 6 && adviceKindB.getKey() < (byte) 6
  506. && adviceKindA.getPrecedence() == adviceKindB.getPrecedence()) {
  507. // Ask the world if it knows about precedence between these
  508. Integer order = getIWorld().getPrecedenceIfAny(adviceA.concreteAspect, adviceB.concreteAspect);
  509. if (order != null && order.equals(new Integer(0))) {
  510. String key = adviceA.getDeclaringAspect() + ":" + adviceB.getDeclaringAspect();
  511. String possibleExistingKey = adviceB.getDeclaringAspect() + ":" + adviceA.getDeclaringAspect();
  512. if (!clashingAspects.contains(possibleExistingKey)) {
  513. clashingAspects.add(key);
  514. }
  515. }
  516. }
  517. }
  518. }
  519. }
  520. }
  521. for (Iterator<String> iter = clashingAspects.iterator(); iter.hasNext();) {
  522. String element = iter.next();
  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. StringBuffer sb = new StringBuffer();
  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<Kind>();
  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. }