aboutsummaryrefslogtreecommitdiffstats
path: root/org.aspectj.ajdt.core
diff options
context:
space:
mode:
authoracolyer <acolyer>2004-03-15 15:10:46 +0000
committeracolyer <acolyer>2004-03-15 15:10:46 +0000
commit40680b6fe4d28b2d061fc4cf9b3efa6640c12f44 (patch)
tree9d90cff75d3b351d06b42dd9088f543de2debbd2 /org.aspectj.ajdt.core
parentec9ac363b0379ce8bb8c0783ab338d8ffaa9da02 (diff)
downloadaspectj-40680b6fe4d28b2d061fc4cf9b3efa6640c12f44.tar.gz
aspectj-40680b6fe4d28b2d061fc4cf9b3efa6640c12f44.zip
move weaving to inside of the compiler.compile loop.
ensure messages are associated with source wherever possible
Diffstat (limited to 'org.aspectj.ajdt.core')
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjClassFile.java37
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompiler.java725
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java231
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ClassFileBasedByteCodeProvider.java50
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/IIntermediateResultsRequestor.java21
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/IOutputClassFileNameProvider.java24
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/InterimCompilationResult.java68
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverAdapter.java163
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java176
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceLocation.java12
10 files changed, 1438 insertions, 69 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjClassFile.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjClassFile.java
new file mode 100644
index 000000000..ef4a4a415
--- /dev/null
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjClassFile.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import org.eclipse.jdt.internal.compiler.ClassFile;
+
+/**
+ * @author colyer
+ *
+ * XXX lightweight subclass of ClassFile that only genuinely supports fileName and getBytes
+ * operations. This nasty hack enables us to keep the rest of the implementation much simpler.
+ */
+public class AjClassFile extends ClassFile {
+ char[] filename;
+ byte[] bytes;
+
+ public AjClassFile(char[] fileName, byte[] byteCodes) {
+ this.filename = fileName;
+ bytes = byteCodes;
+ }
+
+ public char[] fileName() {
+ return filename;
+ }
+
+ public byte[] getBytes() {
+ return bytes;
+ }
+}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompiler.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompiler.java
index 2fce1117f..fef05581c 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompiler.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompiler.java
@@ -1,69 +1,656 @@
-/* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Common Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * PARC initial implementation
- * ******************************************************************/
-
-
-package org.aspectj.ajdt.internal.compiler;
-
-import java.util.Map;
-
-import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
-import org.aspectj.bridge.IMessage;
-import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
-import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
-import org.eclipse.jdt.internal.compiler.IProblemFactory;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
-
-
-public class AjCompiler extends Compiler {
-
- public AjCompiler(
- INameEnvironment environment,
- IErrorHandlingPolicy policy,
- Map settings,
- ICompilerRequestor requestor,
- IProblemFactory problemFactory) {
- super(environment, policy, settings, requestor, problemFactory);
- }
-
- public AjCompiler(
- INameEnvironment environment,
- IErrorHandlingPolicy policy,
- Map settings,
- ICompilerRequestor requestor,
- IProblemFactory problemFactory,
- boolean parseLiteralExpressionsAsConstants) {
- super(
- environment,
- policy,
- settings,
- requestor,
- problemFactory,
- parseLiteralExpressionsAsConstants);
- }
-
- /**
- * In addition to processing each compilation unit in the normal ways,
- * we also need to do weaving for inter-type declarations. This
- * must be done before we use the signatures of these types to do any
- * name binding.
- */
- public void process(CompilationUnitDeclaration unit, int i) {
- EclipseFactory world =
- EclipseFactory.fromLookupEnvironment(lookupEnvironment);
- world.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
- super.process(unit, i);
-
- world.finishedCompilationUnit(unit);
- }
-}
+///* *******************************************************************
+// * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+// * All rights reserved.
+// * This program and the accompanying materials are made available
+// * under the terms of the Common Public License v1.0
+// * which accompanies this distribution and is available at
+// * http://www.eclipse.org/legal/cpl-v10.html
+// *
+// * Contributors:
+// * PARC initial implementation
+// * ******************************************************************/
+//
+//
+//package org.aspectj.ajdt.internal.compiler;
+//
+//import java.io.IOException;
+//import java.util.ArrayList;
+//import java.util.Collection;
+//import java.util.Collections;
+//import java.util.Enumeration;
+//import java.util.Hashtable;
+//import java.util.Iterator;
+//import java.util.List;
+//import java.util.Map;
+//
+//import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
+//import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
+//import org.aspectj.bridge.AbortException;
+//import org.aspectj.bridge.IMessage;
+//import org.aspectj.bridge.IMessageHandler;
+//import org.aspectj.bridge.ISourceLocation;
+//import org.aspectj.bridge.IMessage.Kind;
+//import org.aspectj.weaver.IClassFileProvider;
+//import org.aspectj.weaver.IWeaveRequestor;
+//import org.aspectj.weaver.bcel.BcelWeaver;
+//import org.aspectj.weaver.bcel.BcelWorld;
+//import org.aspectj.weaver.bcel.Pause;
+//import org.aspectj.weaver.bcel.UnwovenClassFile;
+//import org.aspectj.weaver.bcel.UnwovenClassFileWithThirdPartyManagedBytecode;
+//import org.eclipse.jdt.core.compiler.IProblem;
+//import org.eclipse.jdt.internal.compiler.ClassFile;
+//import org.eclipse.jdt.internal.compiler.CompilationResult;
+//import org.eclipse.jdt.internal.compiler.Compiler;
+//import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
+//import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
+//import org.eclipse.jdt.internal.compiler.IProblemFactory;
+//import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+//import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+//import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+//import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+//import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
+//import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+//
+//
+//public class AjCompiler extends Compiler {
+//
+// private List /*InterimResult*/ resultsPendingWeave = new ArrayList();
+// private BcelWorld bcelWorld;
+// private BcelWeaver bcelWeaver;
+// private IIntermediateResultsRequestor intermediateResultRequestor;
+// private IOutputClassFileNameProvider nameProvider;
+// private List /*<InterimResult>*/ binarySources = new ArrayList();
+// private boolean skipTheWeavePhase = false;
+// private boolean reportedErrors = false;
+// private WeaverMessageHandler wmHandler;
+// private boolean isBatchCompile = false;
+// private Collection /*InterimResult*/ resultSetForFullWeave = Collections.EMPTY_LIST;
+//
+// public interface IIntermediateResultsRequestor {
+// void acceptResult(InterimResult intRes);
+// }
+//
+// public interface IOutputClassFileNameProvider {
+// String getOutputClassFileName(char[] eclipseClassFileName, CompilationResult result);
+// }
+//
+// public AjCompiler(
+// INameEnvironment environment,
+// IErrorHandlingPolicy policy,
+// Map settings,
+// ICompilerRequestor requestor,
+// IProblemFactory problemFactory) {
+// super(environment, policy, settings, requestor, problemFactory);
+// }
+//
+// public AjCompiler(
+// INameEnvironment environment,
+// IErrorHandlingPolicy policy,
+// Map settings,
+// ICompilerRequestor requestor,
+// IProblemFactory problemFactory,
+// boolean parseLiteralExpressionsAsConstants) {
+// super(
+// environment,
+// policy,
+// settings,
+// requestor,
+// problemFactory,
+// parseLiteralExpressionsAsConstants);
+// }
+//
+//
+// public void setWeaver(BcelWeaver weaver) {
+// this.bcelWeaver = weaver;
+// }
+//
+// public void setWorld(BcelWorld world) {
+// this.bcelWorld = world;
+// IMessageHandler msgHandler = world.getMessageHandler();
+// wmHandler = new WeaverMessageHandler(msgHandler);
+// world.setMessageHandler(wmHandler);
+// }
+//
+// public void prepareForBatchCompilation() {
+// isBatchCompile = true;
+// }
+//
+// public void setIntermediateResultsRequestor(IIntermediateResultsRequestor intReq) {
+// this.intermediateResultRequestor = intReq;
+// }
+//
+// public void setNoWeave(boolean noWeave) {
+// skipTheWeavePhase = noWeave;
+// }
+//
+// public void setFullWeaveResults(Collection compilationResults) {
+// resultSetForFullWeave = compilationResults;
+// }
+//
+// public void setOutputFileNameProvider(IOutputClassFileNameProvider p) {
+// this.nameProvider = p;
+// }
+//
+// public void addBinarySourceFiles(Map binarySourceEntries) {
+// // Map is fileName |-> List<UnwovenClassFile>
+// for (Iterator binIter = binarySourceEntries.keySet().iterator(); binIter.hasNext();) {
+// String sourceFileName = (String) binIter.next();
+// List unwovenClassFiles = (List) binarySourceEntries.get(sourceFileName);
+//
+// CompilationResult result = new CompilationResult(sourceFileName.toCharArray(),0,0,20);
+// result.noSourceAvailable();
+// InterimResult binarySource = new InterimResult(result,nameProvider);
+// binarySource.unwovenClassFiles = new UnwovenClassFile[unwovenClassFiles.size()];
+// int index = 0;
+// for (Iterator iter = unwovenClassFiles.iterator(); iter.hasNext();) {
+// UnwovenClassFile element = (UnwovenClassFile) iter.next();
+// binarySource.unwovenClassFiles[index] = element;
+// AjClassFile ajcf = new AjClassFile(element.getClassName().replace('.', '/').toCharArray(),
+// element.getBytes());
+// result.record(ajcf.fileName(),ajcf);
+// index++;
+// }
+// binarySources.add(binarySource);
+// }
+// }
+//
+//
+// /**
+// * In addition to processing each compilation unit in the normal ways,
+// * we also need to do weaving for inter-type declarations. This
+// * must be done before we use the signatures of these types to do any
+// * name binding.
+// */
+// public void process(CompilationUnitDeclaration unit, int i) {
+// EclipseFactory world =
+// EclipseFactory.fromLookupEnvironment(lookupEnvironment);
+// world.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
+// super.process(unit, i);
+//
+// world.finishedCompilationUnit(unit);
+// }
+//
+//
+// /* (non-Javadoc)
+// * @see org.eclipse.jdt.internal.compiler.Compiler#compile(org.eclipse.jdt.internal.compiler.env.ICompilationUnit[])
+// * We override this method to defer handing of results to the caller until the weave phase has
+// * completed too. That way the class files are in final form and all error messages relating to the
+// * compilation unit have been reported (which is the contract the JDT expects from this method).
+// */
+// public void compile(ICompilationUnit[] sourceUnits) {
+// try {
+// resultsPendingWeave = new ArrayList();
+// reportedErrors = false;
+// super.compile(sourceUnits);
+// Pause.pause("After super compile");
+// try {
+// if (!(skipTheWeavePhase || reportedErrors)) {
+// weaveResults();
+// Pause.pause("After weave");
+// } else {
+// notifyRequestor(); // weaver notifies as it goes along...
+// }
+// } catch (IOException ex) {
+// // TODO
+// ex.printStackTrace();
+// }
+// } finally {
+// cleanup();
+// }
+// }
+//
+//
+// /* (non-Javadoc)
+// * @see org.eclipse.jdt.internal.compiler.Compiler#registerCompilationResult(org.eclipse.jdt.internal.compiler.CompilationResult)
+// */
+// protected void registerCompilationResult(int index, CompilationResult result) {
+// InterimResult intRes = new InterimResult(result,nameProvider);
+// resultsPendingWeave.add(intRes);
+// if (result.hasErrors()) reportedErrors = true;
+// if (intermediateResultRequestor != null) {
+// intermediateResultRequestor.acceptResult(intRes);
+// }
+// }
+//
+// /* (non-Javadoc)
+// * @see org.eclipse.jdt.internal.compiler.Compiler#reset()
+// * Super does this too early for us...
+// */
+// public void reset() {
+// // no-op, super calls this too early for us...
+// }
+//
+// /* (non-Javadoc)
+// * @see org.eclipse.jdt.internal.compiler.Compiler#resolve(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration, org.eclipse.jdt.internal.compiler.env.ICompilationUnit, boolean, boolean, boolean)
+// */
+// public CompilationUnitDeclaration resolve(CompilationUnitDeclaration unit,
+// ICompilationUnit sourceUnit, boolean verifyMethods,
+// boolean analyzeCode, boolean generateCode) {
+// // TODO include weave phase in resolution too...
+// return super.resolve(unit, sourceUnit, verifyMethods, analyzeCode,
+// generateCode);
+// }
+//
+//
+// // AspectJ helper methods, called from compile...
+// private void weaveResults() throws IOException {
+// // ensure weaver state is set up correctly
+// for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
+// InterimResult iresult = (InterimResult) iter.next();
+// for (int i = 0; i < iresult.unwovenClassFiles.length; i++) {
+// bcelWeaver.addClassFile(iresult.unwovenClassFiles[i]);
+// }
+// }
+// Pause.pause("After adding class files to weaver");
+// bcelWeaver.prepareForWeave();
+// Pause.pause("After preparing for weave");
+// if (isBatchCompile) {
+// resultsPendingWeave.addAll(binarySources);
+// // passed into the compiler, the set of classes in injars and inpath...
+// } else if (bcelWeaver.needToReweaveWorld()) {
+// addAllKnownClassesToWeaveList();
+// }
+// Pause.pause("After adding binary sources to weaver");
+// bcelWeaver.weave(new WeaverAdaptor(this));
+// }
+//
+// private void notifyRequestor() {
+// for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
+// InterimResult iresult = (InterimResult) iter.next();
+// requestor.acceptResult(iresult.result.tagAsAccepted());
+// }
+// }
+//
+// private void cleanup() {
+// resultsPendingWeave = null;
+// isBatchCompile = false;
+// binarySources = new ArrayList();
+// resultSetForFullWeave = Collections.EMPTY_LIST;
+// super.reset();
+// Pause.pause("After notify and cleanup");
+// }
+//
+// private void addAllKnownClassesToWeaveList() {
+// // results pending weave already has some results from this (incremental) compile
+// // add in results from any other source
+// for (Iterator iter = resultSetForFullWeave.iterator(); iter.hasNext();) {
+// InterimResult ir = (InterimResult) iter.next();
+// if (!resultsPendingWeave.contains(ir)) { // equality based on source file name...
+// ir.result.hasBeenAccepted = false; // it may have been accepted before, start again
+// resultsPendingWeave.add(ir);
+// }
+// }
+// }
+//
+// // Helper class that feeds input to the weaver, and accepts results
+// // =======================================================================================
+// private static class WeaverAdaptor implements IClassFileProvider, IWeaveRequestor, Iterator {
+//
+// private AjCompiler compiler;
+// private Iterator resultIterator;
+// private int classFileIndex = 0;
+// private InterimResult nowProcessing;
+// private InterimResult lastReturnedResult;
+//// private CompilationResult lastAcceptedResult;
+// private boolean finalPhase = false;
+//
+//
+// public WeaverAdaptor(AjCompiler forCompiler) { this.compiler = forCompiler; }
+//
+// /* (non-Javadoc)
+// * @see org.aspectj.weaver.IClassFileProvider#getClassFileIterator()
+// */
+// public Iterator getClassFileIterator() {
+// classFileIndex = 0;
+// nowProcessing = null;
+// lastReturnedResult = null;
+// resultIterator = compiler.resultsPendingWeave.iterator();
+// return this;
+// }
+// /* (non-Javadoc)
+// * @see org.aspectj.weaver.IClassFileProvider#getRequestor()
+// */
+// public IWeaveRequestor getRequestor() {
+// return this;
+// }
+// /* (non-Javadoc)
+// * @see org.aspectj.weaver.IWeaveRequestor#acceptResult(org.aspectj.weaver.bcel.UnwovenClassFile)
+// */
+// public void acceptResult(UnwovenClassFile result) {
+// char[] key = result.getClassName().replace('.','/').toCharArray();
+// removeFromHashtable(lastReturnedResult.result.compiledTypes,key);
+// String className = result.getClassName().replace('.', '/');
+// AjClassFile ajcf = new AjClassFile(className.toCharArray(),
+// result.getBytes());
+// lastReturnedResult.result.record(ajcf.fileName(),ajcf);
+//// if ( f(lastAcceptedResult != null) && (lastReturnedResult.result != lastAcceptedResult)) {
+//// // we've got everything we need for lastAcceptedResult, push the result out
+//// // and free up the memory.
+//// finishedWith(lastAcceptedResult);
+//// }
+//// lastAcceptedResult = lastReturnedResult.result;
+// }
+//
+// private void finishedWith(InterimResult result) {
+// compiler.requestor.acceptResult(result.result.tagAsAccepted());
+// for (int i = 0; i < compiler.unitsToProcess.length; i++) {
+// if (compiler.unitsToProcess[i] != null) {
+// if (compiler.unitsToProcess[i].compilationResult == result.result) {
+// compiler.unitsToProcess[i] = null;
+// }
+// }
+// }
+// }
+//
+// /* (non-Javadoc)
+// * @see java.util.Iterator#hasNext()
+// */
+// public boolean hasNext() {
+// if (nowProcessing == null) {
+// if (!resultIterator.hasNext()) return false;
+// nowProcessing = (InterimResult) resultIterator.next();
+// classFileIndex = 0;
+// }
+// while (nowProcessing.unwovenClassFiles.length == 0 ) {
+// if (!resultIterator.hasNext()) return false;
+// nowProcessing = (InterimResult) resultIterator.next();
+// }
+// if (classFileIndex < nowProcessing.unwovenClassFiles.length) {
+// return true;
+// } else {
+// classFileIndex = 0;
+// if (!resultIterator.hasNext()) return false;
+// nowProcessing = (InterimResult) resultIterator.next();
+// while (nowProcessing.unwovenClassFiles.length == 0 ) {
+// if (!resultIterator.hasNext()) return false;
+// nowProcessing = (InterimResult) resultIterator.next();
+// }
+// }
+// return true;
+// }
+// /* (non-Javadoc)
+// * @see java.util.Iterator#next()
+// */
+// public Object next() {
+// if (!hasNext()) return null; // sets up indices correctly
+// if (finalPhase) {
+// if ((lastReturnedResult != null) && (lastReturnedResult != nowProcessing)) {
+// // we're done with the lastReturnedResult
+// finishedWith(lastReturnedResult);
+// }
+// }
+// lastReturnedResult = nowProcessing;
+// compiler.wmHandler.setCurrentResult(nowProcessing.result);
+// return nowProcessing.unwovenClassFiles[classFileIndex++];
+// }
+// /* (non-Javadoc)
+// * @see java.util.Iterator#remove()
+// */
+// public void remove() {
+// throw new UnsupportedOperationException();
+// }
+//
+// public void processingReweavableState() {}
+// public void addingTypeMungers() {}
+// public void weavingAspects() {}
+// public void weavingClasses() {finalPhase = true;}
+// public void weaveCompleted() {
+// if ((lastReturnedResult != null) && (!lastReturnedResult.result.hasBeenAccepted)) {
+// finishedWith(lastReturnedResult);
+// }
+// }
+//
+// private void removeFromHashtable(Hashtable table, char[] key) {
+// // jdt uses char[] as a key in the hashtable, which is not very useful as equality is based on being
+// // the same array, not having the same content.
+// String skey = new String(key);
+// char[] victim = null;
+// for (Enumeration iter = table.keys(); iter.hasMoreElements();) {
+// char[] thisKey = (char[]) iter.nextElement();
+// if (skey.equals(new String(thisKey))) {
+// victim = thisKey;
+// break;
+// }
+// }
+// if (victim != null) {
+// table.remove(victim);
+// }
+// }
+//}
+//
+// // Holder for intermediate form (class files)
+// // =======================================================================================
+// public static class InterimResult {
+// public CompilationResult result;
+// public UnwovenClassFile[] unwovenClassFiles; // longer term would be nice not to have two copies of
+// // the byte codes, one in result.classFiles and another
+// // in unwovenClassFiles;
+// private AjCompiler.IOutputClassFileNameProvider nameGen;
+//// public String[] classNames; // entry at index i is the name of the class at unwovenClassFiles[i]
+//// public BcelObjectType[] classTypes; // entry at i is the resolved type of the class at unwovenClassFiles[i]
+// public InterimResult(CompilationResult cr, AjCompiler.IOutputClassFileNameProvider np) {
+// result = cr;
+// nameGen = np;
+// unwovenClassFiles = ClassFileBasedByteCodeProvider.unwovenClassFilesFor(result,nameGen);
+// }
+//
+// public String fileName() {
+// return new String(result.fileName);
+// }
+//
+// public boolean equals(Object other) {
+// if( other == null || !(other instanceof InterimResult)) {
+// return false;
+// }
+// InterimResult ir = (InterimResult) other;
+// return fileName().equals(ir.fileName());
+// }
+// public int hashCode() {
+// return fileName().hashCode();
+// }
+// };
+//
+//
+//
+// // XXX lightweight subclass of ClassFile that only genuinely supports fileName and getBytes
+// // operations.
+// // =========================================================================================
+// private static class AjClassFile extends ClassFile {
+//
+// char[] filename;
+// byte[] bytes;
+//
+// public AjClassFile(char[] fileName, byte[] byteCodes) {
+// this.filename = fileName;
+// bytes = byteCodes;
+// }
+//
+// public char[] fileName() {
+// return filename;
+// }
+//
+// public byte[] getBytes() {
+// return bytes;
+// }
+// };
+//
+//
+// // Adaptor for ClassFiles that lets them act as the bytecode repository
+// // for UnwovenClassFiles (asking a ClassFile for its bytes causes a
+// // copy to be made).
+// private static class ClassFileBasedByteCodeProvider
+// implements UnwovenClassFileWithThirdPartyManagedBytecode.IByteCodeProvider {
+// private ClassFile cf;
+//
+// public ClassFileBasedByteCodeProvider(ClassFile cf) {
+// this.cf = cf;
+// }
+//
+// public byte[] getBytes() {
+// return cf.getBytes();
+// }
+//
+// public static UnwovenClassFile[] unwovenClassFilesFor(CompilationResult result,
+// AjCompiler.IOutputClassFileNameProvider nameProvider) {
+// ClassFile[] cfs = result.getClassFiles();
+// UnwovenClassFile[] ret = new UnwovenClassFile[cfs.length];
+// for (int i = 0; i < ret.length; i++) {
+// ClassFileBasedByteCodeProvider p = new ClassFileBasedByteCodeProvider(cfs[i]);
+// String fileName = nameProvider.getOutputClassFileName(cfs[i].fileName(), result);
+// ret[i] = new UnwovenClassFileWithThirdPartyManagedBytecode(fileName,p);
+// }
+// return ret;
+// }
+//
+// }
+//
+// // Inner class for handling messages produced by the weaver
+// // ==========================================================
+//
+// private class WeaverMessageHandler implements IMessageHandler {
+// IMessageHandler sink;
+// CompilationResult currentlyWeaving;
+//
+// public WeaverMessageHandler(IMessageHandler handler) {
+// this.sink = handler;
+// }
+//
+// public void setCurrentResult(CompilationResult result) {
+// currentlyWeaving = result;
+// }
+//
+// public boolean handleMessage(IMessage message) throws AbortException {
+// if (! (message.isError() || message.isWarning()) ) return sink.handleMessage(message);
+// // we only care about warnings and errors here...
+// ISourceLocation sLoc = message.getSourceLocation();
+// CompilationResult problemSource = currentlyWeaving;
+// if (problemSource == null) {
+// // must be a problem found during completeTypeBindings phase of begin to compile
+// if (sLoc instanceof EclipseSourceLocation) {
+// problemSource = ((EclipseSourceLocation)sLoc).getCompilationResult();
+// }
+// if (problemSource == null) {
+// // XXX this is ok for ajc, will have to do better for AJDT in time...
+// return sink.handleMessage(message);
+// }
+// }
+// int startPos = getStartPos(sLoc,problemSource);
+// int endPos = getEndPos(sLoc,problemSource);
+// int severity = message.isError() ? ProblemSeverities.Error : ProblemSeverities.Warning;
+// char[] filename = problemSource.fileName;
+// boolean usedBinarySourceFileName = false;
+// if (problemSource.isFromBinarySource()) {
+// if (sLoc != null) {
+// filename = sLoc.getSourceFile().getPath().toCharArray();
+// usedBinarySourceFileName = true;
+// }
+// }
+// ReferenceContext referenceContext = findReferenceContextFor(problemSource);
+// IProblem problem = problemReporter.createProblem(
+// filename,
+// IProblem.Unclassified,
+// new String[0],
+// new String[] {message.getMessage()},
+// severity,
+// startPos,
+// endPos,
+// sLoc != null ? sLoc.getLine() : 1,
+// referenceContext,
+// problemSource
+// );
+// IProblem[] seeAlso = buildSeeAlsoProblems(message.getExtraSourceLocations(),
+// problemSource,
+// usedBinarySourceFileName);
+// problem.setSeeAlsoProblems(seeAlso);
+// if (message.getDetails() != null) {
+// problem.setSupplementaryMessageInfo(message.getDetails());
+// }
+// problemReporter.record(problem, problemSource, referenceContext);
+// return true;
+//// if (weavingPhase) {
+//// return sink.handleMessage(message);
+//// } else {
+//// return true; // message will be reported back in compilation result later...
+//// }
+// }
+//
+// public boolean isIgnoring(Kind kind) {
+// return sink.isIgnoring(kind);
+// }
+//
+// private int getStartPos(ISourceLocation sLoc,CompilationResult result) {
+// int pos = 0;
+// if (sLoc == null) return 0;
+// int line = sLoc.getLine();
+// if (sLoc instanceof EclipseSourceLocation) {
+// pos = ((EclipseSourceLocation)sLoc).getStartPos();
+// } else {
+// if (line <= 1) return 0;
+// if (result != null) {
+// if ((result.lineSeparatorPositions != null) &&
+// (result.lineSeparatorPositions.length >= (line-1))) {
+// pos = result.lineSeparatorPositions[line-2] + 1;
+// }
+// }
+// }
+// return pos;
+// }
+//
+// private int getEndPos(ISourceLocation sLoc,CompilationResult result) {
+// int pos = 0;
+// if (sLoc == null) return 0;
+// int line = sLoc.getLine();
+// if (line <= 0) line = 1;
+// if (sLoc instanceof EclipseSourceLocation) {
+// pos = ((EclipseSourceLocation)sLoc).getEndPos();
+// } else {
+// if (result != null) {
+// if ((result.lineSeparatorPositions != null) &&
+// (result.lineSeparatorPositions.length >= line)) {
+// pos = result.lineSeparatorPositions[line -1] -1;
+// }
+// }
+// }
+// return pos;
+// }
+//
+// private ReferenceContext findReferenceContextFor(CompilationResult result) {
+// ReferenceContext context = null;
+// if (unitsToProcess == null) return null;
+// for (int i = 0; i < unitsToProcess.length; i++) {
+// if ((unitsToProcess[i] != null) &&
+// (unitsToProcess[i].compilationResult == result)) {
+// context = unitsToProcess[i];
+// break;
+// }
+// }
+// return context;
+// }
+//
+// private IProblem[] buildSeeAlsoProblems(List sourceLocations,
+// CompilationResult problemSource,
+// boolean usedBinarySourceFileName) {
+// int probLength = sourceLocations.size();
+// if (usedBinarySourceFileName) probLength++;
+// IProblem[] ret = new IProblem[probLength];
+// for (int i = 0; i < sourceLocations.size(); i++) {
+// ISourceLocation loc = (ISourceLocation) sourceLocations.get(i);
+// ret[i] = new DefaultProblem(loc.getSourceFile().getPath().toCharArray(),
+// "see also",
+// 0,
+// new String[] {},
+// ProblemSeverities.Ignore,
+// getStartPos(loc,null),
+// getEndPos(loc,null),
+// loc.getLine());
+// }
+// if (usedBinarySourceFileName) {
+// ret[ret.length -1] = new DefaultProblem(problemSource.fileName,"see also",0,new String[] {},
+// ProblemSeverities.Ignore,0,
+// 0,0);
+// }
+// return ret;
+// }
+// }
+//
+//}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java
new file mode 100644
index 000000000..ab3cebdb2
--- /dev/null
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/AjCompilerAdapter.java
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.weaver.bcel.BcelWeaver;
+import org.aspectj.weaver.bcel.BcelWorld;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.ICompilerAdapter;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+
+/**
+ * @author colyer
+ *
+ * Adapts standard JDT Compiler to add in AspectJ specific behaviours.
+ */
+public class AjCompilerAdapter implements ICompilerAdapter {
+
+ private Compiler compiler;
+ private BcelWeaver weaver;
+ private EclipseFactory eWorld;
+ private boolean isBatchCompile;
+ private boolean reportedErrors;
+ private boolean isXNoWeave;
+ private IIntermediateResultsRequestor intermediateResultsRequestor;
+ private IOutputClassFileNameProvider outputFileNameProvider;
+ private WeaverMessageHandler weaverMessageHandler;
+ private List /* InterimCompilationResult */ binarySources = new ArrayList();
+ private Collection /*InterimCompilationResult*/ resultSetForFullWeave = Collections.EMPTY_LIST;
+
+
+ List /*InterimResult*/ resultsPendingWeave = new ArrayList();
+
+ /**
+ * Create an adapter, and tell it everything it needs to now to drive the AspectJ
+ * parts of a compile cycle.
+ * @param compiler the JDT compiler that produces class files from source
+ * @param isBatchCompile true if this is a full build (non-incremental)
+ * @param world the bcelWorld used for type resolution during weaving
+ * @param weaver the weaver
+ * @param intRequestor recipient of interim compilation results from compiler (pre-weave)
+ * @param outputFileNameProvider implementor of a strategy providing output file names for results
+ * @param binarySourceEntries binary source that we didn't compile, but that we need to weave
+ * @param resultSetForFullWeave if we are doing an incremental build, and the weaver determines
+ * that we need to weave the world, this is the set of intermediate
+ * results that will be passed to the weaver.
+ * @param isXNoWeave
+ */
+ public AjCompilerAdapter(Compiler compiler,
+ boolean isBatchCompile,
+ BcelWorld world,
+ BcelWeaver weaver,
+ EclipseFactory eFactory,
+ IIntermediateResultsRequestor intRequestor,
+ IOutputClassFileNameProvider outputFileNameProvider,
+ Map binarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
+ Collection /* InterimCompilationResult */ resultSetForFullWeave,
+ boolean isXNoWeave) {
+ this.compiler = compiler;
+ this.isBatchCompile = isBatchCompile;
+ this.weaver = weaver;
+ this.intermediateResultsRequestor = intRequestor;
+ this.outputFileNameProvider = outputFileNameProvider;
+ this.isXNoWeave = isXNoWeave;
+ this.resultSetForFullWeave = resultSetForFullWeave;
+ this.eWorld = eFactory;
+
+ IMessageHandler msgHandler = world.getMessageHandler();
+ weaverMessageHandler = new WeaverMessageHandler(msgHandler, compiler);
+ world.setMessageHandler(weaverMessageHandler);
+
+ addBinarySource(binarySourceEntries);
+ }
+
+ public void beforeCompiling(ICompilationUnit[] sourceUnits) {
+ resultsPendingWeave = new ArrayList();
+ reportedErrors = false;
+ }
+
+ public void afterCompiling() {
+ try {
+ if (isXNoWeave || reportedErrors) {
+ // no point weaving... just tell the requestor we're done
+ notifyRequestor();
+ } else {
+ weave(); // notification happens as weave progresses...
+ }
+ } catch (IOException ex) {
+ AbortCompilation ac = new AbortCompilation();
+ ac.initCause(ex);
+ throw ac;
+ }
+ }
+
+ public void beforeProcessing(CompilationUnitDeclaration unit) {
+ eWorld.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null);
+ }
+
+ public void afterProcessing(CompilationUnitDeclaration unit, int unitIndex) {
+ eWorld.finishedCompilationUnit(unit);
+ InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult,outputFileNameProvider);
+ if (unit.compilationResult.hasErrors()) reportedErrors = true;
+
+ if (intermediateResultsRequestor != null) {
+ intermediateResultsRequestor.acceptResult(intRes);
+ }
+
+ if (isXNoWeave) {
+ acceptResult(unit.compilationResult);
+ } else {
+ resultsPendingWeave.add(intRes);
+ }
+ }
+
+ public void beforeResolving(CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean analyzeCode, boolean generateCode) {
+ resultsPendingWeave = new ArrayList();
+ reportedErrors = false;
+ }
+
+ public void afterResolving(CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean analyzeCode, boolean generateCode) {
+ InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult,outputFileNameProvider);
+ if (unit.compilationResult.hasErrors()) reportedErrors = true;
+ if (isXNoWeave || !generateCode) {
+ acceptResult(unit.compilationResult);
+ } else if (generateCode){
+ resultsPendingWeave.add(intRes);
+ try {
+ weave();
+ } catch (IOException ex) {
+ AbortCompilation ac = new AbortCompilation();
+ ac.initCause(ex);
+ throw ac;
+ }
+ }
+ }
+
+ // helper methods...
+ // ==================================================================================
+
+ /*
+ * Called from the weaverAdapter once it has finished weaving the class files
+ * associated with a given compilation result.
+ */
+ public void acceptResult(CompilationResult result) {
+ compiler.requestor.acceptResult(result.tagAsAccepted());
+ if (compiler.unitsToProcess != null) {
+ for (int i = 0; i < compiler.unitsToProcess.length; i++) {
+ if (compiler.unitsToProcess[i] != null) {
+ if (compiler.unitsToProcess[i].compilationResult == result) {
+ compiler.unitsToProcess[i] = null;
+ }
+ }
+ }
+ }
+ }
+
+ private void addBinarySource(Map binarySourceEntries) {
+ // Map is fileName |-> List<UnwovenClassFile>
+ for (Iterator binIter = binarySourceEntries.keySet().iterator(); binIter.hasNext();) {
+ String sourceFileName = (String) binIter.next();
+ List unwovenClassFiles = (List) binarySourceEntries.get(sourceFileName);
+
+ CompilationResult result = new CompilationResult(sourceFileName.toCharArray(),0,0,20);
+ result.noSourceAvailable();
+ InterimCompilationResult binarySource =
+ new InterimCompilationResult(result,unwovenClassFiles);
+ binarySources.add(binarySource);
+ }
+ }
+
+ private void notifyRequestor() {
+ for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
+ InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
+ compiler.requestor.acceptResult(iresult.result().tagAsAccepted());
+ }
+ }
+
+ private void weave() throws IOException {
+ // ensure weaver state is set up correctly
+ for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
+ InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
+ for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
+ weaver.addClassFile(iresult.unwovenClassFiles()[i]);
+ }
+ }
+
+ weaver.prepareForWeave();
+
+ if (isBatchCompile) {
+ resultsPendingWeave.addAll(binarySources);
+ // passed into the compiler, the set of classes in injars and inpath...
+ } else if (weaver.needToReweaveWorld()) {
+ addAllKnownClassesToWeaveList();
+ }
+
+ weaver.weave(new WeaverAdapter(this,weaverMessageHandler));
+ }
+
+ private void addAllKnownClassesToWeaveList() {
+ // results pending weave already has some results from this (incremental) compile
+ // add in results from any other source
+ for (Iterator iter = resultSetForFullWeave.iterator(); iter.hasNext();) {
+ InterimCompilationResult ir = (InterimCompilationResult) iter.next();
+ if (!resultsPendingWeave.contains(ir)) { // equality based on source file name...
+ ir.result().hasBeenAccepted = false; // it may have been accepted before, start again
+ resultsPendingWeave.add(ir);
+ }
+ }
+ }
+}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ClassFileBasedByteCodeProvider.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ClassFileBasedByteCodeProvider.java
new file mode 100644
index 000000000..57a64a820
--- /dev/null
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ClassFileBasedByteCodeProvider.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import org.aspectj.weaver.bcel.UnwovenClassFile;
+import org.aspectj.weaver.bcel.UnwovenClassFileWithThirdPartyManagedBytecode;
+import org.eclipse.jdt.internal.compiler.ClassFile;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+
+/**
+ * @author colyer
+ *
+ * Adaptor for ClassFiles that lets them act as the bytecode repository
+ * for UnwovenClassFiles (asking a ClassFile for its bytes causes a
+ * copy to be made).
+ */
+public class ClassFileBasedByteCodeProvider
+ implements UnwovenClassFileWithThirdPartyManagedBytecode.IByteCodeProvider{
+
+ private ClassFile cf;
+
+ public ClassFileBasedByteCodeProvider(ClassFile cf) {
+ this.cf = cf;
+ }
+
+ public byte[] getBytes() {
+ return cf.getBytes();
+ }
+
+ public static UnwovenClassFile[] unwovenClassFilesFor(CompilationResult result,
+ IOutputClassFileNameProvider nameProvider) {
+ ClassFile[] cfs = result.getClassFiles();
+ UnwovenClassFile[] ret = new UnwovenClassFile[cfs.length];
+ for (int i = 0; i < ret.length; i++) {
+ ClassFileBasedByteCodeProvider p = new ClassFileBasedByteCodeProvider(cfs[i]);
+ String fileName = nameProvider.getOutputClassFileName(cfs[i].fileName(), result);
+ ret[i] = new UnwovenClassFileWithThirdPartyManagedBytecode(fileName,p);
+ }
+ return ret;
+ }
+
+}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/IIntermediateResultsRequestor.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/IIntermediateResultsRequestor.java
new file mode 100644
index 000000000..c97c20dc6
--- /dev/null
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/IIntermediateResultsRequestor.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+/**
+ * @author colyer
+ *
+ * Receives intermediate results from the compiler (post java-compile, but
+ * before weaving).
+ */
+public interface IIntermediateResultsRequestor {
+ void acceptResult(InterimCompilationResult intRes);
+}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/IOutputClassFileNameProvider.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/IOutputClassFileNameProvider.java
new file mode 100644
index 000000000..125d9ce1b
--- /dev/null
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/IOutputClassFileNameProvider.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+
+/**
+ * @author colyer
+ *
+ * Implementors of this interface know how to create an output destination name
+ * for a given compilation result and class file. This interface capures the variation
+ * in strategy between ajc command-line compiles and an AJDT driven compilation.
+ */
+public interface IOutputClassFileNameProvider {
+ String getOutputClassFileName(char[] eclipseClassFileName, CompilationResult result);
+}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/InterimCompilationResult.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/InterimCompilationResult.java
new file mode 100644
index 000000000..3e72d7c3b
--- /dev/null
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/InterimCompilationResult.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import java.util.List;
+
+import org.aspectj.weaver.bcel.UnwovenClassFile;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+
+/**
+ * Holds a compilation result produced by the Java compilation phase,
+ * ready for weaving in the weave phase.
+ * NOTE: This class defines equality based solely on the fileName
+ * of the compiled file (not the bytecodes produced for example)
+ */
+public class InterimCompilationResult {
+
+ private CompilationResult result;
+ private UnwovenClassFile[] unwovenClassFiles; // longer term would be nice not to have two copies of
+ // the byte codes, one in result.classFiles and another
+ // in unwovenClassFiles;
+
+ public InterimCompilationResult(CompilationResult cr,
+ IOutputClassFileNameProvider np) {
+ result = cr;
+ unwovenClassFiles = ClassFileBasedByteCodeProvider.unwovenClassFilesFor(result,np);
+ }
+
+ public InterimCompilationResult(CompilationResult cr, List ucfList) {
+ result = cr;
+ unwovenClassFiles = new UnwovenClassFile[ucfList.size()];
+ for (int i=0; i < ucfList.size(); i++) {
+ UnwovenClassFile element = (UnwovenClassFile) ucfList.get(i);
+ unwovenClassFiles[i] = element;
+ AjClassFile ajcf = new AjClassFile(element.getClassName().replace('.', '/').toCharArray(),
+ element.getBytes());
+ result.record(ajcf.fileName(),ajcf);
+ }
+ }
+
+ public CompilationResult result() { return result; }
+
+ public UnwovenClassFile[] unwovenClassFiles() { return unwovenClassFiles; }
+
+ public String fileName() {
+ return new String(result.fileName);
+ }
+
+ public boolean equals(Object other) {
+ if( other == null || !(other instanceof InterimCompilationResult)) {
+ return false;
+ }
+ InterimCompilationResult ir = (InterimCompilationResult) other;
+ return fileName().equals(ir.fileName());
+ }
+ public int hashCode() {
+ return fileName().hashCode();
+ }
+
+}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverAdapter.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverAdapter.java
new file mode 100644
index 000000000..6eead0082
--- /dev/null
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverAdapter.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.aspectj.weaver.IClassFileProvider;
+import org.aspectj.weaver.IWeaveRequestor;
+import org.aspectj.weaver.bcel.UnwovenClassFile;
+
+/**
+ * @author colyer
+ * This class provides the weaver with a source of class files to weave (via the
+ * iterator and IClassFileProvider interfaces). It receives results back from the
+ * weaver via the IWeaveRequestor interface.
+ */
+public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Iterator {
+
+ private AjCompilerAdapter compilerAdapter;
+ private Iterator resultIterator;
+ private int classFileIndex = 0;
+ private InterimCompilationResult nowProcessing;
+ private InterimCompilationResult lastReturnedResult;
+ private WeaverMessageHandler weaverMessageHandler;
+ private boolean finalPhase = false;
+
+
+ public WeaverAdapter(AjCompilerAdapter forCompiler,
+ WeaverMessageHandler weaverMessageHandler) {
+ this.compilerAdapter = forCompiler;
+ this.weaverMessageHandler = weaverMessageHandler;
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.IClassFileProvider#getClassFileIterator()
+ */
+ public Iterator getClassFileIterator() {
+ classFileIndex = 0;
+ nowProcessing = null;
+ lastReturnedResult = null;
+ resultIterator = compilerAdapter.resultsPendingWeave.iterator();
+ return this;
+ }
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.IClassFileProvider#getRequestor()
+ */
+ public IWeaveRequestor getRequestor() {
+ return this;
+ }
+
+ // Iteration
+ // ================================================================
+
+ /* (non-Javadoc)
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ if (nowProcessing == null) {
+ if (!resultIterator.hasNext()) return false;
+ nowProcessing = (InterimCompilationResult) resultIterator.next();
+ classFileIndex = 0;
+ }
+ while (nowProcessing.unwovenClassFiles().length == 0 ) {
+ if (!resultIterator.hasNext()) return false;
+ nowProcessing = (InterimCompilationResult) resultIterator.next();
+ }
+ if (classFileIndex < nowProcessing.unwovenClassFiles().length) {
+ return true;
+ } else {
+ classFileIndex = 0;
+ if (!resultIterator.hasNext()) return false;
+ nowProcessing = (InterimCompilationResult) resultIterator.next();
+ while (nowProcessing.unwovenClassFiles().length == 0 ) {
+ if (!resultIterator.hasNext()) return false;
+ nowProcessing = (InterimCompilationResult) resultIterator.next();
+ }
+ }
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see java.util.Iterator#next()
+ */
+ public Object next() {
+ if (!hasNext()) return null; // sets up indices correctly
+ if (finalPhase) {
+ if ((lastReturnedResult != null) && (lastReturnedResult != nowProcessing)) {
+ // we're done with the lastReturnedResult
+ finishedWith(lastReturnedResult);
+ }
+ }
+ lastReturnedResult = nowProcessing;
+ weaverMessageHandler.setCurrentResult(nowProcessing.result());
+ return nowProcessing.unwovenClassFiles()[classFileIndex++];
+ }
+ /* (non-Javadoc)
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+
+ // IWeaveRequestor
+ // =====================================================================================
+
+ // weave phases as indicated by bcelWeaver...
+ public void processingReweavableState() {}
+ public void addingTypeMungers() {}
+ public void weavingAspects() {}
+ public void weavingClasses() {finalPhase = true;}
+
+ public void weaveCompleted() {
+ if ((lastReturnedResult != null) && (!lastReturnedResult.result().hasBeenAccepted)) {
+ finishedWith(lastReturnedResult);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.IWeaveRequestor#acceptResult(org.aspectj.weaver.bcel.UnwovenClassFile)
+ */
+ public void acceptResult(UnwovenClassFile result) {
+ char[] key = result.getClassName().replace('.','/').toCharArray();
+ removeFromHashtable(lastReturnedResult.result().compiledTypes,key);
+ String className = result.getClassName().replace('.', '/');
+ AjClassFile ajcf = new AjClassFile(className.toCharArray(),
+ result.getBytes());
+ lastReturnedResult.result().record(ajcf.fileName(),ajcf);
+ }
+
+ // helpers...
+ // =================================================================
+
+ private void finishedWith(InterimCompilationResult result) {
+ compilerAdapter.acceptResult(result.result());
+ }
+
+ private void removeFromHashtable(Hashtable table, char[] key) {
+ // jdt uses char[] as a key in the hashtable, which is not very useful as equality is based on being
+ // the same array, not having the same content.
+ String skey = new String(key);
+ char[] victim = null;
+ for (Enumeration iter = table.keys(); iter.hasMoreElements();) {
+ char[] thisKey = (char[]) iter.nextElement();
+ if (skey.equals(new String(thisKey))) {
+ victim = thisKey;
+ break;
+ }
+ }
+ if (victim != null) {
+ table.remove(victim);
+ }
+ }
+} \ No newline at end of file
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java
new file mode 100644
index 000000000..399eddc95
--- /dev/null
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/WeaverMessageHandler.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import java.util.List;
+
+import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
+import org.aspectj.bridge.AbortException;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.IMessage.Kind;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+
+/**
+ * @author colyer
+ *
+ * To change the template for this generated type comment go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+public class WeaverMessageHandler implements IMessageHandler {
+ private IMessageHandler sink;
+ private CompilationResult currentlyWeaving;
+ private Compiler compiler;
+
+ public WeaverMessageHandler(IMessageHandler handler, Compiler compiler) {
+ this.sink = handler;
+ this.compiler = compiler;
+ }
+
+ public void setCurrentResult(CompilationResult result) {
+ currentlyWeaving = result;
+ }
+
+ public boolean handleMessage(IMessage message) throws AbortException {
+ if (! (message.isError() || message.isWarning()) ) return sink.handleMessage(message);
+ // we only care about warnings and errors here...
+ ISourceLocation sLoc = message.getSourceLocation();
+ CompilationResult problemSource = currentlyWeaving;
+ if (problemSource == null) {
+ // must be a problem found during completeTypeBindings phase of begin to compile
+ if (sLoc instanceof EclipseSourceLocation) {
+ problemSource = ((EclipseSourceLocation)sLoc).getCompilationResult();
+ }
+ if (problemSource == null) {
+ // XXX this is ok for ajc, will have to do better for AJDT in time...
+ return sink.handleMessage(message);
+ }
+ }
+ int startPos = getStartPos(sLoc,problemSource);
+ int endPos = getEndPos(sLoc,problemSource);
+ int severity = message.isError() ? ProblemSeverities.Error : ProblemSeverities.Warning;
+ char[] filename = problemSource.fileName;
+ boolean usedBinarySourceFileName = false;
+ if (problemSource.isFromBinarySource()) {
+ if (sLoc != null) {
+ filename = sLoc.getSourceFile().getPath().toCharArray();
+ usedBinarySourceFileName = true;
+ }
+ }
+ ReferenceContext referenceContext = findReferenceContextFor(problemSource);
+ IProblem problem = compiler.problemReporter.createProblem(
+ filename,
+ IProblem.Unclassified,
+ new String[0],
+ new String[] {message.getMessage()},
+ severity,
+ startPos,
+ endPos,
+ sLoc != null ? sLoc.getLine() : 1,
+ referenceContext,
+ problemSource
+ );
+ IProblem[] seeAlso = buildSeeAlsoProblems(message.getExtraSourceLocations(),
+ problemSource,
+ usedBinarySourceFileName);
+ problem.setSeeAlsoProblems(seeAlso);
+ if (message.getDetails() != null) {
+ problem.setSupplementaryMessageInfo(message.getDetails());
+ }
+ compiler.problemReporter.record(problem, problemSource, referenceContext);
+ return true;
+ }
+
+ public boolean isIgnoring(Kind kind) {
+ return sink.isIgnoring(kind);
+ }
+
+ private int getStartPos(ISourceLocation sLoc,CompilationResult result) {
+ int pos = 0;
+ if (sLoc == null) return 0;
+ int line = sLoc.getLine();
+ if (sLoc instanceof EclipseSourceLocation) {
+ pos = ((EclipseSourceLocation)sLoc).getStartPos();
+ } else {
+ if (line <= 1) return 0;
+ if (result != null) {
+ if ((result.lineSeparatorPositions != null) &&
+ (result.lineSeparatorPositions.length >= (line-1))) {
+ pos = result.lineSeparatorPositions[line-2] + 1;
+ }
+ }
+ }
+ return pos;
+ }
+
+ private int getEndPos(ISourceLocation sLoc,CompilationResult result) {
+ int pos = 0;
+ if (sLoc == null) return 0;
+ int line = sLoc.getLine();
+ if (line <= 0) line = 1;
+ if (sLoc instanceof EclipseSourceLocation) {
+ pos = ((EclipseSourceLocation)sLoc).getEndPos();
+ } else {
+ if (result != null) {
+ if ((result.lineSeparatorPositions != null) &&
+ (result.lineSeparatorPositions.length >= line)) {
+ pos = result.lineSeparatorPositions[line -1] -1;
+ }
+ }
+ }
+ return pos;
+ }
+
+ private ReferenceContext findReferenceContextFor(CompilationResult result) {
+ ReferenceContext context = null;
+ if (compiler.unitsToProcess == null) return null;
+ for (int i = 0; i < compiler.unitsToProcess.length; i++) {
+ if ((compiler.unitsToProcess[i] != null) &&
+ (compiler.unitsToProcess[i].compilationResult == result)) {
+ context = compiler.unitsToProcess[i];
+ break;
+ }
+ }
+ return context;
+ }
+
+ private IProblem[] buildSeeAlsoProblems(List sourceLocations,
+ CompilationResult problemSource,
+ boolean usedBinarySourceFileName) {
+ int probLength = sourceLocations.size();
+ if (usedBinarySourceFileName) probLength++;
+ IProblem[] ret = new IProblem[probLength];
+ for (int i = 0; i < sourceLocations.size(); i++) {
+ ISourceLocation loc = (ISourceLocation) sourceLocations.get(i);
+ ret[i] = new DefaultProblem(loc.getSourceFile().getPath().toCharArray(),
+ "see also",
+ 0,
+ new String[] {},
+ ProblemSeverities.Ignore,
+ getStartPos(loc,null),
+ getEndPos(loc,null),
+ loc.getLine());
+ }
+ if (usedBinarySourceFileName) {
+ ret[ret.length -1] = new DefaultProblem(problemSource.fileName,"see also",0,new String[] {},
+ ProblemSeverities.Ignore,0,
+ 0,0);
+ }
+ return ret;
+ }
+}
+
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceLocation.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceLocation.java
index 43f2b8ee3..377f90474 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceLocation.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceLocation.java
@@ -39,6 +39,18 @@ public class EclipseSourceLocation implements ISourceLocation {
this.startPos = startPos;
this.endPos = endPos;
}
+
+ public CompilationResult getCompilationResult() {
+ return result;
+ }
+
+ public int getStartPos() {
+ return startPos;
+ }
+
+ public int getEndPos() {
+ return endPos;
+ }
public File getSourceFile() {
if (null == file) {