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 v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
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.Iterator;
18 import java.util.List;
21 import org.aspectj.ajdt.internal.compiler.ast.AddAtAspectJAnnotationsVisitor;
22 import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
23 import org.aspectj.ajdt.internal.compiler.ast.InterTypeConstructorDeclaration;
24 import org.aspectj.ajdt.internal.compiler.ast.InterTypeFieldDeclaration;
25 import org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration;
26 import org.aspectj.ajdt.internal.compiler.ast.ValidateAtAspectJAnnotationsVisitor;
27 import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
28 import org.aspectj.ajdt.internal.core.builder.AjState;
29 import org.aspectj.asm.internal.CharOperation;
30 import org.aspectj.bridge.IMessage;
31 import org.aspectj.bridge.IMessageHandler;
32 import org.aspectj.bridge.IProgressListener;
33 import org.aspectj.bridge.context.CompilationAndWeavingContext;
34 import org.aspectj.bridge.context.ContextToken;
35 import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
36 import org.aspectj.org.eclipse.jdt.internal.compiler.Compiler;
37 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
38 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
39 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
40 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
41 import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
42 import org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
43 import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
44 import org.aspectj.weaver.bcel.BcelWeaver;
45 import org.aspectj.weaver.bcel.BcelWorld;
46 import org.aspectj.weaver.bcel.UnwovenClassFile;
49 * Adapts standard JDT Compiler to add in AspectJ specific behaviours. This version implements pipelining - where files are compiled
50 * and then woven immediately, unlike AjCompilerAdapter which compiles everything then weaves everything. (One small note: because
51 * all aspects have to be known before weaving can take place, the weaving pipeline is 'stalled' until all aspects have been
54 * The basic strategy is this:
56 * 1. diet parse all input source files - this is enough for us to implement ITD matching - this enables us to determine which are
57 * aspects 2. sort the input files, aspects first - keep a note of how many files contain aspects 3. if there are aspects, mark the
58 * pipeline as 'stalled' 3. repeat 3a. compile a file 3b. have we now compiled all aspects? NO - put file in a weave pending queue
59 * YES- unstall the 'pipeline' 3c. is the pipeline stalled? NO - weave all pending files and this one YES- do nothing
61 * Complexities arise because of: - what does -XterminateAfterCompilation mean? since there is no stage where everything is compiled
62 * and nothing is woven
65 * Here is the compiler loop difference when pipelining.
67 * the old way: Finished diet parsing [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java] Finished diet parsing
68 * [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java] > AjLookupEnvironment.completeTypeBindings() <
69 * AjLookupEnvironment.completeTypeBindings() compiling C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java
70 * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java)
71 * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java) compiling
72 * C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java
73 * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java)
74 * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java) >AjCompilerAdapter.weave()
75 * >BcelWeaver.prepareForWeave <BcelWeaver.prepareForWeave woven class ClassOne (from
76 * C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java) woven class ClassTwo (from
77 * C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java) <AjCompilerAdapter.weave()
79 * the new way (see the compiling/weaving mixed up): Finished diet parsing
80 * [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java] Finished diet parsing
81 * [C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java] >AjLookupEnvironment.completeTypeBindings()
82 * <AjLookupEnvironment.completeTypeBindings() compiling C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java
83 * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java)
84 * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java) >AjCompilerAdapter.weave()
85 * >BcelWeaver.prepareForWeave <BcelWeaver.prepareForWeave woven class ClassOne (from
86 * C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassOne.java) <AjCompilerAdapter.weave() compiling
87 * C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java
88 * >Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java)
89 * <Compiler.process(C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java) >AjCompilerAdapter.weave() woven class ClassTwo
90 * (from C:\temp\ajcSandbox\aspectjhead\ajcTest23160.tmp\ClassTwo.java) <AjCompilerAdapter.weave()
94 public class AjPipeliningCompilerAdapter extends AbstractCompilerAdapter {
96 private Compiler compiler;
97 private BcelWeaver weaver;
98 private EclipseFactory eWorld;
99 private boolean isBatchCompile;
100 private boolean reportedErrors;
101 private boolean isXTerminateAfterCompilation;
102 private boolean proceedOnError;
103 private boolean inJava5Mode;
104 private boolean makeReflectable;
105 private boolean noAtAspectJAnnotationProcessing;
106 private IIntermediateResultsRequestor intermediateResultsRequestor;
107 private IProgressListener progressListener;
108 private IOutputClassFileNameProvider outputFileNameProvider;
109 private IBinarySourceProvider binarySourceProvider;
110 private WeaverMessageHandler weaverMessageHandler;
111 private Map<String, List<UnwovenClassFile>> binarySourceSetForFullWeave = new HashMap<>();
113 private ContextToken processingToken = null;
114 private ContextToken resolvingToken = null;
115 private ContextToken analysingToken = null;
116 private ContextToken generatingToken = null;
118 private AjState incrementalCompilationState;
120 // Maintains a list of whats weaving - whilst the pipeline is stalled, this accumulates aspects.
121 List<InterimCompilationResult> resultsPendingWeave = new ArrayList<>();
124 private boolean pipelineStalled = true;
125 private boolean weaverInitialized = false;
126 private int toWaitFor;
127 // If we determine we are going to drop back to a full build - don't need to tell the weaver to report adviceDidNotMatch
128 private boolean droppingBackToFullBuild;
131 * Create an adapter, and tell it everything it needs to now to drive the AspectJ parts of a compile cycle.
133 * @param compiler the JDT compiler that produces class files from source
134 * @param isBatchCompile true if this is a full build (non-incremental)
135 * @param world the bcelWorld used for type resolution during weaving
136 * @param weaver the weaver
137 * @param intRequestor recipient of interim compilation results from compiler (pre-weave)
138 * @param outputFileNameProvider implementor of a strategy providing output file names for results
139 * @param binarySourceEntries binary source that we didn't compile, but that we need to weave
140 * @param resultSetForFullWeave if we are doing an incremental build, and the weaver determines that we need to weave the world,
141 * this is the set of intermediate results that will be passed to the weaver.
143 public AjPipeliningCompilerAdapter(Compiler compiler, boolean isBatchCompile, BcelWorld world, BcelWeaver weaver,
144 EclipseFactory eFactory, IIntermediateResultsRequestor intRequestor, IProgressListener progressListener,
145 IOutputClassFileNameProvider outputFileNameProvider, IBinarySourceProvider binarySourceProvider,
146 Map fullBinarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
147 boolean isXterminateAfterCompilation, boolean proceedOnError, boolean noAtAspectJProcessing, boolean makeReflectable,
148 AjState incrementalCompilationState) {
149 this.compiler = compiler;
150 this.isBatchCompile = isBatchCompile;
151 this.weaver = weaver;
152 this.intermediateResultsRequestor = intRequestor;
153 this.progressListener = progressListener;
154 this.outputFileNameProvider = outputFileNameProvider;
155 this.binarySourceProvider = binarySourceProvider;
156 this.isXTerminateAfterCompilation = isXterminateAfterCompilation;
157 this.proceedOnError = proceedOnError;
158 this.binarySourceSetForFullWeave = fullBinarySourceEntries;
159 this.eWorld = eFactory;
160 this.inJava5Mode = false;
161 this.makeReflectable = makeReflectable;
162 this.noAtAspectJAnnotationProcessing = noAtAspectJProcessing;
163 this.incrementalCompilationState = incrementalCompilationState;
165 if (compiler.options.complianceLevel >= ClassFileConstants.JDK1_5) {
168 IMessageHandler msgHandler = world.getMessageHandler();
169 // Do we need to reset the message handler or create a new one? (This saves a ton of memory lost on incremental compiles...)
170 if (msgHandler instanceof WeaverMessageHandler) {
171 ((WeaverMessageHandler) msgHandler).resetCompiler(compiler);
172 weaverMessageHandler = (WeaverMessageHandler) msgHandler;
174 weaverMessageHandler = new WeaverMessageHandler(msgHandler, compiler);
175 world.setMessageHandler(weaverMessageHandler);
179 // the compilation lifecycle methods below are called in order as compilation progresses...
182 * In a pipelining compilation system, we need to ensure aspects are through the pipeline first. Only when they are all through
183 * (and therefore we know about all static/dynamic crosscutting) can be proceed to weave anything. Effectively the weaving part
184 * of the pipeline stalls until all the aspects have been fully compiled. This method sorts the compilation units such that any
185 * containing aspects are fully compiled first and it keeps a note on how long it should stall the pipeline before commencing
188 public void afterDietParsing(CompilationUnitDeclaration[] units) {
190 System.err.println("> afterDietParsing: there are " + (units == null ? 0 : units.length) + " units to sort");
193 if (!reportedErrors && units != null) {
194 for (CompilationUnitDeclaration unit : units) {
195 if (unit != null && unit.compilationResult != null && unit.compilationResult.hasErrors()) {
196 reportedErrors = true;
197 break; // TODO break or exit here?
202 // Break the units into two lists...
203 List<CompilationUnitDeclaration> aspects = new ArrayList<>();
204 List<CompilationUnitDeclaration> nonaspects = new ArrayList<>();
205 for (CompilationUnitDeclaration unit : units) {
206 if (containsAnAspect(unit)) {
209 nonaspects.add(unit);
213 // ...and put them back together, aspects first
215 for (CompilationUnitDeclaration aspect : aspects) {
216 units[posn++] = aspect;
218 for (CompilationUnitDeclaration nonaspect : nonaspects) {
219 units[posn++] = nonaspect;
222 // Work out how long to stall the pipeline
223 toWaitFor = aspects.size();
225 System.err.println("< afterDietParsing: stalling pipeline for " + toWaitFor + " source files");
229 if (pipelineTesting) {
230 if (pipelineOutput == null) {
231 pipelineOutput = new Hashtable();
233 pipelineOutput.put("filesContainingAspects", new Integer(toWaitFor).toString());
234 StringBuffer order = new StringBuffer();
236 for (int i = 0; i < units.length; i++) {
240 CompilationUnitDeclaration declaration = units[i];
241 String filename = new String(declaration.getFileName());
242 int idx = filename.lastIndexOf('/');
244 filename = filename.substring(idx + 1);
246 idx = filename.lastIndexOf('\\');
248 filename = filename.substring(idx + 1);
250 order.append(filename);
253 pipelineOutput.put("weaveOrder", order.toString());
257 public void beforeCompiling(ICompilationUnit[] sourceUnits) {
258 resultsPendingWeave = new ArrayList<>();
259 reportedErrors = false;
260 droppingBackToFullBuild = false;
263 public void beforeProcessing(CompilationUnitDeclaration unit) {
265 System.err.println("compiling " + new String(unit.getFileName()));
267 eWorld.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
268 processingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_COMPILATION_UNIT, unit
270 if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
271 ContextToken tok = CompilationAndWeavingContext.enteringPhase(
272 CompilationAndWeavingContext.ADDING_AT_ASPECTJ_ANNOTATIONS, unit.getFileName());
273 AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit, makeReflectable);
274 unit.traverse(atAspectJVisitor, unit.scope);
275 CompilationAndWeavingContext.leavingPhase(tok);
279 public void beforeResolving(CompilationUnitDeclaration unit) {
280 resolvingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.RESOLVING_COMPILATION_UNIT, unit
284 public void afterResolving(CompilationUnitDeclaration unit) {
285 if (resolvingToken != null) {
286 CompilationAndWeavingContext.leavingPhase(resolvingToken);
290 public void beforeAnalysing(CompilationUnitDeclaration unit) {
291 analysingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ANALYSING_COMPILATION_UNIT, unit
293 if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
294 ValidateAtAspectJAnnotationsVisitor atAspectJVisitor = new ValidateAtAspectJAnnotationsVisitor(unit);
295 unit.traverse(atAspectJVisitor, unit.scope);
299 public void afterAnalysing(CompilationUnitDeclaration unit) {
300 if (analysingToken != null) {
301 CompilationAndWeavingContext.leavingPhase(analysingToken);
305 public void beforeGenerating(CompilationUnitDeclaration unit) {
306 generatingToken = CompilationAndWeavingContext.enteringPhase(
307 CompilationAndWeavingContext.GENERATING_UNWOVEN_CODE_FOR_COMPILATION_UNIT, unit.getFileName());
308 if (eWorld.pushinCollector != null) {
309 if (unit.types != null && unit.types.length > 0) {
310 for (int t = 0; t < unit.types.length; t++) {
311 TypeDeclaration type = unit.types[t];
312 if (type.methods != null) {
313 for (int m = 0; m < type.methods.length; m++) {
314 AbstractMethodDeclaration md = type.methods[m];
315 if (md instanceof InterTypeMethodDeclaration) {
316 InterTypeMethodDeclaration itmd = ((InterTypeMethodDeclaration) md);
317 ITDMethodPrinter printer = new ITDMethodPrinter(itmd, md.scope);
318 String s = printer.print();
319 eWorld.pushinCollector.recordInterTypeMethodDeclarationCode(md, s, getDeclarationLineNumber(md));
320 } else if (md instanceof InterTypeFieldDeclaration) {
321 ITDFieldPrinter printer = new ITDFieldPrinter(((InterTypeFieldDeclaration) md), md.scope);
322 String s = printer.print();
323 eWorld.pushinCollector.recordInterTypeFieldDeclarationCode(md, s, getDeclarationLineNumber(md));
324 } else if (md instanceof InterTypeConstructorDeclaration) {
325 ITDConstructorPrinter printer = new ITDConstructorPrinter(((InterTypeConstructorDeclaration) md),
327 String s = printer.print();
328 eWorld.pushinCollector.recordInterTypeConstructorDeclarationCode(md, s,
329 getDeclarationLineNumber(md));
330 // } else if (md instanceof DeclareAnnotationDeclaration) {
331 // DeclareAnnotationDeclaration dad = (DeclareAnnotationDeclaration) md;
332 // String value = new DeclareAnnotationsPrinter(dad, dad.scope).print();
333 // eWorld.pushinCollector.recordDeclareAnnotationDeclarationCode(md, value);
339 eWorld.pushinCollector.setOutputFileNameProvider(outputFileNameProvider);
344 * @return the line number for this declaration in the source code
346 private int getDeclarationLineNumber(AbstractMethodDeclaration md) {
347 int sourceStart = md.sourceStart;
348 int[] separators = md.compilationResult.lineSeparatorPositions;
349 int declarationStartLine = 1;
350 for (int separator : separators) {
351 if (sourceStart < separator) {
354 declarationStartLine++;
356 return declarationStartLine;
359 public void afterGenerating(CompilationUnitDeclaration unit) {
360 if (generatingToken != null) {
361 CompilationAndWeavingContext.leavingPhase(generatingToken);
363 if (eWorld.pushinCollector != null) {
364 eWorld.pushinCollector.dump(unit);
368 public void afterCompiling(CompilationUnitDeclaration[] units) {
369 this.eWorld.cleanup();
370 if (!weaverInitialized) { // nothing got compiled, doesnt mean there is nothing to do... (binary weaving)
371 if (!(isXTerminateAfterCompilation || (reportedErrors && !proceedOnError))) {
372 // acceptResult(unit.compilationResult);
375 if (weaveQueuedEntries()) {
376 droppingBackToFullBuild = true;
378 } catch (IOException ex) {
379 AbortCompilation ac = new AbortCompilation(null, ex);
386 // not great ... but one more check before we continue, see pr132314
387 if (!reportedErrors && units != null) {
388 for (CompilationUnitDeclaration unit : units) {
389 if (unit != null && unit.compilationResult != null && unit.compilationResult.hasErrors()) {
390 reportedErrors = true;
395 if (isXTerminateAfterCompilation || (reportedErrors && !proceedOnError)) {
396 // no point weaving... just tell the requestor we're done
399 // weave(); // notification happens as weave progresses...
400 // weaver.getWorld().flush(); // pr152257
402 // } catch (IOException ex) {
403 // AbortCompilation ac = new AbortCompilation(null,ex);
405 } catch (RuntimeException rEx) {
406 if (rEx instanceof AbortCompilation) {
407 throw rEx; // Don't wrap AbortCompilation exceptions!
410 // This will be unwrapped in Compiler.handleInternalException() and the nested
411 // RuntimeException thrown back to the original caller - which is AspectJ
412 // which will then then log it as a compiler problem.
413 throw new AbortCompilation(true, rEx);
417 public void afterProcessing(CompilationUnitDeclaration unit, int unitIndex) {
418 CompilationAndWeavingContext.leavingPhase(processingToken);
419 eWorld.finishedCompilationUnit(unit);
420 InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult, outputFileNameProvider);
421 if (unit.compilationResult.hasErrors()) {
422 reportedErrors = true;
425 if (intermediateResultsRequestor != null) {
426 intermediateResultsRequestor.acceptResult(intRes);
429 if (unit.compilationResult.hasErrors() || (isXTerminateAfterCompilation || (reportedErrors && !proceedOnError))) {
430 acceptResult(unit.compilationResult);
432 queueForWeaving(intRes);
436 private void queueForWeaving(InterimCompilationResult intRes) {
437 resultsPendingWeave.add(intRes);
438 if (pipelineStalled) {
439 if (resultsPendingWeave.size() >= toWaitFor) {
440 pipelineStalled = false;
443 if (pipelineStalled) {
447 if (weaveQueuedEntries()) {
448 droppingBackToFullBuild = true;
450 } catch (IOException ex) {
451 AbortCompilation ac = new AbortCompilation(null, ex);
457 * Called from the weaverAdapter once it has finished weaving the class files associated with a given compilation result.
459 public void acceptResult(CompilationResult result) {
460 compiler.requestor.acceptResult(result.tagAsAccepted());
461 if (compiler.unitsToProcess != null) {
462 for (int i = 0; i < compiler.unitsToProcess.length; i++) {
463 if (compiler.unitsToProcess[i] != null) {
464 if (compiler.unitsToProcess[i].compilationResult == result) {
465 compiler.unitsToProcess[i].cleanUp();
466 compiler.unitsToProcess[i] = null;
474 // ==================================================================================
476 private List<InterimCompilationResult> getBinarySourcesFrom(Map<String, List<UnwovenClassFile>> binarySourceEntries) {
477 // Map is fileName |-> List<UnwovenClassFile>
478 List<InterimCompilationResult> ret = new ArrayList<>();
479 for (String sourceFileName : binarySourceEntries.keySet()) {
480 List<UnwovenClassFile> unwovenClassFiles = binarySourceEntries.get(sourceFileName);
481 // XXX - see bugs 57432,58679 - final parameter on next call should be "compiler.options.maxProblemsPerUnit"
482 CompilationResult result = new CompilationResult(sourceFileName.toCharArray(), 0, 0, Integer.MAX_VALUE);
483 result.noSourceAvailable();
484 InterimCompilationResult binarySource = new InterimCompilationResult(result, unwovenClassFiles);
485 ret.add(binarySource);
490 private void notifyRequestor() {
491 for (InterimCompilationResult iresult : resultsPendingWeave) {
492 compiler.requestor.acceptResult(iresult.result().tagAsAccepted());
496 /** Return true if we've decided to drop back to a full build (too much has changed) */
497 private boolean weaveQueuedEntries() throws IOException {
499 System.err.println(">.weaveQueuedEntries()");
501 for (InterimCompilationResult iresult : resultsPendingWeave) {
502 for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
503 weaver.addClassFile(iresult.unwovenClassFiles()[i], false);
506 ensureWeaverInitialized(); // by doing this only once, are we saying needToReweaveWorld can't change once the aspects have
507 // been stuffed into the weaver?
508 if (weaver.needToReweaveWorld() && !isBatchCompile) {
511 weaver.weave(new WeaverAdapter(this, weaverMessageHandler, progressListener));
512 resultsPendingWeave.clear(); // dont need to do those again
513 this.eWorld.minicleanup();
515 System.err.println("<.weaveQueuedEntries()");
520 private void ensureWeaverInitialized() {
521 if (weaverInitialized) {
524 weaverInitialized = true;
525 weaver.setIsBatchWeave(isBatchCompile);
526 weaver.prepareForWeave();
527 if (weaver.needToReweaveWorld()) {
528 if (!isBatchCompile) {
529 // force full recompilation from source
530 this.incrementalCompilationState.forceBatchBuildNextTimeAround();
533 resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
535 Map binarySourcesToAdd = binarySourceProvider.getBinarySourcesForThisWeave();
536 resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourcesToAdd));
540 // private void weave() throws IOException {
541 // if (debugPipeline)System.err.println("> weave()");
542 // // ensure weaver state is set up correctly
543 // for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
544 // InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
545 // for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
546 // weaver.addClassFile(iresult.unwovenClassFiles()[i]);
550 // weaver.setIsBatchWeave(isBatchCompile);
551 // weaver.prepareForWeave();
552 // if (weaver.needToReweaveWorld()) {
553 // if (!isBatchCompile) {
554 // //force full recompilation from source
555 // this.incrementalCompilationState.forceBatchBuildNextTimeAround();
558 // resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourceSetForFullWeave));
560 // Map binarySourcesToAdd = binarySourceProvider.getBinarySourcesForThisWeave();
561 // resultsPendingWeave.addAll(getBinarySourcesFrom(binarySourcesToAdd));
565 // weaver.weave(new WeaverAdapter(this,weaverMessageHandler,progressListener));
568 // IMessageHandler imh = weaver.getWorld().getMessageHandler();
569 // if (imh instanceof WeaverMessageHandler)
570 // ((WeaverMessageHandler)imh).resetCompiler(null);
572 // if (debugPipeline)System.err.println("< weave()");
575 private void postWeave() {
577 System.err.println("> postWeave()");
579 IMessageHandler imh = weaver.getWorld().getMessageHandler();
580 if (imh instanceof WeaverMessageHandler) {
581 ((WeaverMessageHandler) imh).setCurrentResult(null);
583 if (!droppingBackToFullBuild) {
584 weaver.allWeavingComplete();
587 if (imh instanceof WeaverMessageHandler) {
588 ((WeaverMessageHandler) imh).resetCompiler(null);
591 System.err.println("< postWeave()");
596 * Return true if the compilation unit declaration contains an aspect declaration (either code style or annotation style). It
597 * must inspect the multiple types that may be in a compilation unit declaration and any inner types.
599 private boolean containsAnAspect(CompilationUnitDeclaration cud) {
600 TypeDeclaration[] typeDecls = cud.types;
601 if (typeDecls != null) {
602 for (TypeDeclaration declaration : typeDecls) { // loop through top level types in the file
603 if (isAspect(declaration)) {
606 if (declaration.memberTypes != null) {
607 TypeDeclaration[] memberTypes = declaration.memberTypes;
608 for (TypeDeclaration memberType : memberTypes) { // loop through inner types
609 if (containsAnAspect(memberType)) {
619 private boolean containsAnAspect(TypeDeclaration tDecl) {
620 if (isAspect(tDecl)) {
623 if (tDecl.memberTypes != null) {
624 TypeDeclaration[] memberTypes = tDecl.memberTypes;
625 for (TypeDeclaration memberType : memberTypes) { // loop through inner types
626 if (containsAnAspect(memberType)) {
634 private static final char[] aspectSig = "Lorg/aspectj/lang/annotation/Aspect;".toCharArray();
636 private boolean isAspect(TypeDeclaration declaration) {
637 // avoid an NPE when something else is wrong in this system ... the real problem will be reported elsewhere
638 if (declaration.staticInitializerScope == null) {
641 if (declaration instanceof AspectDeclaration) {
642 return true; // code style
643 } else if (declaration.annotations != null) { // check for annotation style
644 for (int index = 0; index < declaration.annotations.length; index++) {
645 // Cause annotation resolution
646 declaration.binding.getAnnotationTagBits();
647 Annotation a = declaration.annotations[index];
648 if (a.resolvedType == null) {
649 continue; // another problem is being reported, so don't crash here
651 if (CharOperation.equals(a.resolvedType.signature(), aspectSig)) {
661 * SECRET: FOR TESTING - this can be used to collect information that tests can verify.
663 public static boolean pipelineTesting = false;
664 public static Hashtable<String, String> pipelineOutput = null;
666 // Keys into pipelineOutput:
667 // compileOrder "[XXX,YYY]" a list of the order in which files will be woven (aspects should be first)
668 // filesContainingAspects "NNN" how many input source files have aspects inside
671 public static String getPipelineDebugOutput(String key) {
672 if (pipelineOutput == null) {
675 return pipelineOutput.get(key);
678 private final static boolean debugPipeline = false;
680 public List<InterimCompilationResult> getResultsPendingWeave() {
681 return resultsPendingWeave;