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

15 years ago
15 years ago
15 years ago
14 years ago
15 years ago
14 years ago
15 years ago
15 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
15 years ago
15 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
13 years ago
15 years ago
13 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
15 years ago
15 years ago
13 years ago
15 years ago
13 years ago
13 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
15 years ago
15 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
11 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
15 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
13 years ago
15 years ago
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. }