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
9 * Andy Clement - initial implementation 26Jul06
10 *******************************************************************************/
11 package org.aspectj.ajdt.internal.compiler;
13 import java.io.IOException;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Hashtable;
17 import java.util.List;
20 import org.aspectj.ajdt.internal.compiler.ast.AddAtAspectJAnnotationsVisitor;
21 import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
22 import org.aspectj.ajdt.internal.compiler.ast.InterTypeConstructorDeclaration;
23 import org.aspectj.ajdt.internal.compiler.ast.InterTypeFieldDeclaration;
24 import org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration;
25 import org.aspectj.ajdt.internal.compiler.ast.ValidateAtAspectJAnnotationsVisitor;
26 import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
27 import org.aspectj.ajdt.internal.core.builder.AjState;
28 import org.aspectj.asm.internal.CharOperation;
29 import org.aspectj.bridge.IMessage;
30 import org.aspectj.bridge.IMessageHandler;
31 import org.aspectj.bridge.IProgressListener;
32 import org.aspectj.bridge.context.CompilationAndWeavingContext;
33 import org.aspectj.bridge.context.ContextToken;
34 import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
35 import org.aspectj.org.eclipse.jdt.internal.compiler.Compiler;
36 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
37 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
38 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
39 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
40 import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
41 import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
42 import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
43 import org.aspectj.weaver.bcel.BcelWeaver;
44 import org.aspectj.weaver.bcel.BcelWorld;
45 import org.aspectj.weaver.bcel.UnwovenClassFile;
48 * Adapts standard JDT Compiler to add in AspectJ specific behaviours. This version implements pipelining - where files are compiled
49 * and then woven immediately, unlike AjCompilerAdapter which compiles everything then weaves everything. (One small note: because
50 * all aspects have to be known before weaving can take place, the weaving pipeline is 'stalled' until all aspects have been
53 * The basic strategy is this:
55 * 1. diet parse all input source files - this is enough for us to implement ITD matching - this enables us to determine which are
56 * aspects 2. sort the input files, aspects first - keep a note of how many files contain aspects 3. if there are aspects, mark the
57 * pipeline as 'stalled' 3. repeat 3a. compile a file 3b. have we now compiled all aspects? NO - put file in a weave pending queue
58 * YES- unstall the 'pipeline' 3c. is the pipeline stalled? NO - weave all pending files and this one YES- do nothing
60 * Complexities arise because of: - what does -XterminateAfterCompilation mean? since there is no stage where everything is compiled
61 * and nothing is woven
64 * Here is the compiler loop difference when pipelining.
66 * the old way: Finished diet parsing [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java] Finished diet parsing
67 * [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java] > AjLookupEnvironment.completeTypeBindings() <
68 * AjLookupEnvironment.completeTypeBindings() compiling C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java
69 * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java)
70 * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java) compiling
71 * C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java
72 * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java)
73 * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java) >AjCompilerAdapter.weave()
74 * >BcelWeaver.prepareForWeave <BcelWeaver.prepareForWeave woven class ClassOne (from
75 * C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java) woven class ClassTwo (from
76 * C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java) <AjCompilerAdapter.weave()
78 * the new way (see the compiling/weaving mixed up): Finished diet parsing
79 * [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java] Finished diet parsing
80 * [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java] >AjLookupEnvironment.completeTypeBindings()
81 * <AjLookupEnvironment.completeTypeBindings() compiling C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java
82 * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java)
83 * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java) >AjCompilerAdapter.weave()
84 * >BcelWeaver.prepareForWeave <BcelWeaver.prepareForWeave woven class ClassOne (from
85 * C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java) <AjCompilerAdapter.weave() compiling
86 * C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java
87 * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java)
88 * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java) >AjCompilerAdapter.weave() woven class ClassTwo
89 * (from C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java) <AjCompilerAdapter.weave()
93 public class AjPipeliningCompilerAdapter extends AbstractCompilerAdapter {
95 private Compiler compiler;
96 private BcelWeaver weaver;
97 private EclipseFactory eWorld;
98 private boolean isBatchCompile;
99 private boolean reportedErrors;
100 private boolean isXTerminateAfterCompilation;
101 private boolean proceedOnError;
102 private boolean inJava5Mode;
103 private boolean makeReflectable;
104 private boolean noAtAspectJAnnotationProcessing;
105 private IIntermediateResultsRequestor intermediateResultsRequestor;
106 private IProgressListener progressListener;
107 private IOutputClassFileNameProvider outputFileNameProvider;
108 private IBinarySourceProvider binarySourceProvider;
109 private WeaverMessageHandler weaverMessageHandler;
110 private Map<String, List<UnwovenClassFile>> binarySourceSetForFullWeave = new HashMap<>();
112 private ContextToken processingToken = null;
113 private ContextToken resolvingToken = null;
114 private ContextToken analysingToken = null;
115 private ContextToken generatingToken = null;
117 private AjState incrementalCompilationState;
119 // Maintains a list of whats weaving - whilst the pipeline is stalled, this accumulates aspects.
120 List<InterimCompilationResult> resultsPendingWeave = new ArrayList<>();
123 private boolean pipelineStalled = true;
124 private boolean weaverInitialized = false;
125 private int toWaitFor;
126 // If we determine we are going to drop back to a full build - don't need to tell the weaver to report adviceDidNotMatch
127 private boolean droppingBackToFullBuild;
130 * Create an adapter, and tell it everything it needs to now to drive the AspectJ parts of a compile cycle.
132 * @param compiler the JDT compiler that produces class files from source
133 * @param isBatchCompile true if this is a full build (non-incremental)
134 * @param world the bcelWorld used for type resolution during weaving
135 * @param weaver the weaver
136 * @param intRequestor recipient of interim compilation results from compiler (pre-weave)
137 * @param outputFileNameProvider implementor of a strategy providing output file names for results
138 * @param binarySourceProvider binary source that we didn't compile, but that we need to weave
139 * @param incrementalCompilationState if we are doing an incremental build, and the weaver determines that we need to weave the world,
140 * this is the set of intermediate results that will be passed to the weaver.
142 public AjPipeliningCompilerAdapter(Compiler compiler, boolean isBatchCompile, BcelWorld world, BcelWeaver weaver,
143 EclipseFactory eFactory, IIntermediateResultsRequestor intRequestor, IProgressListener progressListener,
144 IOutputClassFileNameProvider outputFileNameProvider, IBinarySourceProvider binarySourceProvider,
145 Map fullBinarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
146 boolean isXterminateAfterCompilation, boolean proceedOnError, boolean noAtAspectJProcessing, boolean makeReflectable,
147 AjState incrementalCompilationState) {
148 this.compiler = compiler;
149 this.isBatchCompile = isBatchCompile;
150 this.weaver = weaver;
151 this.intermediateResultsRequestor = intRequestor;
152 this.progressListener = progressListener;
153 this.outputFileNameProvider = outputFileNameProvider;
154 this.binarySourceProvider = binarySourceProvider;
155 this.isXTerminateAfterCompilation = isXterminateAfterCompilation;
156 this.proceedOnError = proceedOnError;
157 this.binarySourceSetForFullWeave = fullBinarySourceEntries;
158 this.eWorld = eFactory;
159 this.inJava5Mode = false;
160 this.makeReflectable = makeReflectable;
161 this.noAtAspectJAnnotationProcessing = noAtAspectJProcessing;
162 this.incrementalCompilationState = incrementalCompilationState;
164 if (compiler.options.complianceLevel >= ClassFileConstants.JDK1_5) {
167 IMessageHandler msgHandler = world.getMessageHandler();
168 // Do we need to reset the message handler or create a new one? (This saves a ton of memory lost on incremental compiles...)
169 if (msgHandler instanceof WeaverMessageHandler) {
170 ((WeaverMessageHandler) msgHandler).resetCompiler(compiler);
171 weaverMessageHandler = (WeaverMessageHandler) msgHandler;
173 weaverMessageHandler = new WeaverMessageHandler(msgHandler, compiler);
174 world.setMessageHandler(weaverMessageHandler);
178 // the compilation lifecycle methods below are called in order as compilation progresses...
181 * In a pipelining compilation system, we need to ensure aspects are through the pipeline first. Only when they are all through
182 * (and therefore we know about all static/dynamic crosscutting) can be proceed to weave anything. Effectively the weaving part
183 * of the pipeline stalls until all the aspects have been fully compiled. This method sorts the compilation units such that any
184 * containing aspects are fully compiled first and it keeps a note on how long it should stall the pipeline before commencing
187 public void afterDietParsing(CompilationUnitDeclaration[] units) {
189 System.err.println("> afterDietParsing: there are " + (units == null ? 0 : units.length) + " units to sort");
192 if (!reportedErrors && units != null) {
193 for (CompilationUnitDeclaration unit : units) {
194 if (unit != null && unit.compilationResult != null && unit.compilationResult.hasErrors()) {
195 reportedErrors = true;
196 break; // TODO break or exit here?
201 // Break the units into two lists...
202 List<CompilationUnitDeclaration> aspects = new ArrayList<>();
203 List<CompilationUnitDeclaration> nonaspects = new ArrayList<>();
204 for (CompilationUnitDeclaration unit : units) {
205 if (containsAnAspect(unit)) {
208 nonaspects.add(unit);
212 // ...and put them back together, aspects first
214 for (CompilationUnitDeclaration aspect : aspects) {
215 units[posn++] = aspect;
217 for (CompilationUnitDeclaration nonaspect : nonaspects) {
218 units[posn++] = nonaspect;
221 // Work out how long to stall the pipeline
222 toWaitFor = aspects.size();
224 System.err.println("< afterDietParsing: stalling pipeline for " + toWaitFor + " source files");
228 if (pipelineTesting) {
229 if (pipelineOutput == null) {
230 pipelineOutput = new Hashtable();
232 pipelineOutput.put("filesContainingAspects", Integer.toString(toWaitFor));
233 StringBuilder order = new StringBuilder();
235 for (int i = 0; i < units.length; i++) {
239 CompilationUnitDeclaration declaration = units[i];
240 String filename = new String(declaration.getFileName());
241 int idx = filename.lastIndexOf('/');
243 filename = filename.substring(idx + 1);
245 idx = filename.lastIndexOf('\\');
247 filename = filename.substring(idx + 1);
249 order.append(filename);
252 pipelineOutput.put("weaveOrder", order.toString());
256 public void beforeCompiling(ICompilationUnit[] sourceUnits) {
257 resultsPendingWeave = new ArrayList<>();
258 reportedErrors = false;
259 droppingBackToFullBuild = false;
262 public void beforeProcessing(CompilationUnitDeclaration unit) {
264 System.err.println("compiling " + new String(unit.getFileName()));
266 eWorld.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
267 processingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_COMPILATION_UNIT, unit
269 if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
270 ContextToken tok = CompilationAndWeavingContext.enteringPhase(
271 CompilationAndWeavingContext.ADDING_AT_ASPECTJ_ANNOTATIONS, unit.getFileName());
272 AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit, makeReflectable);
273 unit.traverse(atAspectJVisitor, unit.scope);
274 CompilationAndWeavingContext.leavingPhase(tok);
278 public void beforeResolving(CompilationUnitDeclaration unit) {
279 resolvingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.RESOLVING_COMPILATION_UNIT, unit
283 public void afterResolving(CompilationUnitDeclaration unit) {
284 if (resolvingToken != null) {
285 CompilationAndWeavingContext.leavingPhase(resolvingToken);
289 public void beforeAnalysing(CompilationUnitDeclaration unit) {
290 analysingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ANALYSING_COMPILATION_UNIT, unit
292 if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
293 ValidateAtAspectJAnnotationsVisitor atAspectJVisitor = new ValidateAtAspectJAnnotationsVisitor(unit);
294 unit.traverse(atAspectJVisitor, unit.scope);
298 public void afterAnalysing(CompilationUnitDeclaration unit) {
299 if (analysingToken != null) {
300 CompilationAndWeavingContext.leavingPhase(analysingToken);
304 public void beforeGenerating(CompilationUnitDeclaration unit) {
305 generatingToken = CompilationAndWeavingContext.enteringPhase(
306 CompilationAndWeavingContext.GENERATING_UNWOVEN_CODE_FOR_COMPILATION_UNIT, unit.getFileName());
307 if (eWorld.pushinCollector != null) {
308 if (unit.types != null && unit.types.length > 0) {
309 for (int t = 0; t < unit.types.length; t++) {
310 TypeDeclaration type = unit.types[t];
311 if (type.methods != null) {
312 for (int m = 0; m < type.methods.length; m++) {
313 AbstractMethodDeclaration md = type.methods[m];
314 if (md instanceof InterTypeMethodDeclaration) {
315 InterTypeMethodDeclaration itmd = ((InterTypeMethodDeclaration) md);
316 ITDMethodPrinter printer = new ITDMethodPrinter(itmd, md.scope);
317 String s = printer.print();
318 eWorld.pushinCollector.recordInterTypeMethodDeclarationCode(md, s, getDeclarationLineNumber(md));
319 } else if (md instanceof InterTypeFieldDeclaration) {
320 ITDFieldPrinter printer = new ITDFieldPrinter(((InterTypeFieldDeclaration) md), md.scope);
321 String s = printer.print();
322 eWorld.pushinCollector.recordInterTypeFieldDeclarationCode(md, s, getDeclarationLineNumber(md));
323 } else if (md instanceof InterTypeConstructorDeclaration) {
324 ITDConstructorPrinter printer = new ITDConstructorPrinter(((InterTypeConstructorDeclaration) md),
326 String s = printer.print();
327 eWorld.pushinCollector.recordInterTypeConstructorDeclarationCode(md, s,
328 getDeclarationLineNumber(md));
329 // } else if (md instanceof DeclareAnnotationDeclaration) {
330 // DeclareAnnotationDeclaration dad = (DeclareAnnotationDeclaration) md;
331 // String value = new DeclareAnnotationsPrinter(dad, dad.scope).print();
332 // eWorld.pushinCollector.recordDeclareAnnotationDeclarationCode(md, value);
338 eWorld.pushinCollector.setOutputFileNameProvider(outputFileNameProvider);
343 * @return the line number for this declaration in the source code
345 private int getDeclarationLineNumber(AbstractMethodDeclaration md) {
346 int sourceStart = md.sourceStart;
347 int[] separators = md.compilationResult.lineSeparatorPositions;
348 int declarationStartLine = 1;
349 for (int separator : separators) {
350 if (sourceStart < separator) {
353 declarationStartLine++;
355 return declarationStartLine;
358 public void afterGenerating(CompilationUnitDeclaration unit) {
359 if (generatingToken != null) {
360 CompilationAndWeavingContext.leavingPhase(generatingToken);
362 if (eWorld.pushinCollector != null) {
363 eWorld.pushinCollector.dump(unit);
367 public void afterCompiling(CompilationUnitDeclaration[] units) {
368 this.eWorld.cleanup();
369 if (!weaverInitialized) { // nothing got compiled, doesnt mean there is nothing to do... (binary weaving)
370 if (!(isXTerminateAfterCompilation || (reportedErrors && !proceedOnError))) {
371 // acceptResult(unit.compilationResult);
374 if (weaveQueuedEntries()) {
375 droppingBackToFullBuild = true;
377 } catch (IOException ex) {
378 AbortCompilation ac = new AbortCompilation(null, ex);
385 // not great ... but one more check before we continue, see pr132314
386 if (!reportedErrors && units != null) {
387 for (CompilationUnitDeclaration unit : units) {
388 if (unit != null && unit.compilationResult != null && unit.compilationResult.hasErrors()) {
389 reportedErrors = true;
394 if (isXTerminateAfterCompilation || (reportedErrors && !proceedOnError)) {
395 // no point weaving... just tell the requestor we're done
398 // weave(); // notification happens as weave progresses...
399 // weaver.getWorld().flush(); // pr152257
401 // } catch (IOException ex) {
402 // AbortCompilation ac = new AbortCompilation(null,ex);
404 } catch (RuntimeException rEx) {
405 if (rEx instanceof AbortCompilation) {
406 throw rEx; // Don't wrap AbortCompilation exceptions!
409 // This will be unwrapped in Compiler.handleInternalException() and the nested
410 // RuntimeException thrown back to the original caller - which is AspectJ
411 // which will then then log it as a compiler problem.
412 throw new AbortCompilation(true, rEx);
416 public void afterProcessing(CompilationUnitDeclaration unit, int unitIndex) {
417 CompilationAndWeavingContext.leavingPhase(processingToken);
418 eWorld.finishedCompilationUnit(unit);
419 InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult, outputFileNameProvider);
420 if (unit.compilationResult.hasErrors()) {
421 reportedErrors = true;
424 if (intermediateResultsRequestor != null) {
425 intermediateResultsRequestor.acceptResult(intRes);
428 if (unit.compilationResult.hasErrors() || (isXTerminateAfterCompilation || (reportedErrors && !proceedOnError))) {
429 acceptResult(unit.compilationResult);
431 queueForWeaving(intRes);
435 private void queueForWeaving(InterimCompilationResult intRes) {
436 resultsPendingWeave.add(intRes);
437 if (pipelineStalled) {
438 if (resultsPendingWeave.size() >= toWaitFor) {
439 pipelineStalled = false;
442 if (pipelineStalled) {
446 if (weaveQueuedEntries()) {
447 droppingBackToFullBuild = true;
449 } catch (IOException ex) {
450 AbortCompilation ac = new AbortCompilation(null, ex);
456 * Called from the weaverAdapter once it has finished weaving the class files associated with a given compilation result.
458 public void acceptResult(CompilationResult result) {
459 compiler.requestor.acceptResult(result.tagAsAccepted());
460 if (compiler.unitsToProcess != null) {
461 for (int i = 0; i < compiler.unitsToProcess.length; i++) {
462 if (compiler.unitsToProcess[i] != null) {
463 if (compiler.unitsToProcess[i].compilationResult == result) {
464 compiler.unitsToProcess[i].cleanUp();
465 compiler.unitsToProcess[i] = null;
473 // ==================================================================================
475 private List<InterimCompilationResult> getBinarySourcesFrom(Map<String, List<UnwovenClassFile>> binarySourceEntries) {
476 // Map is fileName |-> List<UnwovenClassFile>
477 List<InterimCompilationResult> ret = new ArrayList<>();
478 for (String sourceFileName : binarySourceEntries.keySet()) {
479 List<UnwovenClassFile> unwovenClassFiles = binarySourceEntries.get(sourceFileName);
480 // XXX - see bugs 57432,58679 - final parameter on next call should be "compiler.options.maxProblemsPerUnit"
481 CompilationResult result = new CompilationResult(sourceFileName.toCharArray(), 0, 0, Integer.MAX_VALUE);
482 result.noSourceAvailable();
483 InterimCompilationResult binarySource = new InterimCompilationResult(result, unwovenClassFiles);
484 ret.add(binarySource);
489 private void notifyRequestor() {
490 for (InterimCompilationResult iresult : resultsPendingWeave) {
491 compiler.requestor.acceptResult(iresult.result().tagAsAccepted());
495 /** Return true if we've decided to drop back to a full build (too much has changed) */
496 private boolean weaveQueuedEntries() throws IOException {
498 System.err.println(">.weaveQueuedEntries()");
500 for (InterimCompilationResult iresult : resultsPendingWeave) {
501 for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
502 weaver.addClassFile(iresult.unwovenClassFiles()[i], false);
505 ensureWeaverInitialized(); // by doing this only once, are we saying needToReweaveWorld can't change once the aspects have
506 // been stuffed into the weaver?
507 if (weaver.needToReweaveWorld() && !isBatchCompile) {
510 weaver.weave(new WeaverAdapter(this, weaverMessageHandler, progressListener));
511 resultsPendingWeave.clear(); // dont need to do those again
512 this.eWorld.minicleanup();
514 System.err.println("<.weaveQueuedEntries()");
519 private void ensureWeaverInitialized() {
520 if (weaverInitialized) {
523 weaverInitialized = true;
524 weaver.setIsBatchWeave(isBatchCompile);
525 weaver.prepareForWeave();
526 if (weaver.needToReweaveWorld()) {
527 if (!isBatchCompile) {
528 // force full recompilation from source
529 this.incrementalCompilationState.forceBatchBuildNextTimeAround();
532 resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
534 Map binarySourcesToAdd = binarySourceProvider.getBinarySourcesForThisWeave();
535 resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourcesToAdd));
539 // private void weave() throws IOException {
540 // if (debugPipeline)System.err.println("> weave()");
541 // // ensure weaver state is set up correctly
542 // for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
543 // InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
544 // for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
545 // weaver.addClassFile(iresult.unwovenClassFiles()[i]);
549 // weaver.setIsBatchWeave(isBatchCompile);
550 // weaver.prepareForWeave();
551 // if (weaver.needToReweaveWorld()) {
552 // if (!isBatchCompile) {
553 // //force full recompilation from source
554 // this.incrementalCompilationState.forceBatchBuildNextTimeAround();
557 // resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
559 // Map binarySourcesToAdd = binarySourceProvider.getBinarySourcesForThisWeave();
560 // resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourcesToAdd));
564 // weaver.weave(new WeaverAdapter(this,weaverMessageHandler,progressListener));
567 // IMessageHandler imh = weaver.getWorld().getMessageHandler();
568 // if (imh instanceof WeaverMessageHandler)
569 // ((WeaverMessageHandler)imh).resetCompiler(null);
571 // if (debugPipeline)System.err.println("< weave()");
574 private void postWeave() {
576 System.err.println("> postWeave()");
578 IMessageHandler imh = weaver.getWorld().getMessageHandler();
579 if (imh instanceof WeaverMessageHandler) {
580 ((WeaverMessageHandler) imh).setCurrentResult(null);
582 if (!droppingBackToFullBuild) {
583 weaver.allWeavingComplete();
586 if (imh instanceof WeaverMessageHandler) {
587 ((WeaverMessageHandler) imh).resetCompiler(null);
590 System.err.println("< postWeave()");
595 * Return true if the compilation unit declaration contains an aspect declaration (either code style or annotation style). It
596 * must inspect the multiple types that may be in a compilation unit declaration and any inner types.
598 private boolean containsAnAspect(CompilationUnitDeclaration cud) {
599 TypeDeclaration[] typeDecls = cud.types;
600 if (typeDecls != null) {
601 for (TypeDeclaration declaration : typeDecls) { // loop through top level types in the file
602 if (isAspect(declaration)) {
605 if (declaration.memberTypes != null) {
606 TypeDeclaration[] memberTypes = declaration.memberTypes;
607 for (TypeDeclaration memberType : memberTypes) { // loop through inner types
608 if (containsAnAspect(memberType)) {
618 private boolean containsAnAspect(TypeDeclaration tDecl) {
619 if (isAspect(tDecl)) {
622 if (tDecl.memberTypes != null) {
623 TypeDeclaration[] memberTypes = tDecl.memberTypes;
624 for (TypeDeclaration memberType : memberTypes) { // loop through inner types
625 if (containsAnAspect(memberType)) {
633 private static final char[] aspectSig = "Lorg/aspectj/lang/annotation/Aspect;".toCharArray();
635 private boolean isAspect(TypeDeclaration declaration) {
636 // avoid an NPE when something else is wrong in this system ... the real problem will be reported elsewhere
637 if (declaration.staticInitializerScope == null) {
640 if (declaration instanceof AspectDeclaration) {
641 return true; // code style
642 } else if (declaration.annotations != null) { // check for annotation style
643 for (int index = 0; index < declaration.annotations.length; index++) {
644 // Cause annotation resolution
645 declaration.binding.getAnnotationTagBits();
646 Annotation a = declaration.annotations[index];
647 if (a.resolvedType == null) {
648 continue; // another problem is being reported, so don't crash here
650 if (CharOperation.equals(a.resolvedType.signature(), aspectSig)) {
660 * SECRET: FOR TESTING - this can be used to collect information that tests can verify.
662 public static boolean pipelineTesting = false;
663 public static Hashtable<String, String> pipelineOutput = null;
665 // Keys into pipelineOutput:
666 // compileOrder "[XXX,YYY]" a list of the order in which files will be woven (aspects should be first)
667 // filesContainingAspects "NNN" how many input source files have aspects inside
670 public static String getPipelineDebugOutput(String key) {
671 if (pipelineOutput == null) {
674 return pipelineOutput.get(key);
677 private final static boolean debugPipeline = false;
679 public List<InterimCompilationResult> getResultsPendingWeave() {
680 return resultsPendingWeave;