diff options
author | acolyer <acolyer> | 2004-03-15 15:10:46 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2004-03-15 15:10:46 +0000 |
commit | 40680b6fe4d28b2d061fc4cf9b3efa6640c12f44 (patch) | |
tree | 9d90cff75d3b351d06b42dd9088f543de2debbd2 /org.aspectj.ajdt.core | |
parent | ec9ac363b0379ce8bb8c0783ab338d8ffaa9da02 (diff) | |
download | aspectj-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')
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>Preferences>Java>Code Generation>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) { |