diff options
28 files changed, 726 insertions, 23 deletions
diff --git a/bridge/src/org/aspectj/bridge/context/CompilationAndWeavingContext.java b/bridge/src/org/aspectj/bridge/context/CompilationAndWeavingContext.java new file mode 100644 index 000000000..208bc696b --- /dev/null +++ b/bridge/src/org/aspectj/bridge/context/CompilationAndWeavingContext.java @@ -0,0 +1,240 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.bridge.context; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Stack; + +/** + * @author colyer + * This class is responsible for tracking progress through the various phases of + * compilation and weaving. When an exception occurs (or a message is issued, if + * desired), you can ask this class for a "stack trace" that gives information about + * what the compiler was doing at the time. The trace will say something like: + * + * when matching pointcut xyz + * when matching shadow sss + * when weaving type ABC + * when weaving shadow mungers + * + * Since we can't use ThreadLocal (have to work on 1.3), we use a + * map from Thread -> ContextStack. + */ +public class CompilationAndWeavingContext { + + private static int nextTokenId = 1; + + // unique constants for the different phases that can be registered + + // "FRONT END" + public static final int BATCH_BUILD = 0; + public static final int INCREMENTAL_BUILD = 1; + public static final int PROCESSING_COMPILATION_UNIT = 2; + public static final int RESOLVING_COMPILATION_UNIT = 3; + public static final int ANALYSING_COMPILATION_UNIT = 4; + public static final int GENERATING_UNWOVEN_CODE_FOR_COMPILATION_UNIT = 5; + public static final int COMPLETING_TYPE_BINDINGS = 6; + public static final int PROCESSING_DECLARE_PARENTS = 7; + public static final int CHECK_AND_SET_IMPORTS = 8; + public static final int CONNECTING_TYPE_HIERARCHY = 9; + public static final int BUILDING_FIELDS_AND_METHODS = 10; + public static final int COLLECTING_ITDS_AND_DECLARES = 11; + public static final int PROCESSING_DECLARE_ANNOTATIONS = 12; + public static final int WEAVING_INTERTYPE_DECLARATIONS = 13; + public static final int RESOLVING_POINTCUT_DECLARATIONS = 14; + public static final int ADDING_DECLARE_WARNINGS_AND_ERRORS = 15; + public static final int VALIDATING_AT_ASPECTJ_ANNOTATIONS = 16; + public static final int ACCESS_FOR_INLINE = 17; + public static final int ADDING_AT_ASPECTJ_ANNOTATIONS = 18; + public static final int FIXING_SUPER_CALLS_IN_ITDS = 19; + public static final int FIXING_SUPER_CALLS = 20; + public static final int OPTIMIZING_THIS_JOIN_POINT_CALLS = 21; + + // "BACK END" + + public static final int WEAVING = 22; + public static final int PROCESSING_REWEAVABLE_STATE = 23; + public static final int PROCESSING_TYPE_MUNGERS = 24; + public static final int WEAVING_ASPECTS = 25; + public static final int WEAVING_CLASSES = 26; + public static final int WEAVING_TYPE = 27; + public static final int MATCHING_SHADOW = 28; + public static final int IMPLEMENTING_ON_SHADOW = 29; + public static final int MATCHING_POINTCUT = 30; + public static final int MUNGING_WITH = 31; + + + // phase names + public static final String[] PHASE_NAMES = new String[] { + "batch building", + "incrementally building", + "processing compilation unit", + "resolving types defined in compilation unit", + "analysing types defined in compilation unit", + "generating unwoven code for type defined in compilation unit", + "completing type bindings", + "processing declare parents", + "checking and setting imports", + "connecting type hierarchy", + "building fields and methods", + "collecting itds and declares", + "processing declare annotations", + "weaving intertype declarations", + "resolving pointcut declarations", + "adding declare warning and errors", + "validating @AspectJ annotations", + "creating accessors for inlining", + "adding @AspectJ annotations", + "fixing super calls in ITDs in interface context", + "fixing super calls in ITDs", + "optimizing thisJoinPoint calls", + + // BACK END + + "weaving", + "processing reweavable state", + "processing type mungers", + "weaving aspects", + "weaving classes", + "weaving type", + "matching shadow", + "implementing on shadow", + "matching pointcut", + "type munging with" + }; + + // context stacks, one per thread + private static Map contextMap = new HashMap(); + // formatters, by phase id + private static Map formatterMap = new HashMap(); + + private static ContextFormatter defaultFormatter = new DefaultFormatter(); + + + /** + * this is a static service + */ + private CompilationAndWeavingContext() { + } + + // for testing... + public static void reset() { + contextMap = new HashMap(); + formatterMap = new HashMap(); + nextTokenId = 1; + } + + public static void registerFormatter(int phaseId, ContextFormatter aFormatter) { + formatterMap.put(new Integer(phaseId),aFormatter); + } + + /** + * Returns a string description of what the compiler/weaver is currently doing + */ + public static String getCurrentContext() { + Stack contextStack = getContextStack(); + Stack explanationStack = new Stack(); + for (Iterator iter = contextStack.iterator(); iter.hasNext();) { + ContextStackEntry entry = (ContextStackEntry) iter.next(); + explanationStack.push(getFormatter(entry).formatEntry(entry.phaseId,entry.data)); + } + StringBuffer sb = new StringBuffer(); + for (Iterator iter = explanationStack.iterator(); iter.hasNext();) { + sb.append("when "); + sb.append(iter.next().toString()); + sb.append("\n"); + } + return sb.toString(); + } + + public static ContextToken enteringPhase(int phaseId, Object data) { + Stack contextStack = getContextStack(); + ContextTokenImpl nextToken = nextToken(); + contextStack.push(new ContextStackEntry(nextToken,phaseId,data)); + return nextToken; + } + + /** + * Exit a phase, all stack entries from the one with the given token + * down will be removed. + */ + public static void leavingPhase(ContextToken aToken) { + Stack contextStack = getContextStack(); + while (!contextStack.isEmpty()) { + ContextStackEntry entry = (ContextStackEntry) contextStack.pop(); + if (entry.contextToken == aToken) break; + } + } + + private static Stack getContextStack() { + if (contextMap.containsKey(Thread.currentThread())) { + return (Stack) contextMap.get(Thread.currentThread()); + } else { + Stack contextStack = new Stack(); + contextMap.put(Thread.currentThread(),contextStack); + return contextStack; + } + } + + private static ContextTokenImpl nextToken() { + return new ContextTokenImpl(nextTokenId++); + } + + private static ContextFormatter getFormatter(ContextStackEntry entry) { + Integer key = new Integer(entry.phaseId); + if (formatterMap.containsKey(key)) { + return (ContextFormatter) formatterMap.get(key); + } else { + return defaultFormatter; + } + } + + private static class ContextTokenImpl implements ContextToken { + public int tokenId; + public ContextTokenImpl(int id) { this.tokenId = id; } + } + + // dumb data structure + private static class ContextStackEntry { + public ContextTokenImpl contextToken; + public int phaseId; + public Object data; + public ContextStackEntry(ContextTokenImpl ct, int phase, Object data) { + this.contextToken = ct; + this.phaseId = phase; + this.data = data; + } + } + + private static class DefaultFormatter implements ContextFormatter { + + public String formatEntry(int phaseId, Object data) { + StringBuffer sb = new StringBuffer(); + sb.append(PHASE_NAMES[phaseId]); + sb.append(" "); + if (data instanceof char[]) { + sb.append(new String((char[])data)); + } else { + try { + sb.append(data.toString()); + } catch (RuntimeException ex) { + // don't lose vital info because of bad toString + sb.append("** broken toString in data object **"); + } + } + return sb.toString(); + } + + } +} diff --git a/bridge/src/org/aspectj/bridge/context/ContextFormatter.java b/bridge/src/org/aspectj/bridge/context/ContextFormatter.java new file mode 100644 index 000000000..9f1b591d7 --- /dev/null +++ b/bridge/src/org/aspectj/bridge/context/ContextFormatter.java @@ -0,0 +1,21 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.bridge.context; + +/** + * @author colyer + * Implementors of this interface know how to turn the "Object" data and phase id + * associated with a context stack entry into a meaningful string. + */ +public interface ContextFormatter { + String formatEntry(int phaseId, Object data); +} diff --git a/bridge/src/org/aspectj/bridge/context/ContextToken.java b/bridge/src/org/aspectj/bridge/context/ContextToken.java new file mode 100644 index 000000000..2415fa72e --- /dev/null +++ b/bridge/src/org/aspectj/bridge/context/ContextToken.java @@ -0,0 +1,20 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.bridge.context; + +/** + * When an entry is added to the CompilationAndWeavingContext stack, + * a ContextToken is returned. + * When leaving a compilation or weaving phase, this token must be supplied. + * The token details are opaque to clients + */ +public interface ContextToken {} diff --git a/bridge/src/org/aspectj/bridge/context/PinpointingMessageHandler.java b/bridge/src/org/aspectj/bridge/context/PinpointingMessageHandler.java new file mode 100644 index 000000000..8f7852eb0 --- /dev/null +++ b/bridge/src/org/aspectj/bridge/context/PinpointingMessageHandler.java @@ -0,0 +1,106 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.bridge.context; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.List; + +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; + +/** + * @author colyer + * Facade for an IMessageHandler + * Extends message with details of exactly what the compiler / weaver was doing at the + * time. Use the -Xdev:Pinpoint option to turn this facility on. + */ +public class PinpointingMessageHandler implements IMessageHandler { + + private IMessageHandler delegate; + + public PinpointingMessageHandler(IMessageHandler delegate) { + this.delegate = delegate; + } + + /* (non-Javadoc) + * @see org.aspectj.bridge.IMessageHandler#handleMessage(org.aspectj.bridge.IMessage) + */ + public boolean handleMessage(IMessage message) throws AbortException { + if (!isIgnoring(message.getKind())) { + MessageIssued ex = new MessageIssued(); + ex.fillInStackTrace(); + StringWriter sw = new StringWriter(); + ex.printStackTrace(new PrintWriter(sw)); + StringBuffer sb = new StringBuffer(); + sb.append(CompilationAndWeavingContext.getCurrentContext()); + sb.append(sw.toString()); + IMessage pinpointedMessage = new PinpointedMessage(message,sb.toString()); + return delegate.handleMessage(pinpointedMessage); + } else { + return delegate.handleMessage(message); + } + } + + /* (non-Javadoc) + * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) + */ + public boolean isIgnoring(Kind kind) { + return delegate.isIgnoring(kind); + } + + /* (non-Javadoc) + * @see org.aspectj.bridge.IMessageHandler#dontIgnore(org.aspectj.bridge.IMessage.Kind) + */ + public void dontIgnore(Kind kind) { + delegate.dontIgnore(kind); + } + + private static class PinpointedMessage implements IMessage { + + private IMessage delegate; + private String message; + + public PinpointedMessage(IMessage delegate, String pinpoint) { + this.delegate = delegate; + this.message = delegate.getMessage() + "\n" + pinpoint; + } + + public String getMessage() { return this.message; } + public Kind getKind() { return delegate.getKind();} + public boolean isError() { return delegate.isError(); } + public boolean isWarning() { return delegate.isWarning();} + public boolean isDebug() { return delegate.isDebug();} + public boolean isInfo() { return delegate.isInfo();} + public boolean isAbort() { return delegate.isAbort();} + public boolean isTaskTag() { return delegate.isTaskTag();} + public boolean isFailed() { return delegate.isFailed();} + public boolean getDeclared() { return delegate.getDeclared(); } + public int getID() { return delegate.getID();} + public int getSourceStart() { return delegate.getSourceStart();} + public int getSourceEnd() { return delegate.getSourceEnd();} + public Throwable getThrown() { return delegate.getThrown();} + public ISourceLocation getSourceLocation() { return delegate.getSourceLocation();} + public String getDetails() { return delegate.getDetails();} + public List getExtraSourceLocations() { return delegate.getExtraSourceLocations();} + } + + private static class MessageIssued extends RuntimeException { + public String getMessage() { + return "message issued..."; + } + } + +} diff --git a/bridge/testsrc/BridgeModuleTests.java b/bridge/testsrc/BridgeModuleTests.java index e0049f863..23e28ea60 100644 --- a/bridge/testsrc/BridgeModuleTests.java +++ b/bridge/testsrc/BridgeModuleTests.java @@ -14,6 +14,8 @@ // default package +import org.aspectj.bridge.context.CompilationAndWeavingContextTest; + import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; @@ -23,6 +25,7 @@ public class BridgeModuleTests extends TestCase { public static Test suite() { TestSuite suite = new TestSuite(BridgeModuleTests.class.getName()); suite.addTest(org.aspectj.bridge.BridgeTests.suite()); + suite.addTestSuite(CompilationAndWeavingContextTest.class); return suite; } diff --git a/bridge/testsrc/org/aspectj/bridge/context/CompilationAndWeavingContextTest.java b/bridge/testsrc/org/aspectj/bridge/context/CompilationAndWeavingContextTest.java new file mode 100644 index 000000000..6e8c73e22 --- /dev/null +++ b/bridge/testsrc/org/aspectj/bridge/context/CompilationAndWeavingContextTest.java @@ -0,0 +1,67 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.bridge.context; + +import junit.framework.TestCase; + +/** + * @author colyer + * + */ +public class CompilationAndWeavingContextTest extends TestCase { + + public void testEnteringPhase() { + CompilationAndWeavingContext.enteringPhase(1,"XYZ"); + assertEquals("when fiddling XYZ\n",CompilationAndWeavingContext.getCurrentContext()); + } + + public void testDoubleEntry() { + CompilationAndWeavingContext.enteringPhase(1,"XYZ"); + CompilationAndWeavingContext.enteringPhase(2, "ABC"); + assertEquals("when fiddling XYZ\nwhen mucking about with ABC\n",CompilationAndWeavingContext.getCurrentContext()); + } + + public void testEntryEntryExit() { + CompilationAndWeavingContext.enteringPhase(1,"XYZ"); + ContextToken ct = CompilationAndWeavingContext.enteringPhase(2, "ABC"); + CompilationAndWeavingContext.leavingPhase(ct); + assertEquals("when fiddling XYZ\n",CompilationAndWeavingContext.getCurrentContext()); + } + + public void testEntryExitTop() { + ContextToken ct = CompilationAndWeavingContext.enteringPhase(1,"XYZ"); + CompilationAndWeavingContext.enteringPhase(2, "ABC"); + CompilationAndWeavingContext.leavingPhase(ct); + assertEquals("",CompilationAndWeavingContext.getCurrentContext()); + } + + + protected void setUp() throws Exception { + CompilationAndWeavingContext.reset(); + CompilationAndWeavingContext.registerFormatter(1, new MyContextFormatter("fiddling ")); + CompilationAndWeavingContext.registerFormatter(2, new MyContextFormatter("mucking about with ")); + } + + private static class MyContextFormatter implements ContextFormatter { + + private String prefix; + + public MyContextFormatter(String prefix) { + this.prefix = prefix; + } + + public String formatEntry(int phaseId, Object data) { + return prefix + data.toString(); + } + + } +} diff --git a/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java b/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java index bb41f37cd..208c2b508 100644 --- a/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java +++ b/loadtime/src/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java @@ -182,6 +182,7 @@ public class ClassLoaderWeavingAdaptor extends WeavingAdaptor { world.setMessageHandler(weaverOption.messageHandler); world.setXlazyTjp(weaverOption.lazyTjp); world.setXHasMemberSupportEnabled(weaverOption.hasMember); + world.setPinpointMode(weaverOption.pinpoint); weaver.setReweavableMode(weaverOption.reWeavable, false); world.setXnoInline(weaverOption.noInline); world.setBehaveInJava5Way(weaverOption.java5);//TODO should be autodetected ? diff --git a/loadtime/src/org/aspectj/weaver/loadtime/Options.java b/loadtime/src/org/aspectj/weaver/loadtime/Options.java index adc16835f..9c15c5711 100644 --- a/loadtime/src/org/aspectj/weaver/loadtime/Options.java +++ b/loadtime/src/org/aspectj/weaver/loadtime/Options.java @@ -38,6 +38,7 @@ public class Options { private final static String OPTION_reweavable = "-Xreweavable"; private final static String OPTION_noinline = "-Xnoinline"; private final static String OPTION_hasMember = "-XhasMember"; + private final static String OPTION_pinpoint = "-Xdev:pinpoint"; private final static String OPTION_showWeaveInfo = "-showWeaveInfo"; private final static String OPTIONVALUED_messageHandler = "-XmessageHandlerClass:"; private static final String OPTIONVALUED_Xlintfile = "-Xlintfile:"; @@ -96,8 +97,10 @@ public class Options { weaverOption.showWeaveInfo = true; } else if (arg.equalsIgnoreCase(OPTION_hasMember)) { weaverOption.hasMember = true; - } else if (arg.equalsIgnoreCase(OPTION_verbose)) { + } else if (arg.equalsIgnoreCase(OPTION_verbose)) { weaverOption.verbose = true; + } else if (arg.equalsIgnoreCase(OPTION_pinpoint)) { + weaverOption.pinpoint = true; } else if (arg.startsWith(OPTIONVALUED_messageHandler)) { ;// handled in first round } else if (arg.startsWith(OPTIONVALUED_Xlintfile)) { @@ -144,6 +147,7 @@ public class Options { boolean reWeavable; boolean noInline; boolean showWeaveInfo; + boolean pinpoint; IMessageHandler messageHandler; String lint; String lintFile; diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java index fd542eae3..929619c00 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java @@ -516,7 +516,9 @@ public class BuildArgParser extends Main { buildConfig.setGenerateJavadocsInModelMode(true); } else if (arg.equals("-Xdev:NoAtAspectJProcessing")) { buildConfig.setNoAtAspectJAnnotationProcessing(true); - }else if (arg.equals("-noweave") || arg.equals( "-XnoWeave")) { + } else if (arg.equals("-Xdev:Pinpoint")) { + buildConfig.setXdevPinpointMode(true); + } else if (arg.equals("-noweave") || arg.equals( "-XnoWeave")) { buildConfig.setNoWeave(true); } else if (arg.equals("-XserializableAspects")) { buildConfig.setXserializableAspects(true); 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 index 9369f4bb7..ddc231bec 100644 --- 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 @@ -25,6 +25,8 @@ import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.IMessageHandler; import org.aspectj.bridge.IProgressListener; +import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.bridge.context.ContextToken; import org.aspectj.org.eclipse.jdt.core.compiler.IProblem; import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult; import org.aspectj.org.eclipse.jdt.internal.compiler.Compiler; @@ -60,6 +62,11 @@ public class AjCompilerAdapter implements ICompilerAdapter { private Map /* fileName |-> List<UnwovenClassFile> */ binarySourceSetForFullWeave = new HashMap(); private Collection /*InterimCompilationResult*/ resultSetForFullWeave = Collections.EMPTY_LIST; + private ContextToken processingToken = null; + private ContextToken resolvingToken = null; + private ContextToken analysingToken = null; + private ContextToken generatingToken = null; + List /*InterimResult*/ resultsPendingWeave = new ArrayList(); /** @@ -122,22 +129,26 @@ public class AjCompilerAdapter implements ICompilerAdapter { public void beforeProcessing(CompilationUnitDeclaration unit) { eWorld.showMessage(IMessage.INFO, "compiling " + new String(unit.getFileName()), null, null); + processingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_COMPILATION_UNIT,unit.getFileName()); if (inJava5Mode && !noAtAspectJAnnotationProcessing) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ADDING_AT_ASPECTJ_ANNOTATIONS, unit.getFileName()); AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit); unit.traverse(atAspectJVisitor, unit.scope); + CompilationAndWeavingContext.leavingPhase(tok); } } public void beforeResolving(CompilationUnitDeclaration unit) { - // no-op + resolvingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.RESOLVING_COMPILATION_UNIT, unit.getFileName()); } public void afterResolving(CompilationUnitDeclaration unit) { - // no-op - + if (resolvingToken != null) + CompilationAndWeavingContext.leavingPhase(resolvingToken); } public void beforeAnalysing(CompilationUnitDeclaration unit) { + analysingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ANALYSING_COMPILATION_UNIT, unit.getFileName()); if (inJava5Mode && !noAtAspectJAnnotationProcessing) { ValidateAtAspectJAnnotationsVisitor atAspectJVisitor = new ValidateAtAspectJAnnotationsVisitor(unit); unit.traverse(atAspectJVisitor, unit.scope); @@ -145,15 +156,17 @@ public class AjCompilerAdapter implements ICompilerAdapter { } public void afterAnalysing(CompilationUnitDeclaration unit) { - // no-op + if (analysingToken != null) + CompilationAndWeavingContext.leavingPhase(analysingToken); } public void beforeGenerating(CompilationUnitDeclaration unit) { - // no-op + generatingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.GENERATING_UNWOVEN_CODE_FOR_COMPILATION_UNIT, unit.getFileName()); } public void afterGenerating(CompilationUnitDeclaration unit) { - // no-op + if (generatingToken != null) + CompilationAndWeavingContext.leavingPhase(generatingToken); } public void afterCompiling(CompilationUnitDeclaration[] units) { diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java index 98cb80d24..225ac7e0d 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AdviceDeclaration.java @@ -20,6 +20,8 @@ import java.util.List; import org.aspectj.ajdt.internal.compiler.lookup.AjTypeConstants; import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory; import org.aspectj.ajdt.internal.compiler.lookup.PrivilegedHandler; +import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.bridge.context.ContextToken; import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation; import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile; import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult; @@ -166,7 +168,9 @@ public class AdviceDeclaration extends AjMethodDeclaration { this.traverse(new MakeDeclsPublicVisitor(), (ClassScope)null); AccessForInlineVisitor v = new AccessForInlineVisitor((AspectDeclaration)upperScope.referenceContext, handler); + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ACCESS_FOR_INLINE, selector); this.traverse(v, (ClassScope) null); + CompilationAndWeavingContext.leavingPhase(tok); // ??? if we found a construct that we can't inline, set // proceedInInners so that we won't try to inline this body diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java index d83161553..81c47a4d9 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java @@ -21,6 +21,8 @@ import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory; import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger; import org.aspectj.ajdt.internal.compiler.lookup.InterTypeScope; import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext; +import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.bridge.context.ContextToken; import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation; import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile; import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult; @@ -138,10 +140,12 @@ public abstract class InterTypeDeclaration extends AjMethodDeclaration { private void fixSuperCallsForInterfaceContext(ClassScope scope) { if (onTypeBinding.isInterface()) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.FIXING_SUPER_CALLS, selector); InterSuperFixerVisitor v = new InterSuperFixerVisitor(this, EclipseFactory.fromScopeLookupEnvironment(scope), scope); this.traverse(v, scope); + CompilationAndWeavingContext.leavingPhase(tok); } } @@ -151,9 +155,11 @@ public abstract class InterTypeDeclaration extends AjMethodDeclaration { public abstract EclipseTypeMunger build(ClassScope classScope); public void fixSuperCallsInBody() { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.FIXING_SUPER_CALLS_IN_ITDS, selector); SuperFixerVisitor v = new SuperFixerVisitor(this, onTypeBinding); this.traverse(v, (ClassScope)null); munger.setSuperMethodsCalled(v.superMethodsCalled); + CompilationAndWeavingContext.leavingPhase(tok); } protected void resolveOnType(ClassScope classScope) { diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ThisJoinPointVisitor.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ThisJoinPointVisitor.java index 5f51a4564..17bef539c 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ThisJoinPointVisitor.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ThisJoinPointVisitor.java @@ -14,6 +14,8 @@ package org.aspectj.ajdt.internal.compiler.ast; import org.aspectj.weaver.Advice; +import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.bridge.context.ContextToken; import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression; @@ -135,6 +137,7 @@ public class ThisJoinPointVisitor extends ASTVisitor { boolean inBlockThatCantRun = false; public boolean visit(MessageSend call, BlockScope scope) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.OPTIMIZING_THIS_JOIN_POINT_CALLS, call.selector); Expression receiver = call.receiver; if (isRef(receiver, thisJoinPointDec)) { if (canTreatAsStatic(new String(call.selector))) { @@ -148,12 +151,15 @@ public class ThisJoinPointVisitor extends ASTVisitor { for (int i = 0; i < argumentsLength; i++) call.arguments[i].traverse(this, scope); } + CompilationAndWeavingContext.leavingPhase(tok); return false; } } } - return super.visit(call, scope); + boolean ret = super.visit(call, scope); + CompilationAndWeavingContext.leavingPhase(tok); + return ret; } private void replaceEffectivelyStaticRef(MessageSend call) { diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ValidateAtAspectJAnnotationsVisitor.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ValidateAtAspectJAnnotationsVisitor.java index 2d1785797..4f0106fb6 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ValidateAtAspectJAnnotationsVisitor.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/ValidateAtAspectJAnnotationsVisitor.java @@ -17,6 +17,8 @@ import java.util.Stack; import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory; import org.aspectj.ajdt.internal.compiler.lookup.EclipseScope; import org.aspectj.ajdt.internal.core.builder.EclipseSourceContext; +import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.bridge.context.ContextToken; import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation; import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation; @@ -109,6 +111,7 @@ public class ValidateAtAspectJAnnotationsVisitor extends ASTVisitor { } private void checkTypeDeclaration(TypeDeclaration typeDecl) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.VALIDATING_AT_ASPECTJ_ANNOTATIONS, typeDecl.name); if (!(typeDecl instanceof AspectDeclaration)) { if (ajAnnotations.hasAspectAnnotation) { validateAspectDeclaration(typeDecl); @@ -138,9 +141,11 @@ public class ValidateAtAspectJAnnotationsVisitor extends ASTVisitor { ); } } + CompilationAndWeavingContext.leavingPhase(tok); } public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.VALIDATING_AT_ASPECTJ_ANNOTATIONS, methodDeclaration.selector); ajAnnotations = new AspectJAnnotations(methodDeclaration.annotations); if (!methodDeclaration.getClass().equals(AjMethodDeclaration.class)) { // simply test for innapropriate use of annotations on code-style members @@ -171,6 +176,7 @@ public class ValidateAtAspectJAnnotationsVisitor extends ASTVisitor { "@AspectJ annotations cannot be declared on this aspect member"); } } + CompilationAndWeavingContext.leavingPhase(tok); return false; } @@ -179,6 +185,7 @@ public class ValidateAtAspectJAnnotationsVisitor extends ASTVisitor { } else if (ajAnnotations.hasPointcutAnnotation) { convertToPointcutDeclaration(methodDeclaration,scope); } + CompilationAndWeavingContext.leavingPhase(tok); return false; } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java index 4b4ada030..5b64bd471 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/AjLookupEnvironment.java @@ -27,6 +27,8 @@ import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration; import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.WeaveMessage; +import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.bridge.context.ContextToken; import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation; @@ -91,22 +93,29 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC //??? duplicates some of super's code public void completeTypeBindings() { + ContextToken completeTypeBindingsToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.COMPLETING_TYPE_BINDINGS, ""); // builtInterTypesAndPerClauses = false; //pendingTypesToWeave = new ArrayList(); stepCompleted = BUILD_TYPE_HIERARCHY; for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.CHECK_AND_SET_IMPORTS, units[i].compilationResult.fileName); units[i].scope.checkAndSetImports(); + CompilationAndWeavingContext.leavingPhase(tok); } stepCompleted = CHECK_AND_SET_IMPORTS; for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.CONNECTING_TYPE_HIERARCHY, units[i].compilationResult.fileName); units[i].scope.connectTypeHierarchy(); + CompilationAndWeavingContext.leavingPhase(tok); } stepCompleted = CONNECT_TYPE_HIERARCHY; for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.BUILDING_FIELDS_AND_METHODS, units[i].compilationResult.fileName); units[i].scope.buildFieldsAndMethods(); + CompilationAndWeavingContext.leavingPhase(tok); } // would like to gather up all TypeDeclarations at this point and put them in the factory @@ -190,14 +199,18 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { SourceTypeBinding[] b = units[i].scope.topLevelTypes; for (int j = 0; j < b.length; j++) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.RESOLVING_POINTCUT_DECLARATIONS, b[j].sourceName); resolvePointcutDeclarations(b[j].scope); + CompilationAndWeavingContext.leavingPhase(tok); } } for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) { SourceTypeBinding[] b = units[i].scope.topLevelTypes; for (int j = 0; j < b.length; j++) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ADDING_DECLARE_WARNINGS_AND_ERRORS, b[j].sourceName); addAdviceLikeDeclares(b[j].scope); + CompilationAndWeavingContext.leavingPhase(tok); } } @@ -207,6 +220,8 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC stepCompleted = BUILD_FIELDS_AND_METHODS; lastCompletedUnitIndex = lastUnitIndex; + + CompilationAndWeavingContext.leavingPhase(completeTypeBindingsToken); } @@ -218,6 +233,7 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC */ private void collectAllITDsAndDeclares(SourceTypeBinding sourceType, Collection yetToProcess) { // Look at the supertype first + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.COLLECTING_ITDS_AND_DECLARES, sourceType.sourceName); ReferenceBinding superType = sourceType.superclass(); if (yetToProcess.contains(superType) && superType instanceof SourceTypeBinding) { collectAllITDsAndDeclares((SourceTypeBinding)superType, yetToProcess); @@ -225,6 +241,7 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC buildInterTypeAndPerClause(sourceType.scope); addCrosscuttingStructures(sourceType.scope); yetToProcess.remove(sourceType); + CompilationAndWeavingContext.leavingPhase(tok); } /** @@ -259,7 +276,9 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC private void doPendingWeaves() { for (Iterator i = pendingTypesToWeave.iterator(); i.hasNext(); ) { SourceTypeBinding t = (SourceTypeBinding)i.next(); + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_INTERTYPE_DECLARATIONS, t.sourceName); weaveInterTypeDeclarations(t); + CompilationAndWeavingContext.leavingPhase(tok); } pendingTypesToWeave.clear(); } @@ -397,6 +416,7 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC private void weaveInterTypeDeclarations(SourceTypeBinding sourceType, Collection typeMungers, Collection declareParents, Collection declareAnnotationOnTypes, boolean skipInners) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_INTERTYPE_DECLARATIONS, sourceType.sourceName); ResolvedType onType = factory.fromEclipse(sourceType); // AMC we shouldn't need this when generic sigs are fixed?? if (onType.isRawType()) onType = onType.getGenericType(); @@ -423,7 +443,7 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC } } - + CompilationAndWeavingContext.leavingPhase(tok); return; } @@ -556,9 +576,11 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC weaveInterTypeDeclarations((SourceTypeBinding) memberTypes[i], typeMungers, declareParents,declareAnnotationOnTypes, false); } } + CompilationAndWeavingContext.leavingPhase(tok); } private boolean doDeclareParents(DeclareParents declareParents, SourceTypeBinding sourceType) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_DECLARE_PARENTS, sourceType.sourceName); List newParents = declareParents.findMatchingNewParents(factory.fromEclipse(sourceType),false); if (!newParents.isEmpty()) { for (Iterator i = newParents.iterator(); i.hasNext(); ) { @@ -576,8 +598,10 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC addParent(sourceType, parent); } } + CompilationAndWeavingContext.leavingPhase(tok); return true; } + CompilationAndWeavingContext.leavingPhase(tok); return false; } @@ -608,7 +632,8 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC if (!decA.matches(rtx)) return false; if (!rtx.isExposedToWeaver()) return false; - + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_DECLARE_ANNOTATIONS, sourceType.sourceName); + // Get the annotation specified in the declare TypeBinding tb = factory.makeTypeBinding(decA.getAspect()); @@ -635,12 +660,16 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC // FIXME asc we have a lint for attempting to add an annotation twice to a method, // we could put it out here *if* we can resolve the problem of errors coming out // multiple times if we have cause to loop through here - if (a.equals(b)) return false; + if (a.equals(b)) { + CompilationAndWeavingContext.leavingPhase(tok); + return false; + } } if (((abits & TagBits.AnnotationTargetMASK)!=0)) { if ( (abits & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType))==0) { // this means it specifies something other than annotation or normal type - error will have been already reported, just resolution process above + CompilationAndWeavingContext.leavingPhase(tok); return false; } if ( (sourceType.isAnnotationType() && (abits & TagBits.AnnotationForAnnotationType)==0) || @@ -659,6 +688,7 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC // } // } } + CompilationAndWeavingContext.leavingPhase(tok); return false; } } @@ -675,6 +705,7 @@ public class AjLookupEnvironment extends LookupEnvironment implements AnonymousC System.arraycopy(abefore,0,newset,toAdd.length,abefore.length); } sourceType.scope.referenceContext.annotations = newset; + CompilationAndWeavingContext.leavingPhase(tok); return true; } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/problem/AjProblemReporter.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/problem/AjProblemReporter.java index 203089371..4cacecc36 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/problem/AjProblemReporter.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/problem/AjProblemReporter.java @@ -13,6 +13,8 @@ package org.aspectj.ajdt.internal.compiler.problem; +import java.io.PrintWriter; +import java.io.StringWriter; import java.lang.reflect.Modifier; import java.util.Iterator; import java.util.List; @@ -22,6 +24,7 @@ import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration; import org.aspectj.ajdt.internal.compiler.ast.Proceed; import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory; import org.aspectj.ajdt.internal.compiler.lookup.InterTypeMethodBinding; +import org.aspectj.bridge.context.CompilationAndWeavingContext; import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation; import org.aspectj.org.eclipse.jdt.core.compiler.IProblem; import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult; @@ -430,4 +433,64 @@ public class AjProblemReporter extends ProblemReporter { if (currentMethod == inheritedMethod) return; super.finalMethodCannotBeOverridden(currentMethod, inheritedMethod); } + + /** + * All problems end up routed through here at some point... + */ + public IProblem createProblem(char[] fileName, int problemId, String[] problemArguments, String[] messageArguments, int severity, int problemStartPosition, int problemEndPosition, int lineNumber) { + IProblem problem = super.createProblem(fileName, problemId, problemArguments, + messageArguments, severity, problemStartPosition, problemEndPosition, + lineNumber); + if (factory.getWorld().isInPinpointMode()) { + MessageIssued ex = new MessageIssued(); + ex.fillInStackTrace(); + StringWriter sw = new StringWriter(); + ex.printStackTrace(new PrintWriter(sw)); + StringBuffer sb = new StringBuffer(); + sb.append(CompilationAndWeavingContext.getCurrentContext()); + sb.append(sw.toString()); + problem = new PinpointedProblem(problem,sb.toString()); + } + return problem; + } + + private static class MessageIssued extends RuntimeException { + public String getMessage() { + return "message issued..."; + } + } + + private static class PinpointedProblem implements IProblem { + + private IProblem delegate; + private String message; + + public PinpointedProblem(IProblem aProblem, String pinpoint) { + this.delegate = aProblem; + // if this was a problem that came via the weaver, it will already have + // pinpoint info, don't do it twice... + if (delegate.getMessage().indexOf("message issued...") == -1) { + this.message = delegate.getMessage() + "\n" + pinpoint; + } else { + this.message = delegate.getMessage(); + } + } + + public String[] getArguments() {return delegate.getArguments();} + public int getID() {return delegate.getID();} + public String getMessage() { return message; } + public char[] getOriginatingFileName() {return delegate.getOriginatingFileName();} + public int getSourceEnd() { return delegate.getSourceEnd();} + public int getSourceLineNumber() { return delegate.getSourceLineNumber();} + public int getSourceStart() { return delegate.getSourceStart();} + public boolean isError() { return delegate.isError();} + public boolean isWarning() { return delegate.isWarning();} + public void setSourceEnd(int sourceEnd) { delegate.setSourceEnd(sourceEnd); } + public void setSourceLineNumber(int lineNumber) { delegate.setSourceLineNumber(lineNumber);} + public void setSourceStart(int sourceStart) { delegate.setSourceStart(sourceStart);} + public void setSeeAlsoProblems(IProblem[] problems) { delegate.setSeeAlsoProblems(problems);} + public IProblem[] seeAlso() { return delegate.seeAlso();} + public void setSupplementaryMessageInfo(String msg) { delegate.setSupplementaryMessageInfo(msg);} + public String getSupplementaryMessageInfo() { return delegate.getSupplementaryMessageInfo();} + } } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java index 26cc3fe25..6a0b0e228 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java @@ -485,6 +485,14 @@ public class AjBuildConfig { return options.xHasMember; } + public void setXdevPinpointMode(boolean enabled) { + options.xdevPinpoint = enabled; + } + + public boolean isXdevPinpoint() { + return options.xdevPinpoint; + } + public boolean isXreweavable() { return options.xReweavable; } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java index 0a3887882..55ddf133a 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java @@ -56,6 +56,9 @@ import org.aspectj.bridge.Message; import org.aspectj.bridge.MessageUtil; import org.aspectj.bridge.SourceLocation; import org.aspectj.bridge.Version; +import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.bridge.context.ContextFormatter; +import org.aspectj.bridge.context.ContextToken; import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation; import org.aspectj.org.eclipse.jdt.core.compiler.IProblem; import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile; @@ -74,7 +77,6 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import org.aspectj.org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; import org.aspectj.util.FileUtil; import org.aspectj.weaver.Dump; -import org.aspectj.weaver.MissingResolvedTypeWithKnownSignature; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.World; import org.aspectj.weaver.bcel.BcelWeaver; @@ -101,7 +103,14 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc * the latter will get used. */ private static AsmHierarchyBuilder asmHierarchyBuilder = new AsmHierarchyBuilder(); - + + static { + CompilationAndWeavingContext.registerFormatter( + CompilationAndWeavingContext.BATCH_BUILD, new AjBuildContexFormatter()); + CompilationAndWeavingContext.registerFormatter( + CompilationAndWeavingContext.INCREMENTAL_BUILD, new AjBuildContexFormatter()); + } + private IProgressListener progressListener = null; private int compiledCount; @@ -158,6 +167,8 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc boolean ret = true; batchCompile = batch; + int phase = batch ? CompilationAndWeavingContext.BATCH_BUILD : CompilationAndWeavingContext.INCREMENTAL_BUILD; + ContextToken ct = CompilationAndWeavingContext.enteringPhase(phase ,buildConfig); try { if (batch) { this.state = new AjState(this); @@ -269,6 +280,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc AsmManager.getDefault().fireModelUpdated(); } } finally { + CompilationAndWeavingContext.leavingPhase(ct); if (zos != null) { closeOutputStream(buildConfig.getOutputJar()); } @@ -538,6 +550,7 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc bcelWorld.setXnoInline(buildConfig.isXnoInline()); bcelWorld.setXlazyTjp(buildConfig.isXlazyTjp()); bcelWorld.setXHasMemberSupportEnabled(buildConfig.isXHasMemberEnabled()); + bcelWorld.setPinpointMode(buildConfig.isXdevPinpoint()); BcelWeaver bcelWeaver = new BcelWeaver(bcelWorld); state.setWorld(bcelWorld); state.setWeaver(bcelWeaver); @@ -1056,5 +1069,26 @@ public class AjBuildManager implements IOutputClassFileNameProvider,IBinarySourc public void setState(AjState buildState) { state = buildState; } + + private static class AjBuildContexFormatter implements ContextFormatter { + + public String formatEntry(int phaseId, Object data) { + StringBuffer sb = new StringBuffer(); + if (phaseId == CompilationAndWeavingContext.BATCH_BUILD) { + sb.append("batch building "); + } else { + sb.append("incrementally building "); + } + AjBuildConfig config = (AjBuildConfig) data; + List classpath = config.getClasspath(); + sb.append("with classpath: "); + for (Iterator iter = classpath.iterator(); iter.hasNext();) { + sb.append(iter.next().toString()); + sb.append(File.pathSeparator); + } + return sb.toString(); + } + + } } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java index 8c13e00b1..ce206580d 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjCompilerOptions.java @@ -43,6 +43,7 @@ public class AjCompilerOptions extends CompilerOptions { public static final String OPTION_XReweavable = "org.aspectj.ajdt.core.compiler.weaver.XReweavable"; public static final String OPTION_XReweavableCompress = "org.aspectj.ajdt.core.compiler.weaver.XReweavableCompress"; public static final String OPTION_XHasMember = "org.aspectj.ajdt.core.compiler.weaver.XHasMember"; + public static final String OPTION_XdevPinpoint = "org.aspectj.ajdt.core.compiler.weaver.XdevPinpoint"; // these next four not exposed by IDEs public static final String OPTION_XDevNoAtAspectJProcessing = "org.aspectj.ajdt.core.compiler.ast.NoAtAspectJProcessing"; @@ -68,6 +69,7 @@ public class AjCompilerOptions extends CompilerOptions { public boolean xReweavable = false; public boolean xReweavableCompress = false; public boolean xHasMember = false; + public boolean xdevPinpoint = false; public boolean showWeavingInformation = false; // If true - autoboxing behaves differently ... @@ -122,6 +124,7 @@ public class AjCompilerOptions extends CompilerOptions { map.put(OPTION_XReweavable,this.xReweavable ? ENABLED : DISABLED); map.put(OPTION_XReweavableCompress,this.xReweavableCompress ? ENABLED : DISABLED); map.put(OPTION_XHasMember, this.xHasMember ? ENABLED : DISABLED); + map.put(OPTION_XdevPinpoint, this.xdevPinpoint ? ENABLED : DISABLED); map.put(OPTION_GenerateModel,this.generateModel ? ENABLED : DISABLED); map.put(OPTION_GenerateJavaDocsInModel,this.generateJavaDocsInModel ? ENABLED : DISABLED); @@ -196,7 +199,15 @@ public class AjCompilerOptions extends CompilerOptions { this.xHasMember = false; } } - + + if ((optionValue = optionsMap.get(OPTION_XdevPinpoint)) != null) { + if (ENABLED.equals(optionValue)) { + this.xdevPinpoint = true; + } else if (DISABLED.equals(optionValue)) { + this.xdevPinpoint = false; + } + } + if ((optionValue = optionsMap.get(OPTION_GenerateModel)) != null) { if (ENABLED.equals(optionValue)) { this.generateModel = true; diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java index 8198012b0..c8b7b2e2f 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AspectJBuilder.java @@ -159,6 +159,7 @@ public class AspectJBuilder extends JavaBuilder implements ICompilerAdapterFacto myBcelWorld.setXnoInline(options.xNoInline); myBcelWorld.setXlazyTjp(options.xLazyThisJoinPoint); myBcelWorld.setXHasMemberSupportEnabled(options.xHasMember); + myBcelWorld.setPinpointMode(options.xdevPinpoint); setLintProperties(myBcelWorld,options); myWeaver = new BcelWeaver(myBcelWorld); myWeaver.setReweavableMode(options.xReweavable,options.xReweavableCompress); diff --git a/org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java b/org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java index 9bda53768..e250c6b29 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/tools/ajc/Main.java @@ -33,6 +33,7 @@ import org.aspectj.bridge.MessageHandler; import org.aspectj.bridge.MessageUtil; import org.aspectj.bridge.ReflectionFactory; import org.aspectj.bridge.Version; +import org.aspectj.bridge.context.CompilationAndWeavingContext; import org.aspectj.util.FileUtil; import org.aspectj.util.LangUtil; @@ -143,6 +144,7 @@ public class Main { String m = thrown.getMessage(); return THROWN_PREFIX + (null != m ? m + "\n": "") + + CompilationAndWeavingContext.getCurrentContext() + LangUtil.renderException(thrown, true); } diff --git a/weaver/src/org/aspectj/weaver/BCException.java b/weaver/src/org/aspectj/weaver/BCException.java index d282e9d65..161d0ed90 100644 --- a/weaver/src/org/aspectj/weaver/BCException.java +++ b/weaver/src/org/aspectj/weaver/BCException.java @@ -16,6 +16,8 @@ package org.aspectj.weaver; import java.io.PrintStream; import java.io.PrintWriter; +import org.aspectj.bridge.context.CompilationAndWeavingContext; + /** * Exception to use inside the bcweaver. */ @@ -26,10 +28,10 @@ public class BCException extends RuntimeException { } public BCException(String s) { - super(s); + super(s + "\n" + CompilationAndWeavingContext.getCurrentContext()); } public BCException(String s, Throwable thrown) { - super(s); + this(s); this.thrown = thrown; } public void printStackTrace() { diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java index dcb18a3fc..87ed3e648 100644 --- a/weaver/src/org/aspectj/weaver/World.java +++ b/weaver/src/org/aspectj/weaver/World.java @@ -29,6 +29,7 @@ import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.Message; import org.aspectj.bridge.MessageUtil; import org.aspectj.bridge.IMessage.Kind; +import org.aspectj.bridge.context.PinpointingMessageHandler; import org.aspectj.weaver.UnresolvedType.TypeKind; import org.aspectj.weaver.patterns.DeclarePrecedence; import org.aspectj.weaver.patterns.PerClause; @@ -69,6 +70,9 @@ public abstract class World implements Dump.INode { /** XhasMember option setting passed down to weaver */ private boolean XhasMember = false; + /** Xpinpoint controls whether we put out developer info showing the source of messages */ + private boolean Xpinpoint = false; + /** When behaving in a Java 5 way autoboxing is considered */ private boolean behaveInJava5Way = false; @@ -504,7 +508,11 @@ public abstract class World implements Dump.INode { } public void setMessageHandler(IMessageHandler messageHandler) { - this.messageHandler = messageHandler; + if (this.isInPinpointMode()) { + this.messageHandler = new PinpointingMessageHandler(messageHandler); + } else { + this.messageHandler = messageHandler; + } } /** @@ -602,6 +610,14 @@ public abstract class World implements Dump.INode { XhasMember = b; } + public boolean isInPinpointMode() { + return Xpinpoint; + } + + public void setPinpointMode(boolean b) { + this.Xpinpoint = b; + } + public void setBehaveInJava5Way(boolean b) { behaveInJava5Way = b; } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java index 6c17184b7..a6fe494f3 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java @@ -57,6 +57,8 @@ import org.aspectj.apache.bcel.generic.annotation.AnnotationGen; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.WeaveMessage; +import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.bridge.context.ContextToken; import org.aspectj.util.PartialOrder; import org.aspectj.weaver.AjAttribute; import org.aspectj.weaver.AjcMemberMaker; @@ -1726,9 +1728,11 @@ class BcelClassWeaver implements IClassWeaver { private boolean match(BcelShadow shadow, List shadowAccumulator) { //System.err.println("match: " + shadow); + ContextToken shadowMatchToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.MATCHING_SHADOW, shadow); boolean isMatched = false; for (Iterator i = shadowMungers.iterator(); i.hasNext(); ) { ShadowMunger munger = (ShadowMunger)i.next(); + ContextToken mungerMatchToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.MATCHING_POINTCUT, munger.getPointcut()); if (munger.match(shadow, world)) { WeaverMetrics.recordMatchResult(true);// Could pass: munger @@ -1741,9 +1745,11 @@ class BcelClassWeaver implements IClassWeaver { } else { WeaverMetrics.recordMatchResult(false); // Could pass: munger } + CompilationAndWeavingContext.leavingPhase(mungerMatchToken); } if (isMatched) shadowAccumulator.add(shadow); + CompilationAndWeavingContext.leavingPhase(shadowMatchToken); return isMatched; } @@ -1759,7 +1765,9 @@ class BcelClassWeaver implements IClassWeaver { for (Iterator i = shadows.iterator(); i.hasNext(); ) { BcelShadow shadow = (BcelShadow)i.next(); + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.IMPLEMENTING_ON_SHADOW,shadow); shadow.implement(); + CompilationAndWeavingContext.leavingPhase(tok); } mg.matchedShadows = null; } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java index c13b8df83..0045130a0 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java @@ -2822,7 +2822,7 @@ public class BcelShadow extends Shadow { public LazyMethodGen extractMethod(String newMethodName, int visibilityModifier, ShadowMunger munger) { LazyMethodGen.assertGoodBody(range.getBody(), newMethodName); - if (!getKind().allowsExtraction()) throw new BCException(); + if (!getKind().allowsExtraction()) throw new BCException("Attempt to extract method from a shadow kind that does not support this operation (" + getKind() + ")"); LazyMethodGen freshMethod = createMethodGen(newMethodName,visibilityModifier); // System.err.println("******"); diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index 997c57418..19cfd39a1 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -34,6 +34,8 @@ import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.Message; import org.aspectj.bridge.MessageUtil; import org.aspectj.bridge.WeaveMessage; +import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.bridge.context.ContextToken; import org.aspectj.weaver.AjcMemberMaker; import org.aspectj.weaver.AnnotationOnTypeMunger; import org.aspectj.weaver.AnnotationX; @@ -71,6 +73,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { } public boolean munge(BcelClassWeaver weaver) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.MUNGING_WITH, this); boolean changed = false; boolean worthReporting = true; @@ -150,6 +153,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { } } + CompilationAndWeavingContext.leavingPhase(tok); return changed; } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java index 3549d4872..1aefee5b9 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java @@ -52,6 +52,8 @@ import org.aspectj.bridge.Message; import org.aspectj.bridge.MessageUtil; import org.aspectj.bridge.SourceLocation; import org.aspectj.bridge.WeaveMessage; +import org.aspectj.bridge.context.CompilationAndWeavingContext; +import org.aspectj.bridge.context.ContextToken; import org.aspectj.util.FileUtil; import org.aspectj.util.FuzzyBoolean; import org.aspectj.weaver.Advice; @@ -952,10 +954,12 @@ public class BcelWeaver implements IWeaver { // variation of "weave" that sources class files from an external source. public Collection weave(IClassFileProvider input) throws IOException { + ContextToken weaveToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING, ""); Collection wovenClassNames = new ArrayList(); IWeaveRequestor requestor = input.getRequestor(); requestor.processingReweavableState(); + ContextToken reweaveToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_REWEAVABLE_STATE,""); prepareToProcessReweavableState(); // clear all state from files we'll be reweaving for (Iterator i = input.getClassFileIterator(); i.hasNext(); ) { @@ -965,10 +969,16 @@ public class BcelWeaver implements IWeaver { // null return from getClassType() means the delegate is an eclipse source type - so // there *cant* be any reweavable state... (he bravely claimed...) - if (classType !=null) + if (classType !=null) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_REWEAVABLE_STATE, className); processReweavableStateIfPresent(className, classType); + CompilationAndWeavingContext.leavingPhase(tok); + } } + CompilationAndWeavingContext.leavingPhase(reweaveToken); + + ContextToken typeMungingToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_TYPE_MUNGERS,""); requestor.addingTypeMungers(); // We process type mungers in two groups, first mungers that change the type @@ -993,7 +1003,10 @@ public class BcelWeaver implements IWeaver { addNormalTypeMungers(className); } + CompilationAndWeavingContext.leavingPhase(typeMungingToken); + requestor.weavingAspects(); + ContextToken aspectToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_ASPECTS, ""); // first weave into aspects for (Iterator i = input.getClassFileIterator(); i.hasNext(); ) { UnwovenClassFile classFile = (UnwovenClassFile)i.next(); @@ -1004,8 +1017,10 @@ public class BcelWeaver implements IWeaver { wovenClassNames.add(className); } } + CompilationAndWeavingContext.leavingPhase(aspectToken); requestor.weavingClasses(); + ContextToken classToken = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_CLASSES, ""); // then weave into non-aspects for (Iterator i = input.getClassFileIterator(); i.hasNext(); ) { UnwovenClassFile classFile = (UnwovenClassFile)i.next(); @@ -1016,6 +1031,7 @@ public class BcelWeaver implements IWeaver { wovenClassNames.add(className); } } + CompilationAndWeavingContext.leavingPhase(classToken); addedClasses = new ArrayList(); deletedTypenames = new ArrayList(); @@ -1024,6 +1040,7 @@ public class BcelWeaver implements IWeaver { warnOnUnmatchedAdvice(); requestor.weaveCompleted(); + CompilationAndWeavingContext.leavingPhase(weaveToken); return wovenClassNames; } @@ -1119,7 +1136,9 @@ public class BcelWeaver implements IWeaver { weaveParentsFor(typesForWeaving,rtxI.getName()); } } + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_DECLARE_PARENTS,rtx.getName()); weaveParentTypeMungers(rtx); // Now do this type + CompilationAndWeavingContext.leavingPhase(tok); typesForWeaving.remove(typeToWeave); // and remove it from the list of those to process } @@ -1168,6 +1187,7 @@ public class BcelWeaver implements IWeaver { private void weaveAndNotify(UnwovenClassFile classFile, BcelObjectType classType, IWeaveRequestor requestor) throws IOException { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.WEAVING_TYPE, classType.getResolvedTypeX().getName()); LazyClassGen clazz = weaveWithoutDump(classFile,classType); classType.finishedWith(); //clazz is null if the classfile was unchanged by weaving... @@ -1179,6 +1199,7 @@ public class BcelWeaver implements IWeaver { } else { requestor.acceptResult(classFile); } + CompilationAndWeavingContext.leavingPhase(tok); } /** helper method - will return NULL if the underlying delegate is an EclipseSourceType and not a BcelObjectType */ @@ -1379,6 +1400,7 @@ public class BcelWeaver implements IWeaver { } public void weaveNormalTypeMungers(ResolvedType onType) { + ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.PROCESSING_TYPE_MUNGERS, onType.getName()); if (onType.isRawType() || onType.isParameterizedType()) onType = onType.getGenericType(); for (Iterator i = typeMungerList.iterator(); i.hasNext(); ) { ConcreteTypeMunger m = (ConcreteTypeMunger)i.next(); @@ -1386,6 +1408,7 @@ public class BcelWeaver implements IWeaver { onType.addInterTypeMunger(m); } } + CompilationAndWeavingContext.leavingPhase(tok); } diff --git a/weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java b/weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java index 4cd3ee58a..b3de2d417 100644 --- a/weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java +++ b/weaver/src/org/aspectj/weaver/bcel/ClassPathManager.java @@ -148,7 +148,7 @@ public class ClassPathManager { try { if (fis!=null) fis.close(); } catch (IOException ioe) { - throw new BCException("Can't close class file : "+file.getName()+": "+ioe.toString()); + throw new BCException("Can't close class file : "+file.getName(),ioe); } finally { fis = null; } @@ -250,7 +250,7 @@ public class ClassPathManager { zipFile = new ZipFile(file); openArchives.add(zipFile); } catch (IOException ioe) { - throw new BCException("Can't open archive: "+file.getName()+": "+ioe.toString()); + throw new BCException("Can't open archive: "+file.getName(),ioe); } } @@ -272,7 +272,7 @@ public class ClassPathManager { openArchives.remove(zipFile); zipFile.close(); } catch (IOException ioe) { - throw new BCException("Can't close archive: "+file.getName()+": "+ioe.toString()); + throw new BCException("Can't close archive: "+file.getName(),ioe); } finally { zipFile = null; } |