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 13KB

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