diff options
author | avasseur <avasseur> | 2005-05-04 14:57:21 +0000 |
---|---|---|
committer | avasseur <avasseur> | 2005-05-04 14:57:21 +0000 |
commit | 2679e77604bf50748ec715206258dd8a3586fb87 (patch) | |
tree | 3ea1965e734da2b1490aff3460ef37c8bd3fb05a | |
parent | 929c87018158604e439a24fbdfdb721d6a07fff7 (diff) | |
download | aspectj-2679e77604bf50748ec715206258dd8a3586fb87.tar.gz aspectj-2679e77604bf50748ec715206258dd8a3586fb87.zip |
LTW modules + AntSpec to test LTW in the sandbox + code cleanup in my FIXME + fix in error handling when no debug info can be read from @Aj aspect (many files modified since refactored IMessageHanlder for LTW dontIgnore method)
26 files changed, 477 insertions, 61 deletions
diff --git a/bridge/src/org/aspectj/bridge/CountingMessageHandler.java b/bridge/src/org/aspectj/bridge/CountingMessageHandler.java index 3cdd7d482..5bfe0b971 100644 --- a/bridge/src/org/aspectj/bridge/CountingMessageHandler.java +++ b/bridge/src/org/aspectj/bridge/CountingMessageHandler.java @@ -65,7 +65,16 @@ public class CountingMessageHandler implements IMessageHandler { public boolean isIgnoring(IMessage.Kind kind) { return delegate.isIgnoring(kind); } - + + /** + * Delegate + * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) + * @param kind + */ + public void dontIgnore(IMessage.Kind kind) { + delegate.dontIgnore(kind); + } + /** @return delegate.toString() */ public String toString() { return delegate.toString(); diff --git a/bridge/src/org/aspectj/bridge/IMessageHandler.java b/bridge/src/org/aspectj/bridge/IMessageHandler.java index 76b76ec0b..d3846db73 100644 --- a/bridge/src/org/aspectj/bridge/IMessageHandler.java +++ b/bridge/src/org/aspectj/bridge/IMessageHandler.java @@ -49,6 +49,9 @@ public interface IMessageHandler { public boolean isIgnoring(IMessage.Kind kind) { return false; } + public void dontIgnore(IMessage.Kind kind) { + ; + } }; /** @@ -66,4 +69,12 @@ public interface IMessageHandler { * @return true if this handler is ignoring all messages of this type */ boolean isIgnoring(IMessage.Kind kind); + + /** + * Allow fine grained configuration after initialization. Minaly used in LTW. Most of the + * implementation can have this method be a no-op. + * + * @param kind + */ + void dontIgnore(IMessage.Kind kind); } diff --git a/bridge/src/org/aspectj/bridge/MessageUtil.java b/bridge/src/org/aspectj/bridge/MessageUtil.java index 79250943e..fd4a41efe 100644 --- a/bridge/src/org/aspectj/bridge/MessageUtil.java +++ b/bridge/src/org/aspectj/bridge/MessageUtil.java @@ -358,6 +358,9 @@ public class MessageUtil { public boolean isIgnoring(Kind kind) { return false; } + public void dontIgnore(IMessage.Kind kind) { + ; + } }; return visitMessages(holder, selector, true, false); } @@ -576,7 +579,11 @@ public class MessageUtil { return (0 < IMessage.Kind.COMPARATOR.compare(sought, kind)); } } - + + public void dontIgnore(IMessage.Kind kind) { + ; + } + private boolean textIn(IMessage message) { if (null == infix) { return true; diff --git a/bridge/src/org/aspectj/bridge/MessageWriter.java b/bridge/src/org/aspectj/bridge/MessageWriter.java index 467002c3b..bc9530314 100644 --- a/bridge/src/org/aspectj/bridge/MessageWriter.java +++ b/bridge/src/org/aspectj/bridge/MessageWriter.java @@ -52,13 +52,22 @@ public class MessageWriter implements IMessageHandler { } /** - * @see org.aspectj.bridge.IMessageHandler#isIgnoring(Kind) + * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) */ public boolean isIgnoring(IMessage.Kind kind) { // XXX share MessageHandler implementation in superclass return false; } + /** + * No-op + * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) + * @param kind + */ + public void dontIgnore(IMessage.Kind kind) { + ; + } + /** @return null to not print, or message rendering (including newlines) */ protected String render(IMessage message) { return message.toString(); diff --git a/lib/test/loadtime5.jar b/lib/test/loadtime5.jar Binary files differnew file mode 100644 index 000000000..18892227d --- /dev/null +++ b/lib/test/loadtime5.jar diff --git a/loadtime/src/org/aspectj/weaver/loadtime/Aj.java b/loadtime/src/org/aspectj/weaver/loadtime/Aj.java index 057669d2f..69af2ef14 100644 --- a/loadtime/src/org/aspectj/weaver/loadtime/Aj.java +++ b/loadtime/src/org/aspectj/weaver/loadtime/Aj.java @@ -128,6 +128,7 @@ public class Aj implements ClassPreProcessor { * @throws Throwable */ static void __dump(String name, byte[] b) throws Throwable { + if (true) return;//FIXME AV have an option String className = name.replace('.', '/'); final File dir; if (className.indexOf('/') > 0) { 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 index a7c9bc056..d70388605 100644 --- 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 @@ -120,7 +120,16 @@ public class WeaverMessageHandler implements IMessageHandler { public boolean isIgnoring(Kind kind) { return sink.isIgnoring(kind); } - + + /** + * No-op + * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) + * @param kind + */ + public void dontIgnore(IMessage.Kind kind) { + ; + } + private int getStartPos(ISourceLocation sLoc,CompilationResult result) { int pos = 0; if (sLoc == null) return 0; 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 5407758ff..471770f7b 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 @@ -228,7 +228,16 @@ public class AspectJBuilder extends JavaBuilder implements ICompilerAdapterFacto if (kind == IMessage.DEBUG || kind == IMessage.INFO) return true; return false; } - + + /** + * No-op + * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) + * @param kind + */ + public void dontIgnore(IMessage.Kind kind) { + ; + } + } 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 56aaaef5a..365242c73 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 @@ -534,8 +534,17 @@ public class Main { public boolean isIgnoring(IMessage.Kind kind) { return (null != getStreamFor(kind)); } - - /** @return System.err for FAIL, ABORT, ERROR, and WARNING, + + /** + * No-op + * @see org.aspectj.bridge.IMessageHandler#isIgnoring(org.aspectj.bridge.IMessage.Kind) + * @param kind + */ + public void dontIgnore(IMessage.Kind kind) { + ; + } + + /** @return System.err for FAIL, ABORT, ERROR, and WARNING, * System.out for INFO if -verbose and WEAVEINFO if -showWeaveInfo. */ protected PrintStream getStreamFor(IMessage.Kind kind) { diff --git a/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java b/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java index 77e8a3b40..02a5028c4 100644 --- a/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java +++ b/org.aspectj.ajdt.core/testsrc/org/aspectj/tools/ajc/AjcTestCase.java @@ -58,7 +58,7 @@ public class AjcTestCase extends TestCase { */ protected Ajc ajc; - private static final String DEFAULT_CLASSPATH_ENTRIES = + public static final String DEFAULT_CLASSPATH_ENTRIES = File.pathSeparator + ".." + File.separator + "runtime" + File.separator + "bin" + File.pathSeparator + diff --git a/testing-client/testsrc/org/aspectj/testing/TesterTest.java b/testing-client/testsrc/org/aspectj/testing/TesterTest.java index 5acce235d..4ed67cac4 100644 --- a/testing-client/testsrc/org/aspectj/testing/TesterTest.java +++ b/testing-client/testsrc/org/aspectj/testing/TesterTest.java @@ -202,7 +202,11 @@ public class TesterTest extends TestCase { public boolean isIgnoring(IMessage.Kind kind) { return false; } - + + public void dontIgnore(IMessage.Kind kind) { + ; + } + public boolean handleMessage(IMessage message) { (message.isFailed() ? failures : passes).add(message); return true; diff --git a/testing/newsrc/org/aspectj/testing/AntSpec.java b/testing/newsrc/org/aspectj/testing/AntSpec.java new file mode 100644 index 000000000..84abb4b2a --- /dev/null +++ b/testing/newsrc/org/aspectj/testing/AntSpec.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * 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: + * Alexandre Vasseur initial implementation + *******************************************************************************/ +package org.aspectj.testing; + +import org.aspectj.tools.ajc.AjcTestCase; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.ProjectHelper; +import org.apache.tools.ant.DefaultLogger; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.types.Path; + +import java.io.File; +import java.util.StringTokenizer; + +/** + * Element that allow to run an abritrary Ant target in a sandbox. + * <p/> + * Such a spec is used in a "<ajc-test><ant file="myAnt.xml" [target="..."] [verbose="true"]/> XML element. + * The "target" is optional. If not set, default myAnt.xml target is used. + * The "file" file is looked up from the <ajc-test dir="..."/> attribute. + * If "verbose" is set to "true", the ant -v output is piped, else nothing is reported except errors. + * <p/> + * The called Ant target benefits from 2 implicit variables: + * "${aj.sandbox}" points to the test current sandbox folder. + * "aj.path" is an Ant refid on the classpath formed with the sandbox folder + ltw + the AjcTestCase classpath + * (ie usually aspectjrt, junit, and testing infra) + * <p/> + * Element "<stdout><line text="..">" and "<stderr><line text="..">" can be used. For now a full match + * is performed on the output of the runned target only (not the whole Ant invocation). This is experimental + * and advised to use a "<junit>" task instead or a "<java>" whose main that throws some exception upon failure. + * + * + * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> + */ +public class AntSpec implements ITestStep { + + private final static String DEFAULT_LTW_CLASSPATH_ENTRIES = + ".." + File.separator + "_IDE"//ALEX hack since IntelliJ does not produce modules/bin/ + + File.pathSeparator + ".." + File.separator + "asm/bin" + + File.pathSeparator + ".." + File.separator + "bridge/bin" + + File.pathSeparator + ".." + File.separator + "loadtime/bin" + + File.pathSeparator + ".." + File.separator + "loadtime5/bin" + + File.pathSeparator + ".." + File.separator + "weaver/bin" + + File.pathSeparator + ".." + File.separator + "lib/bcel/bcel.jar"; + + + private boolean m_verbose = false; + private AjcTest m_ajcTest; + private OutputSpec m_stdErrSpec; + private OutputSpec m_stdOutSpec; + private String m_antFile; + private String m_antTarget; + + public void execute(AjcTestCase inTestCase) { + final String failMessage = "test \"" + m_ajcTest.getTitle() + "\" failed: "; + + File buildFile = new File(m_ajcTest.getDir() + File.separatorChar + m_antFile); + if (!buildFile.exists()) { + AjcTestCase.fail(failMessage + "no such Ant file " + buildFile.getAbsolutePath()); + } + Project p = new Project(); + final StringBuffer stdout = new StringBuffer(); + final StringBuffer stderr = new StringBuffer(); + try { + // read the Ant file + p.init(); + p.setUserProperty("ant.file", buildFile.getAbsolutePath()); + // setup aj.sandbox + p.setUserProperty("aj.sandbox", inTestCase.getSandboxDirectory().getAbsolutePath()); + // setup aj.dir "modules" folder + p.setUserProperty("aj.root", new File("..").getAbsolutePath()); + + ProjectHelper helper = ProjectHelper.getProjectHelper(); + helper.parse(p, buildFile); + + // use default target if no target specified + if (m_antTarget == null) { + m_antTarget = p.getDefaultTarget(); + } + + // make sure we listen for failure + DefaultLogger consoleLogger = new DefaultLogger() { + public void targetFinished(BuildEvent event) { + super.targetFinished(event); + if (event.getException() != null) { + AjcTestCase.fail(failMessage + "failure in '" + event.getTarget() + "' " + event.getException()); + } + } + public void messageLogged(BuildEvent event) { + super.messageLogged(event); + if (event.getTarget() != null && event.getPriority() >= Project.MSG_INFO && m_antTarget.equals(event.getTarget().getName())) { + if (event.getException() == null) { + stdout.append(event.getMessage()).append('\n'); + } else { + stderr.append(event.getMessage()); + } + } + } + }; + consoleLogger.setErrorPrintStream(System.err); + consoleLogger.setOutputPrintStream(System.out); + consoleLogger.setMessageOutputLevel(m_verbose?Project.MSG_VERBOSE:Project.MSG_ERR); + p.addBuildListener(consoleLogger); + + // create the test implicit path aj.path that contains the sandbox + regular test infra path + Path path = new Path(p, inTestCase.getSandboxDirectory().getAbsolutePath()); + populatePath(path, DEFAULT_LTW_CLASSPATH_ENTRIES); + populatePath(path, AjcTestCase.DEFAULT_CLASSPATH_ENTRIES); + p.addReference("aj.path", path); + } catch (Throwable t) { + AjcTestCase.fail(failMessage + "invalid Ant script :" + t.toString()); + } + try { + p.fireBuildStarted(); + p.executeTarget(m_antTarget); + p.fireBuildFinished(null); + } catch (BuildException e) { + p.fireBuildFinished(e); + } catch (Throwable t) { + AjcTestCase.fail(failMessage + "error when invoking target :" + t.toString()); + } + + // match lines + //TODO AV experimental: requires full match so rather useless. + // if someone needs it, we ll have to impl a "include / exclude" stuff + if (m_stdOutSpec != null) + m_stdOutSpec.matchAgainst(stdout.toString()); + // match lines + if (m_stdErrSpec != null) + m_stdErrSpec.matchAgainst(stdout.toString()); + } + + public void addStdErrSpec(OutputSpec spec) { + if (m_stdErrSpec!=null) + throw new UnsupportedOperationException("only one 'stderr' allowed in 'ant'"); + m_stdErrSpec = spec; + } + + public void addStdOutSpec(OutputSpec spec) { + if (m_stdOutSpec!=null) + throw new UnsupportedOperationException("only one 'stdout' allowed in 'ant'"); + m_stdOutSpec = spec; + } + + public void setVerbose(String verbose) { + if (verbose != null && "true".equalsIgnoreCase(verbose)) { + m_verbose = true; + } + } + + public void setFile(String file) { + m_antFile = file; + } + + public void setTarget(String target) { + m_antTarget = target; + } + + public void addExpectedMessage(ExpectedMessageSpec message) { + throw new UnsupportedOperationException("don't use 'message' in 'ant' specs."); + } + + public void setBaseDir(String dir) { + ; + } + + public void setTest(AjcTest test) { + m_ajcTest = test; + } + + private static void populatePath(Path path, String pathEntries) { + StringTokenizer st = new StringTokenizer(pathEntries, File.pathSeparator); + while (st.hasMoreTokens()) { + path.setPath(new File(st.nextToken()).getAbsolutePath()); + } + } +} diff --git a/testing/newsrc/org/aspectj/testing/XMLBasedAjcTestCase.java b/testing/newsrc/org/aspectj/testing/XMLBasedAjcTestCase.java index 91ded4c1a..2f00a3c1b 100644 --- a/testing/newsrc/org/aspectj/testing/XMLBasedAjcTestCase.java +++ b/testing/newsrc/org/aspectj/testing/XMLBasedAjcTestCase.java @@ -145,6 +145,17 @@ public abstract class XMLBasedAjcTestCase extends AjcTestCase { digester.addObjectCreate("suite/ajc-test/weave",WeaveSpec.class); digester.addSetProperties("suite/ajc-test/weave"); digester.addSetNext("suite/ajc-test/weave","addTestStep","org.aspectj.testing.ITestStep"); + + digester.addObjectCreate("suite/ajc-test/ant",AntSpec.class); + digester.addSetProperties("suite/ajc-test/ant"); + digester.addSetNext("suite/ajc-test/ant","addTestStep","org.aspectj.testing.ITestStep"); + digester.addObjectCreate("suite/ajc-test/ant/stderr",OutputSpec.class); + digester.addSetProperties("suite/ajc-test/ant/stderr"); + digester.addSetNext("suite/ajc-test/ant/stderr","addStdErrSpec","org.aspectj.testing.OutputSpec"); + digester.addObjectCreate("suite/ajc-test/ant/stdout",OutputSpec.class); + digester.addSetProperties("suite/ajc-test/ant/stdout"); + digester.addSetNext("suite/ajc-test/ant/stdout","addStdOutSpec","org.aspectj.testing.OutputSpec"); + digester.addObjectCreate("suite/ajc-test/run/stderr",OutputSpec.class); digester.addSetProperties("suite/ajc-test/run/stderr"); digester.addSetNext("suite/ajc-test/run/stderr","addStdErrSpec","org.aspectj.testing.OutputSpec"); diff --git a/testing/src/org/aspectj/testing/run/RunStatus.java b/testing/src/org/aspectj/testing/run/RunStatus.java index ce3bff73a..71fd63612 100644 --- a/testing/src/org/aspectj/testing/run/RunStatus.java +++ b/testing/src/org/aspectj/testing/run/RunStatus.java @@ -224,7 +224,7 @@ public class RunStatus implements IRunStatus { * @return true if completed, not aborted, no thrown, no * messages of kind ERROR, FAIL or ABORT, and * result object is not IRunStatus.FAIL. - * @see org.aspectj.testing.harness.newbridge.IRunStatus#runResult() + * @see org.aspectj.testing.run.IRunStatus#runResult() */ public boolean runResult() { return validator.runPassed(this); @@ -277,23 +277,27 @@ public class RunStatus implements IRunStatus { public boolean isIgnoring(IMessage.Kind kind) { return messageHolder.isIgnoring(kind); } - + + public void dontIgnore(IMessage.Kind kind) { + messageHolder.dontIgnore(kind); + } + /** - * @see org.aspectj.bridge.IMessageHolder#hasAnyMessage(Kind, boolean) + * @see org.aspectj.bridge.IMessageHolder#hasAnyMessage(org.aspectj.bridge.IMessage.Kind, boolean) */ public boolean hasAnyMessage(IMessage.Kind kind, boolean orGreater) { return messageHolder.hasAnyMessage(kind, orGreater); } /** - * @see org.aspectj.bridge.IMessageHolder#getMessages(Kind) + * @see org.aspectj.bridge.IMessageHolder#getMessages(org.aspectj.bridge.IMessage.Kind, boolean) */ public IMessage[] getMessages(IMessage.Kind kind, boolean orGreater) { return messageHolder.getMessages(kind, orGreater); } /** - * @see org.aspectj.bridge.IMessageHolder#numMessages(Kind) + * @see org.aspectj.bridge.IMessageHolder#numMessages(org.aspectj.bridge.IMessage.Kind, boolean) */ public int numMessages(IMessage.Kind kind, boolean orGreater) { return messageHolder.numMessages(kind, orGreater); diff --git a/tests/java5/ataspectj/ajc-ant.xml b/tests/java5/ataspectj/ajc-ant.xml new file mode 100644 index 000000000..4aaf76d0d --- /dev/null +++ b/tests/java5/ataspectj/ajc-ant.xml @@ -0,0 +1,20 @@ +<!-- ajc-ant script, not to be used from Ant commant line - see AntSpec --> +<project name="foo" default="all"> + + <target name="compile:javac"> + <!-- compile only javac compilable stuff --> + <javac destdir="${aj.sandbox}" classpathref="aj.path" + srcdir="${basedir}" + includes="ataspectj/*" + debug="true"> + </javac> + </target> + + <target name="all" depends="compile:javac"> + <java fork="yes" classname="ataspectj.AllLTWTests" failonerror="yes"> + <classpath refid="aj.path"/> + <jvmarg value="-javaagent:${aj.root}/lib/test/loadtime5.jar"/> + <jvmarg value="-Daj5.def=ataspectj/aop.xml"/> + </java> + </target> +</project>
\ No newline at end of file diff --git a/tests/java5/ataspectj/ataspectj/AllLTWTests.java b/tests/java5/ataspectj/ataspectj/AllLTWTests.java new file mode 100644 index 000000000..eddd0cde2 --- /dev/null +++ b/tests/java5/ataspectj/ataspectj/AllLTWTests.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2005 Contributors. + * 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: + * Alexandre Vasseur initial implementation + *******************************************************************************/ +package ataspectj; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import test.loadtime5.AtAspectJTest; + +/** + * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> + */ +public class AllLTWTests extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite("All tests"); + + suite.addTestSuite(ataspectj.SingletonAspectBindingsTest.class); + suite.addTestSuite(ataspectj.CflowTest.class); + suite.addTestSuite(ataspectj.PointcutReferenceTest.class); + suite.addTestSuite(ataspectj.AfterXTest.class); + //FIXME AV - fix the pc grammar to support if for @AJ aspects + System.err.println("(AllTests: IfPointcutTest fails)"); + //suite.addTestSuite(IfPointcutTest.class); + suite.addTestSuite(ataspectj.XXJoinPointTest.class); + suite.addTestSuite(ataspectj.PrecedenceTest.class); + suite.addTestSuite(ataspectj.BindingTest.class); + suite.addTestSuite(ataspectj.PerClauseTest.class); + suite.addTestSuite(AroundInlineMungerTest.class); + + return suite; + } + + public static void main(String[] args) { + TestHelper.runAndThrowOnFailure(suite()); + } + +} diff --git a/tests/java5/ataspectj/ataspectj/BindingTest.java b/tests/java5/ataspectj/ataspectj/BindingTest.java index 342b8ebf0..62e1dfe13 100644 --- a/tests/java5/ataspectj/ataspectj/BindingTest.java +++ b/tests/java5/ataspectj/ataspectj/BindingTest.java @@ -82,12 +82,12 @@ public class BindingTest extends TestCase { } public void testAccessAspectState() { - //TestAspect_1 aspect = (TestAspect_1) Aspects.aspectOf(TestAspect_1.class); - //aspect.m_count = 0; + TestAspect_1 aspect = (TestAspect_1) Aspects.aspectOf(TestAspect_1.class); + aspect.m_count = 0; int res = echo(3); res += echo(3); assertEquals(6, res); - //assertEquals(2, aspect.m_count); + assertEquals(2, aspect.m_count); } public void testTryCatch() { @@ -181,7 +181,7 @@ public class BindingTest extends TestCase { @Around("call(int echo(int)) && withincode(void ataspectj.BindingTest.testAccessAspectState()) && args(i)") public Object aaround7(int i, final ProceedingJoinPoint jp) throws Throwable { - //m_count++;// what if inlined ?//FIXME + m_count++;// will be wrapped for inlining support return jp.proceed(); } diff --git a/tests/java5/ataspectj/ataspectj/aop.xml b/tests/java5/ataspectj/ataspectj/aop.xml new file mode 100644 index 000000000..d76592f04 --- /dev/null +++ b/tests/java5/ataspectj/ataspectj/aop.xml @@ -0,0 +1,25 @@ +<?xml version="1.0"?> +<aspectj> + <aspects> + <!-- see here nested class with ".", "$" is accepted as well --> + <aspect name="ataspectj.SingletonAspectBindingsTest.TestAspect"/> + <aspect name="ataspectj.CflowTest.TestAspect"/> + <aspect name="ataspectj.PointcutReferenceTest.TestAspect"/> + <aspect name="ataspectj.AfterXTest.TestAspect"/> +<!-- <aspect name="ataspectj.IfPointcutTest.TestAspect"/>--> + <aspect name="ataspectj.XXJoinPointTest.TestAspect"/> + <aspect name="ataspectj.PrecedenceTest.TestAspect_2"/> + <aspect name="ataspectj.PrecedenceTest.TestAspect_1"/> + <aspect name="ataspectj.PrecedenceTest.TestAspect_3"/> + <aspect name="ataspectj.PrecedenceTest.TestAspect_Order"/> + + <aspect name="ataspectj.BindingTest.TestAspect_1"/> + + <aspect name="ataspectj.PerClauseTest.TestAspectPerSingleton"/> + <aspect name="ataspectj.PerClauseTest.TestAspectPerTarget"/> + <aspect name="ataspectj.PerClauseTest.TestAspectPerCflow"/> + <aspect name="ataspectj.PerClauseTest.TestAspectPTW"/> + + <aspect name="ataspectj.AroundInlineMungerTest.Open"/> + </aspects> +</aspectj> diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml index eab2949e5..89981e4fa 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml @@ -93,4 +93,8 @@ <compile files="ataspectj/AroundInlineMungerTest.java,ataspectj/TestHelper.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore"/> <run class="ataspectj.AroundInlineMungerTest"/> </ajc-test> + + <ajc-test dir="java5/ataspectj" title="RunThemAllWithJavacCompiledAndLTW"> + <ant file="ajc-ant.xml" target="all"/> + </ajc-test> </suite>
\ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/Shadow.java b/weaver/src/org/aspectj/weaver/Shadow.java index 93c49f0f0..d0936c214 100644 --- a/weaver/src/org/aspectj/weaver/Shadow.java +++ b/weaver/src/org/aspectj/weaver/Shadow.java @@ -458,17 +458,16 @@ public abstract class Shadow { else if (ak.getKey()==AdviceKind.Around.getKey()) return IRelationship.Kind.ADVICE_AROUND; else if (ak.getKey()==AdviceKind.CflowEntry.getKey() || - ak.getKey()==AdviceKind.CflowBelowEntry.getKey() || - ak.getKey()==AdviceKind.InterInitializer.getKey() || - ak.getKey()==AdviceKind.PerCflowEntry.getKey() || - ak.getKey()==AdviceKind.PerCflowBelowEntry.getKey() || - ak.getKey()==AdviceKind.PerThisEntry.getKey() || - ak.getKey()==AdviceKind.PerTargetEntry.getKey() || - ak.getKey()==AdviceKind.Softener.getKey() || - ak.getKey()==AdviceKind.PerTypeWithinEntry.getKey()) { - //FIXME: Alex: why this System.err was there ?? It prints nasty thing in my LTW. - System.err.println("Dont want a message about this: "+ak); - return null; + ak.getKey()==AdviceKind.CflowBelowEntry.getKey() || + ak.getKey()==AdviceKind.InterInitializer.getKey() || + ak.getKey()==AdviceKind.PerCflowEntry.getKey() || + ak.getKey()==AdviceKind.PerCflowBelowEntry.getKey() || + ak.getKey()==AdviceKind.PerThisEntry.getKey() || + ak.getKey()==AdviceKind.PerTargetEntry.getKey() || + ak.getKey()==AdviceKind.Softener.getKey() || + ak.getKey()==AdviceKind.PerTypeWithinEntry.getKey()) { + //System.err.println("Dont want a message about this: "+ak); + return null; } throw new RuntimeException("Shadow.determineRelKind: What the hell is it? "+ak); } diff --git a/weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java b/weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java index 290e32f61..a9502994a 100644 --- a/weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java +++ b/weaver/src/org/aspectj/weaver/ataspectj/Aj5Attributes.java @@ -425,7 +425,12 @@ public class Aj5Attributes { ElementNameValuePair beforeAdvice = getAnnotationElement(before, "value"); if (beforeAdvice != null) { // this/target/args binding - FormalBinding[] bindings = extractBindings(struct); + FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; + try { + bindings = extractBindings(struct); + } catch (UnreadableDebugInfo unreadableDebugInfo) { + return false; + } IScope binding = new BindingScope( struct.enclosingType, bindings @@ -470,7 +475,12 @@ public class Aj5Attributes { ElementNameValuePair afterAdvice = getAnnotationElement(after, "value"); if (afterAdvice != null) { // this/target/args binding - FormalBinding[] bindings = extractBindings(struct); + FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; + try { + bindings = extractBindings(struct); + } catch (UnreadableDebugInfo unreadableDebugInfo) { + return false; + } IScope binding = new BindingScope( struct.enclosingType, bindings @@ -538,7 +548,12 @@ public class Aj5Attributes { // this/target/args binding // exclude the return binding from the pointcut binding since it is an extraArg binding - FormalBinding[] bindings = (returned==null?extractBindings(struct):extractBindings(struct, returned)); + FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; + try { + bindings = (returned==null?extractBindings(struct):extractBindings(struct, returned)); + } catch (UnreadableDebugInfo unreadableDebugInfo) { + return false; + } IScope binding = new BindingScope( struct.enclosingType, bindings @@ -611,7 +626,12 @@ public class Aj5Attributes { // this/target/args binding // exclude the throwned binding from the pointcut binding since it is an extraArg binding - FormalBinding[] bindings = (throwned==null?extractBindings(struct):extractBindings(struct, throwned)); + FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; + try { + bindings = (throwned==null?extractBindings(struct):extractBindings(struct, throwned)); + } catch (UnreadableDebugInfo unreadableDebugInfo) { + return false; + } IScope binding = new BindingScope( struct.enclosingType, bindings @@ -660,7 +680,12 @@ public class Aj5Attributes { ElementNameValuePair aroundAdvice = getAnnotationElement(around, "value"); if (aroundAdvice != null) { // this/target/args binding - FormalBinding[] bindings = extractBindings(struct); + FormalBinding[] bindings = new org.aspectj.weaver.patterns.FormalBinding[0]; + try { + bindings = extractBindings(struct); + } catch (UnreadableDebugInfo unreadableDebugInfo) { + return false; + } IScope binding = new BindingScope( struct.enclosingType, bindings @@ -732,10 +757,15 @@ public class Aj5Attributes { } // this/target/args binding - IScope binding = new BindingScope( - struct.enclosingType, - extractBindings(struct) - ); + final IScope binding; + try { + binding = new BindingScope( + struct.enclosingType, + extractBindings(struct) + ); + } catch(UnreadableDebugInfo e) { + return; + } TypeX[] argumentTypes = new TypeX[struct.method.getArgumentTypes().length]; for (int i = 0; i < argumentTypes.length; i++) { @@ -788,15 +818,25 @@ public class Aj5Attributes { * Build the bindings for a given method (pointcut / advice) * * @param struct - * @return + * @return null if no debug info is available */ - private static FormalBinding[] extractBindings(AjAttributeMethodStruct struct) { + private static FormalBinding[] extractBindings(AjAttributeMethodStruct struct) + throws UnreadableDebugInfo { Method method = struct.method; String[] argumentNames = struct.getArgumentNames(); // assert debug info was here if (argumentNames.length != method.getArgumentTypes().length) { - throw new RuntimeException("cannot access debug info " + method); + struct.handler.handleMessage( + new Message( + "Cannot read debug info for @Aspect '" + struct.enclosingType.getName() + "'" + + " (please compile with 'javac -g' or '<javac debug='true'.../>' in Ant)", + IMessage.FAIL, + null, + struct.enclosingType.getSourceLocation() + ) + ); + throw new UnreadableDebugInfo(); } List bindings = new ArrayList(); @@ -823,7 +863,8 @@ public class Aj5Attributes { } //FIXME alex deal with exclude index - private static FormalBinding[] extractBindings(AjAttributeMethodStruct struct, String excludeFormal) { + private static FormalBinding[] extractBindings(AjAttributeMethodStruct struct, String excludeFormal) + throws UnreadableDebugInfo { FormalBinding[] bindings = extractBindings(struct); int excludeIndex = -1; for (int i = 0; i < bindings.length; i++) { @@ -1056,4 +1097,10 @@ public class Aj5Attributes { } pointcut.m_ignoreUnboundBindingForNames = (String[])ignores.toArray(new String[ignores.size()]); } + + /** + * A check exception when we cannot read debug info (needed for formal binding) + */ + private static class UnreadableDebugInfo extends Exception { + } } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java index 813cf8232..e25beb343 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelAdvice.java @@ -150,11 +150,17 @@ public class BcelAdvice extends Advice { } else if (getKind() == AdviceKind.After) { shadow.weaveAfter(this); } else if (getKind() == AdviceKind.Around) { + // Note: under regular LTW the aspect is usually loaded after the first use of any class affecteted by it + // This means that as long as the aspect has not been thru the LTW, it's woven state is unknown + // and thus canInline(s) will return false. + // To force inlining (test), ones can do Class aspect = FQNAspect.class in the clinit of the target class + // FIXME AV : for AJC compiled @AJ aspect (or any code style aspect), the woven state can never be known + // if the aspect belongs to a parent classloader. In that case the aspect will never be inlined. + // It might be dangerous to change that especially for @AJ aspect non compiled with AJC since if those + // are not weaved (f.e. use of some limiteed LTW etc) then they cannot be prepared for inlining. + // One solution would be to flag @AJ aspect with an annotation as "prepared" and query that one. if (!canInline(s)) { shadow.weaveAroundClosure(this, hasDynamicTests()); - //FIXME : check Inlining and LTW - //ALEX : uncomment to force inlining for LTW - else inlining does not seems to happen. - //shadow.weaveAroundInline(this, hasDynamicTests()); } else { shadow.weaveAroundInline(this, hasDynamicTests()); } @@ -231,7 +237,7 @@ public class BcelAdvice extends Advice { */ public boolean mustCheckExceptions() { if (getConcreteAspect() == null) { - //FIXME Alex: not sure this is good to default to that. + //FIXME AV: not sure this is good to default to that. // dig when do we reach that ie not yet concretized return true; } @@ -357,7 +363,7 @@ public class BcelAdvice extends Advice { fact, getExtraParameterType().resolve(world)); } else { - //FIXME this code will throw an error if ProceedingJP is used in a before advice f.e. ok ?? + //FIXME AV test for that - this code will throw an error if ProceedingJP is used in a before advice f.e. ok ?? throw new Error("Should not happen - unbound advice argument at index " + i + " in [" + toString() + "]"); } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java index 0442d8c68..762bc52ae 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java @@ -1942,14 +1942,10 @@ public class BcelShadow extends Shadow { // specific test for @AJ proceedInInners if (munger.getConcreteAspect().isAnnotationStyleAspect()) { - //FIXME // if we can't find one proceed() // we suspect that the call is happening in an inner class // so we don't inline it. // Note: for code style, this is done at Aspect compilation time. - // Limitation: if there is two calls and one is done in an inner class, inlining will happen - // since we will see the non proceed in inner one as if it was the sole one. - // The one made in the inner class will never be madeXXX. Should be documented. boolean canSeeProceedPassedToOther = false; InstructionHandle curr = adviceMethod.getBody().getStart(); InstructionHandle end = adviceMethod.getBody().getEnd(); @@ -1957,11 +1953,7 @@ public class BcelShadow extends Shadow { while (curr != end) { InstructionHandle next = curr.getNext(); Instruction inst = curr.getInstruction(); - /*if ((inst instanceof INVOKEINTERFACE) - && "proceed".equals(((INVOKEINTERFACE) inst).getMethodName(cpg))) { - canSeeProceed = true; - //continue since we may have a proceed in inner or pjp as arg - } else*/ if ((inst instanceof InvokeInstruction) + if ((inst instanceof InvokeInstruction) && ((InvokeInstruction)inst).getSignature(cpg).indexOf("Lorg/aspectj/lang/ProceedingJoinPoint;") > 0) { // we may want to refine to exclude stuff returning jp ? // does code style skip inline if i write dump(thisJoinPoint) ? diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java index 5a62d9fc7..65db20769 100644 --- a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java +++ b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java @@ -88,7 +88,7 @@ public final class LazyMethodGen { private Attribute[] attributes; // private AnnotationGen[] annotations; /* private */ final LazyClassGen enclosingClass; - private final BcelMethod memberView; + private /*final*/ BcelMethod memberView;//FIXME AV LTW int highestLineNumber = 0; /** This is nonnull if this method is the result of an "inlining". We currently @@ -194,8 +194,10 @@ public final class LazyMethodGen { public boolean hasAnnotation(TypeX annotationTypeX) { initialize(); if (memberView==null) { - System.err.println("REPORT THIS! 02: Can't determine if "+this+" has annotation "+annotationTypeX); - return false; + memberView = new BcelMethod(getEnclosingClass().getBcelObjectType(), getMethod());//FIXME AV LTW + //System.err.println("REPORT THIS! 02: Can't determine if "+getEnclosingClass().getName() + "." + this.getName() + this.getSignature()+" has annotation "+annotationTypeX); + //return false + return memberView.hasAnnotation(annotationTypeX); } return memberView.hasAnnotation(annotationTypeX); } diff --git a/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java b/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java index a24008f7c..a1bf961cd 100644 --- a/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java +++ b/weaver/src/org/aspectj/weaver/tools/WeavingAdaptor.java @@ -174,6 +174,7 @@ public class WeavingAdaptor { */ public byte[] weaveClass (String name, byte[] bytes) throws IOException { if (shouldWeave(name)) { + System.out.println("WeavingAdaptor.weaveClass " + name); info("weaving '" + name + "'"); bytes = getWovenBytes(name, bytes); } @@ -192,7 +193,11 @@ public class WeavingAdaptor { } private boolean shouldWeaveName (String name) { - return !((name.startsWith("org.apache.bcel.") || name.startsWith("org.aspectj.") || name.startsWith("java.") || name.startsWith("javax."))); + return !((name.startsWith("org.apache.bcel.")//FIXME AV why ? bcel is wrapped in org.aspectj. + || name.startsWith("org.aspectj.") + || name.startsWith("java.") + || name.startsWith("javax.")) + || name.startsWith("$Proxy"));//JDK proxies } /** @@ -213,7 +218,6 @@ public class WeavingAdaptor { * @param bytes the bytes that define the class * @return byte[] the woven bytes for the class * @throws IOException - * @throws FileNotFoundException */ private byte[] getWovenBytes(String name, byte[] bytes) throws IOException { WeavingClassFileProvider wcp = new WeavingClassFileProvider(name,bytes); diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternMatchingTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternMatchingTestCase.java index e9173723d..35c191bbb 100644 --- a/weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternMatchingTestCase.java +++ b/weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternMatchingTestCase.java @@ -113,6 +113,7 @@ public class AnnotationPatternMatchingTestCase extends TestCase { return false; } public boolean isIgnoring(Kind kind) {return false;} + public void dontIgnore(IMessage.Kind kind) {;} } public void testReferenceToNonAnnotationType() { |