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.

AjCompilerAdapter.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /*******************************************************************************
  2. * Copyright (c) 2004 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. * IBM Corporation - initial API and implementation
  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.List;
  16. import java.util.Map;
  17. import org.aspectj.ajdt.internal.compiler.ast.AddAtAspectJAnnotationsVisitor;
  18. import org.aspectj.ajdt.internal.compiler.ast.ValidateAtAspectJAnnotationsVisitor;
  19. import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
  20. import org.aspectj.ajdt.internal.core.builder.AjState;
  21. import org.aspectj.bridge.IMessage;
  22. import org.aspectj.bridge.IMessageHandler;
  23. import org.aspectj.bridge.IProgressListener;
  24. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  25. import org.aspectj.bridge.context.ContextToken;
  26. import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
  27. import org.aspectj.org.eclipse.jdt.internal.compiler.Compiler;
  28. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
  29. import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
  30. import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
  31. import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
  32. import org.aspectj.weaver.bcel.BcelWeaver;
  33. import org.aspectj.weaver.bcel.BcelWorld;
  34. /**
  35. * @author colyer
  36. *
  37. * Adapts standard JDT Compiler to add in AspectJ specific behaviours.
  38. */
  39. public class AjCompilerAdapter extends AbstractCompilerAdapter {
  40. private Compiler compiler;
  41. private BcelWeaver weaver;
  42. private EclipseFactory eWorld;
  43. private boolean isBatchCompile;
  44. private boolean reportedErrors;
  45. private boolean isXTerminateAfterCompilation;
  46. private boolean proceedOnError;
  47. private boolean inJava5Mode;
  48. private boolean reflectable;
  49. private boolean noAtAspectJAnnotationProcessing;
  50. private IIntermediateResultsRequestor intermediateResultsRequestor;
  51. private IProgressListener progressListener;
  52. private IOutputClassFileNameProvider outputFileNameProvider;
  53. private IBinarySourceProvider binarySourceProvider;
  54. private WeaverMessageHandler weaverMessageHandler;
  55. private Map /* fileName |-> List<UnwovenClassFile> */binarySourceSetForFullWeave = new HashMap();
  56. private ContextToken processingToken = null;
  57. private ContextToken resolvingToken = null;
  58. private ContextToken analysingToken = null;
  59. private ContextToken generatingToken = null;
  60. private AjState incrementalCompilationState;
  61. List /* InterimResult */resultsPendingWeave = new ArrayList();
  62. /**
  63. * Create an adapter, and tell it everything it needs to now to drive the AspectJ parts of a compile cycle.
  64. *
  65. * @param compiler the JDT compiler that produces class files from source
  66. * @param isBatchCompile true if this is a full build (non-incremental)
  67. * @param world the bcelWorld used for type resolution during weaving
  68. * @param weaver the weaver
  69. * @param intRequestor recipient of interim compilation results from compiler (pre-weave)
  70. * @param outputFileNameProvider implementor of a strategy providing output file names for results
  71. * @param binarySourceProvider binary source that we didn't compile, but that we need to weave
  72. * @param incrementalCompilationState if we are doing an incremental build, and the weaver determines that we need to weave the world,
  73. * this is the set of intermediate results that will be passed to the weaver.
  74. */
  75. public AjCompilerAdapter(Compiler compiler, boolean isBatchCompile, BcelWorld world, BcelWeaver weaver,
  76. EclipseFactory eFactory, IIntermediateResultsRequestor intRequestor, IProgressListener progressListener,
  77. IOutputClassFileNameProvider outputFileNameProvider, IBinarySourceProvider binarySourceProvider,
  78. Map fullBinarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
  79. boolean isXterminateAfterCompilation, boolean proceedOnError, boolean noAtAspectJProcessing, boolean reflectable,
  80. AjState incrementalCompilationState) {
  81. this.compiler = compiler;
  82. this.isBatchCompile = isBatchCompile;
  83. this.weaver = weaver;
  84. this.intermediateResultsRequestor = intRequestor;
  85. this.progressListener = progressListener;
  86. this.outputFileNameProvider = outputFileNameProvider;
  87. this.binarySourceProvider = binarySourceProvider;
  88. this.isXTerminateAfterCompilation = isXterminateAfterCompilation;
  89. this.proceedOnError = proceedOnError;
  90. this.binarySourceSetForFullWeave = fullBinarySourceEntries;
  91. this.eWorld = eFactory;
  92. this.reflectable = reflectable;
  93. this.inJava5Mode = false;
  94. this.noAtAspectJAnnotationProcessing = noAtAspectJProcessing;
  95. this.incrementalCompilationState = incrementalCompilationState;
  96. if (compiler.options.complianceLevel >= ClassFileConstants.JDK1_5) {
  97. inJava5Mode = true;
  98. }
  99. IMessageHandler msgHandler = world.getMessageHandler();
  100. // Do we need to reset the message handler or create a new one? (This saves a ton of memory lost on incremental compiles...)
  101. if (msgHandler instanceof WeaverMessageHandler) {
  102. ((WeaverMessageHandler) msgHandler).resetCompiler(compiler);
  103. weaverMessageHandler = (WeaverMessageHandler) msgHandler;
  104. } else {
  105. weaverMessageHandler = new WeaverMessageHandler(msgHandler, compiler);
  106. world.setMessageHandler(weaverMessageHandler);
  107. }
  108. }
  109. // the compilation lifecycle methods below are called in order as compilation progresses...
  110. public void beforeCompiling(ICompilationUnit[] sourceUnits) {
  111. resultsPendingWeave = new ArrayList();
  112. reportedErrors = false;
  113. }
  114. public void beforeProcessing(CompilationUnitDeclaration unit) {
  115. eWorld.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
  116. processingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_COMPILATION_UNIT, unit
  117. .getFileName());
  118. if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
  119. ContextToken tok = CompilationAndWeavingContext.enteringPhase(
  120. CompilationAndWeavingContext.ADDING_AT_ASPECTJ_ANNOTATIONS, unit.getFileName());
  121. AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit, reflectable);
  122. unit.traverse(atAspectJVisitor, unit.scope);
  123. CompilationAndWeavingContext.leavingPhase(tok);
  124. }
  125. }
  126. public void beforeResolving(CompilationUnitDeclaration unit) {
  127. resolvingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.RESOLVING_COMPILATION_UNIT, unit
  128. .getFileName());
  129. }
  130. public void afterResolving(CompilationUnitDeclaration unit) {
  131. if (resolvingToken != null) {
  132. CompilationAndWeavingContext.leavingPhase(resolvingToken);
  133. }
  134. }
  135. public void beforeAnalysing(CompilationUnitDeclaration unit) {
  136. analysingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ANALYSING_COMPILATION_UNIT, unit
  137. .getFileName());
  138. if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
  139. ValidateAtAspectJAnnotationsVisitor atAspectJVisitor = new ValidateAtAspectJAnnotationsVisitor(unit);
  140. unit.traverse(atAspectJVisitor, unit.scope);
  141. }
  142. }
  143. public void afterAnalysing(CompilationUnitDeclaration unit) {
  144. if (analysingToken != null) {
  145. CompilationAndWeavingContext.leavingPhase(analysingToken);
  146. }
  147. }
  148. public void beforeGenerating(CompilationUnitDeclaration unit) {
  149. generatingToken = CompilationAndWeavingContext.enteringPhase(
  150. CompilationAndWeavingContext.GENERATING_UNWOVEN_CODE_FOR_COMPILATION_UNIT, unit.getFileName());
  151. }
  152. public void afterGenerating(CompilationUnitDeclaration unit) {
  153. if (generatingToken != null) {
  154. CompilationAndWeavingContext.leavingPhase(generatingToken);
  155. }
  156. }
  157. public void afterCompiling(CompilationUnitDeclaration[] units) {
  158. this.eWorld.cleanup();
  159. try {
  160. // not great ... but one more check before we continue, see pr132314
  161. if (!reportedErrors && units != null) {
  162. for (CompilationUnitDeclaration unit : units) {
  163. if (unit != null && unit.compilationResult != null && unit.compilationResult.hasErrors()) {
  164. reportedErrors = true;
  165. break;
  166. }
  167. }
  168. }
  169. if (isXTerminateAfterCompilation || (reportedErrors && !proceedOnError)) {
  170. // no point weaving... just tell the requestor we're done
  171. notifyRequestor();
  172. } else {
  173. weave(); // notification happens as weave progresses...
  174. // weaver.getWorld().flush(); // pr152257
  175. }
  176. } catch (IOException ex) {
  177. AbortCompilation ac = new AbortCompilation(null, ex);
  178. throw ac;
  179. } catch (RuntimeException rEx) {
  180. if (rEx instanceof AbortCompilation) {
  181. throw rEx; // Don't wrap AbortCompilation exceptions!
  182. }
  183. // This will be unwrapped in Compiler.handleInternalException() and the nested
  184. // RuntimeException thrown back to the original caller - which is AspectJ
  185. // which will then then log it as a compiler problem.
  186. throw new AbortCompilation(true, rEx);
  187. }
  188. }
  189. public void afterProcessing(CompilationUnitDeclaration unit, int unitIndex) {
  190. CompilationAndWeavingContext.leavingPhase(processingToken);
  191. eWorld.finishedCompilationUnit(unit);
  192. InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult, outputFileNameProvider);
  193. if (unit.compilationResult.hasErrors()) {
  194. reportedErrors = true;
  195. }
  196. if (intermediateResultsRequestor != null) {
  197. intermediateResultsRequestor.acceptResult(intRes);
  198. }
  199. if (isXTerminateAfterCompilation) {
  200. acceptResult(unit.compilationResult);
  201. } else {
  202. resultsPendingWeave.add(intRes);
  203. }
  204. }
  205. // public void beforeResolving(CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean
  206. // analyzeCode, boolean generateCode) {
  207. // resultsPendingWeave = new ArrayList();
  208. // reportedErrors = false;
  209. // }
  210. //
  211. // public void afterResolving(CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean
  212. // analyzeCode, boolean generateCode) {
  213. // InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult,outputFileNameProvider);
  214. // if (unit.compilationResult.hasErrors()) reportedErrors = true;
  215. // if (isXNoWeave || !generateCode) {
  216. // acceptResult(unit.compilationResult);
  217. // } else if (generateCode){
  218. // resultsPendingWeave.add(intRes);
  219. // try {
  220. // weave();
  221. // } catch (IOException ex) {
  222. // AbortCompilation ac = new AbortCompilation(null,ex);
  223. // throw ac;
  224. // }
  225. // }
  226. // }
  227. // helper methods...
  228. // ==================================================================================
  229. /*
  230. * Called from the weaverAdapter once it has finished weaving the class files associated with a given compilation result.
  231. */
  232. public void acceptResult(CompilationResult result) {
  233. compiler.requestor.acceptResult(result.tagAsAccepted());
  234. if (compiler.unitsToProcess != null) {
  235. for (int i = 0; i < compiler.unitsToProcess.length; i++) {
  236. if (compiler.unitsToProcess[i] != null) {
  237. if (compiler.unitsToProcess[i].compilationResult == result) {
  238. compiler.unitsToProcess[i] = null;
  239. }
  240. }
  241. }
  242. }
  243. }
  244. private List getBinarySourcesFrom(Map binarySourceEntries) {
  245. // Map is fileName |-> List<UnwovenClassFile>
  246. List ret = new ArrayList();
  247. for (Object o : binarySourceEntries.keySet()) {
  248. String sourceFileName = (String) o;
  249. List unwovenClassFiles = (List) binarySourceEntries.get(sourceFileName);
  250. // XXX - see bugs 57432,58679 - final parameter on next call should be "compiler.options.maxProblemsPerUnit"
  251. CompilationResult result = new CompilationResult(sourceFileName.toCharArray(), 0, 0, Integer.MAX_VALUE);
  252. result.noSourceAvailable();
  253. InterimCompilationResult binarySource = new InterimCompilationResult(result, unwovenClassFiles);
  254. ret.add(binarySource);
  255. }
  256. return ret;
  257. }
  258. private void notifyRequestor() {
  259. for (Object o : resultsPendingWeave) {
  260. InterimCompilationResult iresult = (InterimCompilationResult) o;
  261. compiler.requestor.acceptResult(iresult.result().tagAsAccepted());
  262. }
  263. }
  264. private void weave() throws IOException {
  265. // ensure weaver state is set up correctly
  266. for (Object o : resultsPendingWeave) {
  267. InterimCompilationResult iresult = (InterimCompilationResult) o;
  268. for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
  269. weaver.addClassFile(iresult.unwovenClassFiles()[i], false);
  270. }
  271. }
  272. weaver.setIsBatchWeave(isBatchCompile);
  273. weaver.prepareForWeave();
  274. if (weaver.needToReweaveWorld()) {
  275. if (!isBatchCompile) {
  276. // force full recompilation from source
  277. this.incrementalCompilationState.forceBatchBuildNextTimeAround();
  278. return;
  279. // addAllKnownClassesToWeaveList(); // if it's batch, they're already on the list...
  280. }
  281. resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
  282. } else {
  283. Map binarySourcesToAdd = binarySourceProvider.getBinarySourcesForThisWeave();
  284. resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourcesToAdd));
  285. }
  286. // if (isBatchCompile) {
  287. // resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
  288. // // passed into the compiler, the set of classes in injars and inpath...
  289. // } else if (weaver.needToReweaveWorld()) {
  290. // addAllKnownClassesToWeaveList();
  291. // resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
  292. // }
  293. try {
  294. weaver.weave(new WeaverAdapter(this, weaverMessageHandler, progressListener));
  295. } finally {
  296. // ???: is this the right point for this? After weaving has finished clear the caches.
  297. weaverMessageHandler.setCurrentResult(null);
  298. weaver.allWeavingComplete();
  299. weaver.tidyUp();
  300. IMessageHandler imh = weaver.getWorld().getMessageHandler();
  301. if (imh instanceof WeaverMessageHandler) {
  302. ((WeaverMessageHandler) imh).resetCompiler(null);
  303. }
  304. }
  305. }
  306. public void afterDietParsing(CompilationUnitDeclaration[] units) {
  307. // to be filled in...
  308. }
  309. public List getResultsPendingWeave() {
  310. return resultsPendingWeave;
  311. }
  312. }