選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

AjPipeliningCompilerAdapter.java 28KB

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