Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

AjPipeliningCompilerAdapter.java 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*******************************************************************************
  2. * Copyright (c) 2006 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * Andy Clement - initial implementation 26Jul06
  10. *******************************************************************************/
  11. package org.aspectj.ajdt.internal.compiler;
  12. import java.io.IOException;
  13. import java.util.ArrayList;
  14. import java.util.HashMap;
  15. import java.util.Hashtable;
  16. import java.util.Iterator;
  17. import java.util.List;
  18. import java.util.Map;
  19. import org.aspectj.ajdt.internal.compiler.ast.AddAtAspectJAnnotationsVisitor;
  20. import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
  21. import org.aspectj.ajdt.internal.compiler.ast.ValidateAtAspectJAnnotationsVisitor;
  22. import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
  23. import org.aspectj.ajdt.internal.core.builder.AjState;
  24. import org.aspectj.bridge.IMessage;
  25. import org.aspectj.bridge.IMessageHandler;
  26. import org.aspectj.bridge.IProgressListener;
  27. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  28. import org.aspectj.bridge.context.ContextToken;
  29. import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
  30. import org.aspectj.org.eclipse.jdt.internal.compiler.Compiler;
  31. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
  32. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
  33. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
  34. import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
  35. import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
  36. import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
  37. import org.aspectj.util.CharOperation;
  38. import org.aspectj.weaver.bcel.BcelWeaver;
  39. import org.aspectj.weaver.bcel.BcelWorld;
  40. import org.aspectj.weaver.patterns.CflowPointcut;
  41. /**
  42. * Adapts standard JDT Compiler to add in AspectJ specific behaviours.
  43. * This version implements pipelining - where files are compiled and then
  44. * woven immediately, unlike AjCompilerAdapter which compiles everything
  45. * then weaves everything. (One small note: because all aspects have to
  46. * be known before weaving can take place, the weaving pipeline is 'stalled'
  47. * until all aspects have been compiled).
  48. *
  49. * The basic strategy is this:
  50. *
  51. * 1. diet parse all input source files
  52. * - this is enough for us to implement ITD matching
  53. * - this enables us to determine which are aspects
  54. * 2. sort the input files, aspects first
  55. * - keep a note of how many files contain aspects
  56. * 3. if there are aspects, mark the pipeline as 'stalled'
  57. * 3. repeat
  58. * 3a. compile a file
  59. * 3b. have we now compiled all aspects?
  60. * NO - put file in a weave pending queue
  61. * YES- unstall the 'pipeline'
  62. * 3c. is the pipeline stalled?
  63. * NO - weave all pending files and this one
  64. * YES- do nothing
  65. *
  66. * Complexities arise because of:
  67. * - what does -XterminateAfterCompilation mean? since there is no stage
  68. * where everything is compiled and nothing is woven
  69. *
  70. *
  71. * Here is the compiler loop difference when pipelining.
  72. *
  73. * the old way:
  74. * Finished diet parsing [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java]
  75. * Finished diet parsing [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java]
  76. * > AjLookupEnvironment.completeTypeBindings()
  77. * < AjLookupEnvironment.completeTypeBindings()
  78. * compiling C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java
  79. * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java)
  80. * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java)
  81. * compiling C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java
  82. * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java)
  83. * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java)
  84. * >AjCompilerAdapter.weave()
  85. * >BcelWeaver.prepareForWeave
  86. * <BcelWeaver.prepareForWeave
  87. * woven class ClassOne (from C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java)
  88. * woven class ClassTwo (from C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java)
  89. * <AjCompilerAdapter.weave()
  90. *
  91. * the new way (see the compiling/weaving mixed up):
  92. * Finished diet parsing [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java]
  93. * Finished diet parsing [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java]
  94. * >AjLookupEnvironment.completeTypeBindings()
  95. * <AjLookupEnvironment.completeTypeBindings()
  96. * compiling C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java
  97. * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java)
  98. * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java)
  99. * >AjCompilerAdapter.weave()
  100. * >BcelWeaver.prepareForWeave
  101. * <BcelWeaver.prepareForWeave
  102. * woven class ClassOne (from C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java)
  103. * <AjCompilerAdapter.weave()
  104. * compiling C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java
  105. * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java)
  106. * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java)
  107. * >AjCompilerAdapter.weave()
  108. * woven class ClassTwo (from C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java)
  109. * <AjCompilerAdapter.weave()
  110. *
  111. *
  112. */
  113. public class AjPipeliningCompilerAdapter extends AbstractCompilerAdapter {
  114. private Compiler compiler;
  115. private BcelWeaver weaver;
  116. private EclipseFactory eWorld;
  117. private boolean isBatchCompile;
  118. private boolean reportedErrors;
  119. private boolean isXTerminateAfterCompilation;
  120. private boolean proceedOnError;
  121. private boolean inJava5Mode;
  122. private boolean noAtAspectJAnnotationProcessing;
  123. private IIntermediateResultsRequestor intermediateResultsRequestor;
  124. private IProgressListener progressListener;
  125. private IOutputClassFileNameProvider outputFileNameProvider;
  126. private IBinarySourceProvider binarySourceProvider;
  127. private WeaverMessageHandler weaverMessageHandler;
  128. private Map /* fileName > List<UnwovenClassFile> */ binarySourceSetForFullWeave = new HashMap();
  129. private ContextToken processingToken = null;
  130. private ContextToken resolvingToken = null;
  131. private ContextToken analysingToken = null;
  132. private ContextToken generatingToken = null;
  133. private AjState incrementalCompilationState;
  134. // Maintains a list of whats weaving - whilst the pipeline is stalled, this accumulates aspects.
  135. List /*InterimResult*/ resultsPendingWeave = new ArrayList();
  136. // pipelining info
  137. private boolean pipelineStalled = true;
  138. private boolean weaverInitialized = false;
  139. private int toWaitFor;
  140. // If we determine we are going to drop back to a full build - don't need to tell the weaver to report adviceDidNotMatch
  141. private boolean droppingBackToFullBuild;
  142. /**
  143. * Create an adapter, and tell it everything it needs to now to drive the AspectJ
  144. * parts of a compile cycle.
  145. * @param compiler the JDT compiler that produces class files from source
  146. * @param isBatchCompile true if this is a full build (non-incremental)
  147. * @param world the bcelWorld used for type resolution during weaving
  148. * @param weaver the weaver
  149. * @param intRequestor recipient of interim compilation results from compiler (pre-weave)
  150. * @param outputFileNameProvider implementor of a strategy providing output file names for results
  151. * @param binarySourceEntries binary source that we didn't compile, but that we need to weave
  152. * @param resultSetForFullWeave if we are doing an incremental build, and the weaver determines
  153. * that we need to weave the world, this is the set of intermediate
  154. * results that will be passed to the weaver.
  155. */
  156. public AjPipeliningCompilerAdapter(Compiler compiler,
  157. boolean isBatchCompile,
  158. BcelWorld world,
  159. BcelWeaver weaver,
  160. EclipseFactory eFactory,
  161. IIntermediateResultsRequestor intRequestor,
  162. IProgressListener progressListener,
  163. IOutputClassFileNameProvider outputFileNameProvider,
  164. IBinarySourceProvider binarySourceProvider,
  165. Map fullBinarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
  166. boolean isXterminateAfterCompilation,
  167. boolean proceedOnError,
  168. boolean noAtAspectJProcessing,
  169. AjState incrementalCompilationState) {
  170. this.compiler = compiler;
  171. this.isBatchCompile = isBatchCompile;
  172. this.weaver = weaver;
  173. this.intermediateResultsRequestor = intRequestor;
  174. this.progressListener = progressListener;
  175. this.outputFileNameProvider = outputFileNameProvider;
  176. this.binarySourceProvider = binarySourceProvider;
  177. this.isXTerminateAfterCompilation = isXterminateAfterCompilation;
  178. this.proceedOnError = proceedOnError;
  179. this.binarySourceSetForFullWeave = fullBinarySourceEntries;
  180. this.eWorld = eFactory;
  181. this.inJava5Mode = false;
  182. this.noAtAspectJAnnotationProcessing = noAtAspectJProcessing;
  183. this.incrementalCompilationState = incrementalCompilationState;
  184. if (compiler.options.complianceLevel == CompilerOptions.JDK1_5) inJava5Mode = true;
  185. IMessageHandler msgHandler = world.getMessageHandler();
  186. // Do we need to reset the message handler or create a new one? (This saves a ton of memory lost on incremental compiles...)
  187. if (msgHandler instanceof WeaverMessageHandler) {
  188. ((WeaverMessageHandler)msgHandler).resetCompiler(compiler);
  189. weaverMessageHandler = (WeaverMessageHandler)msgHandler;
  190. } else {
  191. weaverMessageHandler = new WeaverMessageHandler(msgHandler, compiler);
  192. world.setMessageHandler(weaverMessageHandler);
  193. }
  194. }
  195. // the compilation lifecycle methods below are called in order as compilation progresses...
  196. /**
  197. * In a pipelining compilation system, we need to ensure aspects are through the pipeline first. Only
  198. * when they are all through (and therefore we know about all static/dynamic crosscutting) can be
  199. * proceed to weave anything. Effectively the weaving part of the pipeline stalls until all the
  200. * aspects have been fully compiled. This method sorts the compilation units such that any containing
  201. * aspects are fully compiled first and it keeps a note on how long it should stall the pipeline before
  202. * commencing weaving.
  203. */
  204. public void afterDietParsing(CompilationUnitDeclaration[] units) {
  205. if (debugPipeline) System.err.println("> afterDietParsing: there are "+(units==null?0:units.length)+" units to sort");
  206. if (!reportedErrors && units!=null) {
  207. for (int i = 0; i < units.length; i++) {
  208. if (units[i]!=null && units[i].compilationResult!=null && units[i].compilationResult.hasErrors()) {
  209. reportedErrors = true;
  210. break; // TODO break or exit here?
  211. }
  212. }
  213. }
  214. // Break the units into two lists...
  215. List aspects = new ArrayList();
  216. List nonaspects = new ArrayList();
  217. for (int i=0;i<units.length;i++) {
  218. if (containsAnAspect(units[i])) aspects.add(units[i]); else nonaspects.add(units[i]);
  219. }
  220. if (units == null) return; // what does this mean?
  221. // ...and put them back together, aspects first
  222. int posn = 0;
  223. for (Iterator iter = aspects.iterator(); iter.hasNext();) {
  224. units[posn++] = (CompilationUnitDeclaration) iter.next();
  225. }
  226. for (Iterator iter = nonaspects.iterator(); iter.hasNext();) {
  227. units[posn++] = (CompilationUnitDeclaration) iter.next();
  228. }
  229. // Work out how long to stall the pipeline
  230. toWaitFor = aspects.size();
  231. if (debugPipeline) System.err.println("< afterDietParsing: stalling pipeline for "+toWaitFor+" source files");
  232. // TESTING
  233. if (pipelineTesting) {
  234. if (pipelineOutput ==null) pipelineOutput = new Hashtable();
  235. pipelineOutput.put("filesContainingAspects", new Integer(toWaitFor).toString());
  236. StringBuffer order = new StringBuffer();
  237. order.append("[");
  238. for (int i = 0; i < units.length; i++) {
  239. if (i!=0) order.append(",");
  240. CompilationUnitDeclaration declaration = units[i];
  241. String filename = new String(declaration.getFileName());
  242. int idx = filename.lastIndexOf('/');
  243. if (idx>0) filename=filename.substring(idx+1);
  244. idx = filename.lastIndexOf('\\');
  245. if (idx>0) filename=filename.substring(idx+1);
  246. order.append(filename);
  247. }
  248. order.append("]");
  249. pipelineOutput.put("weaveOrder", order.toString());
  250. }
  251. }
  252. public void beforeCompiling(ICompilationUnit[] sourceUnits) {
  253. resultsPendingWeave = new ArrayList();
  254. reportedErrors = false;
  255. droppingBackToFullBuild=false;
  256. }
  257. public void beforeProcessing(CompilationUnitDeclaration unit) {
  258. if (debugPipeline) System.err.println("compiling " + new String(unit.getFileName()));
  259. eWorld.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
  260. processingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_COMPILATION_UNIT,unit.getFileName());
  261. if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
  262. ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ADDING_AT_ASPECTJ_ANNOTATIONS, unit.getFileName());
  263. AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit);
  264. unit.traverse(atAspectJVisitor, unit.scope);
  265. CompilationAndWeavingContext.leavingPhase(tok);
  266. }
  267. }
  268. public void beforeResolving(CompilationUnitDeclaration unit) {
  269. resolvingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.RESOLVING_COMPILATION_UNIT, unit.getFileName());
  270. }
  271. public void afterResolving(CompilationUnitDeclaration unit) {
  272. if (resolvingToken != null)
  273. CompilationAndWeavingContext.leavingPhase(resolvingToken);
  274. }
  275. public void beforeAnalysing(CompilationUnitDeclaration unit) {
  276. analysingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ANALYSING_COMPILATION_UNIT, unit.getFileName());
  277. if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
  278. ValidateAtAspectJAnnotationsVisitor atAspectJVisitor = new ValidateAtAspectJAnnotationsVisitor(unit);
  279. unit.traverse(atAspectJVisitor, unit.scope);
  280. }
  281. }
  282. public void afterAnalysing(CompilationUnitDeclaration unit) {
  283. if (analysingToken != null)
  284. CompilationAndWeavingContext.leavingPhase(analysingToken);
  285. }
  286. public void beforeGenerating(CompilationUnitDeclaration unit) {
  287. generatingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.GENERATING_UNWOVEN_CODE_FOR_COMPILATION_UNIT, unit.getFileName());
  288. }
  289. public void afterGenerating(CompilationUnitDeclaration unit) {
  290. if (generatingToken != null)
  291. CompilationAndWeavingContext.leavingPhase(generatingToken);
  292. }
  293. public void afterCompiling(CompilationUnitDeclaration[] units) {
  294. this.eWorld.cleanup();
  295. if (!weaverInitialized) { // nothing got compiled, doesnt mean there is nothing to do... (binary weaving)
  296. if (!(isXTerminateAfterCompilation || (reportedErrors && !proceedOnError))) {
  297. // acceptResult(unit.compilationResult);
  298. // } else {
  299. try {
  300. if (weaveQueuedEntries()) droppingBackToFullBuild=true;
  301. } catch (IOException ex) {
  302. AbortCompilation ac = new AbortCompilation(null,ex);
  303. throw ac;
  304. }
  305. }
  306. }
  307. postWeave();
  308. try {
  309. // not great ... but one more check before we continue, see pr132314
  310. if (!reportedErrors && units!=null) {
  311. for (int i = 0; i < units.length; i++) {
  312. if (units[i]!=null && units[i].compilationResult!=null && units[i].compilationResult.hasErrors()) {
  313. reportedErrors = true;
  314. break;
  315. }
  316. }
  317. }
  318. if (isXTerminateAfterCompilation || (reportedErrors && !proceedOnError)) {
  319. // no point weaving... just tell the requestor we're done
  320. notifyRequestor();
  321. } else {
  322. // weave(); // notification happens as weave progresses...
  323. // weaver.getWorld().flush(); // pr152257
  324. }
  325. // } catch (IOException ex) {
  326. // AbortCompilation ac = new AbortCompilation(null,ex);
  327. // throw ac;
  328. } catch (RuntimeException rEx) {
  329. if (rEx instanceof AbortCompilation) throw rEx; // Don't wrap AbortCompilation exceptions!
  330. // This will be unwrapped in Compiler.handleInternalException() and the nested
  331. // RuntimeException thrown back to the original caller - which is AspectJ
  332. // which will then then log it as a compiler problem.
  333. throw new AbortCompilation(true,rEx);
  334. }
  335. }
  336. public void afterProcessing(CompilationUnitDeclaration unit, int unitIndex) {
  337. CompilationAndWeavingContext.leavingPhase(processingToken);
  338. eWorld.finishedCompilationUnit(unit);
  339. InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult,outputFileNameProvider);
  340. if (unit.compilationResult.hasErrors()) reportedErrors = true;
  341. if (intermediateResultsRequestor != null) {
  342. intermediateResultsRequestor.acceptResult(intRes);
  343. }
  344. if (isXTerminateAfterCompilation || (reportedErrors && !proceedOnError)) {
  345. acceptResult(unit.compilationResult);
  346. } else {
  347. queueForWeaving(intRes);
  348. }
  349. }
  350. private void queueForWeaving(InterimCompilationResult intRes) {
  351. resultsPendingWeave.add(intRes);
  352. if (pipelineStalled) {
  353. if (resultsPendingWeave.size()>=toWaitFor) pipelineStalled = false;
  354. }
  355. if (pipelineStalled) return;
  356. try {
  357. if (weaveQueuedEntries()) droppingBackToFullBuild=true;
  358. } catch (IOException ex) {
  359. AbortCompilation ac = new AbortCompilation(null,ex);
  360. throw ac;
  361. }
  362. }
  363. /*
  364. * Called from the weaverAdapter once it has finished weaving the class files
  365. * associated with a given compilation result.
  366. */
  367. public void acceptResult(CompilationResult result) {
  368. compiler.requestor.acceptResult(result.tagAsAccepted());
  369. if (compiler.unitsToProcess != null) {
  370. for (int i = 0; i < compiler.unitsToProcess.length; i++) {
  371. if (compiler.unitsToProcess[i] != null) {
  372. if (compiler.unitsToProcess[i].compilationResult == result) {
  373. compiler.unitsToProcess[i].cleanUp();
  374. compiler.unitsToProcess[i] = null;
  375. }
  376. }
  377. }
  378. }
  379. }
  380. // helper methods...
  381. // ==================================================================================
  382. private List getBinarySourcesFrom(Map binarySourceEntries) {
  383. // Map is fileName |-> List<UnwovenClassFile>
  384. List ret = new ArrayList();
  385. for (Iterator binIter = binarySourceEntries.keySet().iterator(); binIter.hasNext();) {
  386. String sourceFileName = (String) binIter.next();
  387. List unwovenClassFiles = (List) binarySourceEntries.get(sourceFileName);
  388. // XXX - see bugs 57432,58679 - final parameter on next call should be "compiler.options.maxProblemsPerUnit"
  389. CompilationResult result = new CompilationResult(sourceFileName.toCharArray(),0,0,Integer.MAX_VALUE);
  390. result.noSourceAvailable();
  391. InterimCompilationResult binarySource =
  392. new InterimCompilationResult(result,unwovenClassFiles);
  393. ret.add(binarySource);
  394. }
  395. return ret;
  396. }
  397. private void notifyRequestor() {
  398. for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
  399. InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
  400. compiler.requestor.acceptResult(iresult.result().tagAsAccepted());
  401. }
  402. }
  403. /** Return true if we've decided to drop back to a full build (too much has changed) */
  404. private boolean weaveQueuedEntries() throws IOException {
  405. if (debugPipeline)System.err.println(">.weaveQueuedEntries()");
  406. for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
  407. InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
  408. for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
  409. weaver.addClassFile(iresult.unwovenClassFiles()[i]);
  410. }
  411. }
  412. ensureWeaverInitialized(); // by doing this only once, are we saying needToReweaveWorld can't change once the aspects have been stuffed into the weaver?
  413. if (weaver.needToReweaveWorld() && !isBatchCompile) return true;
  414. weaver.weave(new WeaverAdapter(this,weaverMessageHandler,progressListener));
  415. resultsPendingWeave.clear(); // dont need to do those again
  416. this.eWorld.minicleanup();
  417. if (debugPipeline)System.err.println("<.weaveQueuedEntries()");
  418. return false;
  419. }
  420. private void ensureWeaverInitialized() {
  421. if (weaverInitialized) return;
  422. weaverInitialized=true;
  423. weaver.setIsBatchWeave(isBatchCompile);
  424. weaver.prepareForWeave();
  425. if (weaver.needToReweaveWorld()) {
  426. if (!isBatchCompile) {
  427. //force full recompilation from source
  428. this.incrementalCompilationState.forceBatchBuildNextTimeAround();
  429. return;
  430. }
  431. resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
  432. } else {
  433. Map binarySourcesToAdd = binarySourceProvider.getBinarySourcesForThisWeave();
  434. resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourcesToAdd));
  435. }
  436. }
  437. private void weave() throws IOException {
  438. if (debugPipeline)System.err.println("> weave()");
  439. // ensure weaver state is set up correctly
  440. for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
  441. InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
  442. for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
  443. weaver.addClassFile(iresult.unwovenClassFiles()[i]);
  444. }
  445. }
  446. weaver.setIsBatchWeave(isBatchCompile);
  447. weaver.prepareForWeave();
  448. if (weaver.needToReweaveWorld()) {
  449. if (!isBatchCompile) {
  450. //force full recompilation from source
  451. this.incrementalCompilationState.forceBatchBuildNextTimeAround();
  452. return;
  453. }
  454. resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
  455. } else {
  456. Map binarySourcesToAdd = binarySourceProvider.getBinarySourcesForThisWeave();
  457. resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourcesToAdd));
  458. }
  459. try {
  460. weaver.weave(new WeaverAdapter(this,weaverMessageHandler,progressListener));
  461. } finally {
  462. CflowPointcut.clearCaches();
  463. weaver.tidyUp();
  464. IMessageHandler imh = weaver.getWorld().getMessageHandler();
  465. if (imh instanceof WeaverMessageHandler)
  466. ((WeaverMessageHandler)imh).resetCompiler(null);
  467. }
  468. if (debugPipeline)System.err.println("< weave()");
  469. }
  470. private void postWeave() {
  471. if (debugPipeline)System.err.println("> postWeave()");
  472. IMessageHandler imh = weaver.getWorld().getMessageHandler();
  473. CflowPointcut.clearCaches();
  474. if (imh instanceof WeaverMessageHandler)
  475. ((WeaverMessageHandler)imh).setCurrentResult(null);
  476. if (!droppingBackToFullBuild) weaver.allWeavingComplete();
  477. weaver.tidyUp();
  478. if (imh instanceof WeaverMessageHandler)
  479. ((WeaverMessageHandler)imh).resetCompiler(null);
  480. if (debugPipeline)System.err.println("< postWeave()");
  481. }
  482. /**
  483. * Return true if the compilation unit declaration contains an aspect declaration (either code style
  484. * or annotation style). It must inspect the multiple types that may be in a compilation
  485. * unit declaration and any inner types.
  486. */
  487. private boolean containsAnAspect(CompilationUnitDeclaration cud) {
  488. TypeDeclaration[] typeDecls = cud.types;
  489. if (typeDecls!=null) {
  490. for (int i = 0; i < typeDecls.length; i++) { // loop through top level types in the file
  491. TypeDeclaration declaration = typeDecls[i];
  492. if (isAspect(declaration)) return true;
  493. if (declaration.memberTypes!=null) {
  494. TypeDeclaration[] memberTypes = declaration.memberTypes;
  495. for (int j = 0; j < memberTypes.length; j++) { // loop through inner types
  496. if (containsAnAspect(memberTypes[j])) return true;
  497. }
  498. }
  499. }
  500. }
  501. return false;
  502. }
  503. private boolean containsAnAspect(TypeDeclaration tDecl) {
  504. if (isAspect(tDecl)) return true;
  505. if (tDecl.memberTypes!=null) {
  506. TypeDeclaration[] memberTypes = tDecl.memberTypes;
  507. for (int j = 0; j < memberTypes.length; j++) { // loop through inner types
  508. if (containsAnAspect(memberTypes[j])) return true;
  509. }
  510. }
  511. return false;
  512. }
  513. private static final char[] aspectSig = "Lorg/aspectj/lang/annotation/Aspect;".toCharArray();
  514. private boolean isAspect(TypeDeclaration declaration) {
  515. if (declaration instanceof AspectDeclaration) return true; // code style
  516. else if (declaration.annotations!=null) { // check for annotation style
  517. for (int index = 0; index < declaration.annotations.length; index++) {
  518. TypeDeclaration.resolveAnnotations(declaration.staticInitializerScope, declaration.annotations, declaration.binding); // force annotation resolution
  519. Annotation a = declaration.annotations[index];
  520. if (a.resolvedType == null) continue; // another problem is being reported, so don't crash here
  521. if (CharOperation.equals(a.resolvedType.signature(),aspectSig)) return true;
  522. }
  523. }
  524. return false;
  525. }
  526. // ---
  527. /**
  528. * SECRET: FOR TESTING - this can be used to collect information that tests can verify.
  529. */
  530. public static boolean pipelineTesting = false;
  531. public static Hashtable pipelineOutput = null;
  532. // Keys into pipelineOutput:
  533. // compileOrder "[XXX,YYY]" a list of the order in which files will be woven (aspects should be first)
  534. // filesContainingAspects "NNN" how many input source files have aspects inside
  535. //
  536. public static String getPipelineDebugOutput(String key) {
  537. if (pipelineOutput==null) return "";
  538. return (String)pipelineOutput.get(key);
  539. }
  540. private final boolean debugPipeline = false;
  541. public List getResultsPendingWeave() { return resultsPendingWeave;}
  542. }