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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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.Collection;
  15. import java.util.Collections;
  16. import java.util.HashMap;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. import java.util.Map;
  20. import org.aspectj.ajdt.internal.compiler.ast.AddAtAspectJAnnotationsVisitor;
  21. import org.aspectj.ajdt.internal.compiler.ast.ValidateAtAspectJAnnotationsVisitor;
  22. import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
  23. import org.aspectj.bridge.IMessage;
  24. import org.aspectj.bridge.IMessageHandler;
  25. import org.aspectj.bridge.IProgressListener;
  26. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  27. import org.aspectj.bridge.context.ContextToken;
  28. import org.aspectj.org.eclipse.jdt.core.compiler.IProblem;
  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.CompilationUnitDeclaration;
  32. import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
  33. import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
  34. import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
  35. import org.aspectj.weaver.bcel.BcelWeaver;
  36. import org.aspectj.weaver.bcel.BcelWorld;
  37. import org.aspectj.weaver.patterns.CflowPointcut;
  38. /**
  39. * @author colyer
  40. *
  41. * Adapts standard JDT Compiler to add in AspectJ specific behaviours.
  42. */
  43. public class AjCompilerAdapter implements ICompilerAdapter {
  44. private Compiler compiler;
  45. private BcelWeaver weaver;
  46. private EclipseFactory eWorld;
  47. private boolean isBatchCompile;
  48. private boolean reportedErrors;
  49. private boolean isXNoWeave;
  50. private boolean proceedOnError;
  51. private boolean inJava5Mode;
  52. private boolean noAtAspectJAnnotationProcessing;
  53. private IIntermediateResultsRequestor intermediateResultsRequestor;
  54. private IProgressListener progressListener;
  55. private IOutputClassFileNameProvider outputFileNameProvider;
  56. private IBinarySourceProvider binarySourceProvider;
  57. private WeaverMessageHandler weaverMessageHandler;
  58. private Map /* fileName |-> List<UnwovenClassFile> */ binarySourceSetForFullWeave = new HashMap();
  59. private Collection /*InterimCompilationResult*/ resultSetForFullWeave = Collections.EMPTY_LIST;
  60. private ContextToken processingToken = null;
  61. private ContextToken resolvingToken = null;
  62. private ContextToken analysingToken = null;
  63. private ContextToken generatingToken = null;
  64. List /*InterimResult*/ resultsPendingWeave = new ArrayList();
  65. /**
  66. * Create an adapter, and tell it everything it needs to now to drive the AspectJ
  67. * parts of a compile cycle.
  68. * @param compiler the JDT compiler that produces class files from source
  69. * @param isBatchCompile true if this is a full build (non-incremental)
  70. * @param world the bcelWorld used for type resolution during weaving
  71. * @param weaver the weaver
  72. * @param intRequestor recipient of interim compilation results from compiler (pre-weave)
  73. * @param outputFileNameProvider implementor of a strategy providing output file names for results
  74. * @param binarySourceEntries binary source that we didn't compile, but that we need to weave
  75. * @param resultSetForFullWeave if we are doing an incremental build, and the weaver determines
  76. * that we need to weave the world, this is the set of intermediate
  77. * results that will be passed to the weaver.
  78. * @param isXNoWeave
  79. */
  80. public AjCompilerAdapter(Compiler compiler,
  81. boolean isBatchCompile,
  82. BcelWorld world,
  83. BcelWeaver weaver,
  84. EclipseFactory eFactory,
  85. IIntermediateResultsRequestor intRequestor,
  86. IProgressListener progressListener,
  87. IOutputClassFileNameProvider outputFileNameProvider,
  88. IBinarySourceProvider binarySourceProvider,
  89. Map fullBinarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
  90. Collection /* InterimCompilationResult */ resultSetForFullWeave,
  91. boolean isXNoWeave,
  92. boolean proceedOnError,
  93. boolean noAtAspectJProcessing) {
  94. this.compiler = compiler;
  95. this.isBatchCompile = isBatchCompile;
  96. this.weaver = weaver;
  97. this.intermediateResultsRequestor = intRequestor;
  98. this.progressListener = progressListener;
  99. this.outputFileNameProvider = outputFileNameProvider;
  100. this.binarySourceProvider = binarySourceProvider;
  101. this.isXNoWeave = isXNoWeave;
  102. this.proceedOnError = proceedOnError;
  103. this.binarySourceSetForFullWeave = fullBinarySourceEntries;
  104. this.resultSetForFullWeave = resultSetForFullWeave;
  105. this.eWorld = eFactory;
  106. this.inJava5Mode = false;
  107. this.noAtAspectJAnnotationProcessing = noAtAspectJProcessing;
  108. if (compiler.options.complianceLevel == CompilerOptions.JDK1_5) inJava5Mode = true;
  109. IMessageHandler msgHandler = world.getMessageHandler();
  110. weaverMessageHandler = new WeaverMessageHandler(msgHandler, compiler);
  111. world.setMessageHandler(weaverMessageHandler);
  112. }
  113. // the compilation lifecycle methods below are called in order as compilation progresses...
  114. public void beforeCompiling(ICompilationUnit[] sourceUnits) {
  115. resultsPendingWeave = new ArrayList();
  116. reportedErrors = false;
  117. }
  118. public void beforeProcessing(CompilationUnitDeclaration unit) {
  119. eWorld.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
  120. processingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_COMPILATION_UNIT,unit.getFileName());
  121. if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
  122. ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ADDING_AT_ASPECTJ_ANNOTATIONS, unit.getFileName());
  123. AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit);
  124. unit.traverse(atAspectJVisitor, unit.scope);
  125. CompilationAndWeavingContext.leavingPhase(tok);
  126. }
  127. }
  128. public void beforeResolving(CompilationUnitDeclaration unit) {
  129. resolvingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.RESOLVING_COMPILATION_UNIT, unit.getFileName());
  130. }
  131. public void afterResolving(CompilationUnitDeclaration unit) {
  132. if (resolvingToken != null)
  133. CompilationAndWeavingContext.leavingPhase(resolvingToken);
  134. }
  135. public void beforeAnalysing(CompilationUnitDeclaration unit) {
  136. analysingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ANALYSING_COMPILATION_UNIT, unit.getFileName());
  137. if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
  138. ValidateAtAspectJAnnotationsVisitor atAspectJVisitor = new ValidateAtAspectJAnnotationsVisitor(unit);
  139. unit.traverse(atAspectJVisitor, unit.scope);
  140. }
  141. }
  142. public void afterAnalysing(CompilationUnitDeclaration unit) {
  143. if (analysingToken != null)
  144. CompilationAndWeavingContext.leavingPhase(analysingToken);
  145. }
  146. public void beforeGenerating(CompilationUnitDeclaration unit) {
  147. generatingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.GENERATING_UNWOVEN_CODE_FOR_COMPILATION_UNIT, unit.getFileName());
  148. }
  149. public void afterGenerating(CompilationUnitDeclaration unit) {
  150. if (generatingToken != null)
  151. CompilationAndWeavingContext.leavingPhase(generatingToken);
  152. }
  153. public void afterCompiling(CompilationUnitDeclaration[] units) {
  154. try {
  155. if (isXNoWeave || (reportedErrors && !proceedOnError)) {
  156. // no point weaving... just tell the requestor we're done
  157. notifyRequestor();
  158. } else {
  159. weave(); // notification happens as weave progresses...
  160. }
  161. } catch (IOException ex) {
  162. AbortCompilation ac = new AbortCompilation(null,ex);
  163. throw ac;
  164. } catch (RuntimeException rEx) {
  165. if (rEx instanceof AbortCompilation) throw rEx; // Don't wrap AbortCompilation exceptions!
  166. // This will be unwrapped in Compiler.handleInternalException() and the nested
  167. // RuntimeException thrown back to the original caller - which is AspectJ
  168. // which will then then log it as a compiler problem.
  169. throw new AbortCompilation(true,rEx);
  170. }
  171. }
  172. public void afterProcessing(CompilationUnitDeclaration unit, int unitIndex) {
  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) addAllKnownClassesToWeaveList(); // if it's batch, they're already on the list...
  255. resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
  256. } else {
  257. Map binarySourcesToAdd = binarySourceProvider.getBinarySourcesForThisWeave();
  258. resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourcesToAdd));
  259. }
  260. // if (isBatchCompile) {
  261. // resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
  262. // // passed into the compiler, the set of classes in injars and inpath...
  263. // } else if (weaver.needToReweaveWorld()) {
  264. // addAllKnownClassesToWeaveList();
  265. // resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
  266. // }
  267. try {
  268. weaver.weave(new WeaverAdapter(this,weaverMessageHandler,progressListener));
  269. } finally {
  270. // ???: is this the right point for this? After weaving has finished clear the caches.
  271. CflowPointcut.clearCaches();
  272. }
  273. }
  274. private void addAllKnownClassesToWeaveList() {
  275. // results pending weave already has some results from this (incremental) compile
  276. // add in results from any other source
  277. for (Iterator iter = resultSetForFullWeave.iterator(); iter.hasNext();) {
  278. InterimCompilationResult ir = (InterimCompilationResult) iter.next();
  279. if (!resultsPendingWeave.contains(ir)) { // equality based on source file name...
  280. ir.result().hasBeenAccepted = false; // it may have been accepted before, start again
  281. // Remove DEOWs as they are going to be added again during weaving
  282. ir.result().removeProblems(new CompilationResult.ProblemsForRemovalFilter() {
  283. public boolean accept(IProblem p) {
  284. String s = p.getSupplementaryMessageInfo();
  285. if (s != null && s.endsWith("[deow=true]")) return true;
  286. return false;
  287. }});
  288. resultsPendingWeave.add(ir);
  289. }
  290. }
  291. }
  292. }