@@ -224,6 +224,10 @@ public class EclipseSourceType extends ResolvedTypeX.ConcreteName { | |||
public boolean hasAnnotation(ResolvedTypeX ofType) { | |||
throw new RuntimeException("How to implement this? Needs to ask eclipse!"); | |||
} | |||
public ResolvedTypeX[] getAnnotationTypes() { | |||
throw new RuntimeException("How to implement this? Needs to ask eclipse!"); | |||
} | |||
public PerClause getPerClause() { | |||
//should probably be: ((AspectDeclaration)declaration).perClause; |
@@ -0,0 +1,11 @@ | |||
public class AnnotatedType { | |||
public static void main(String[] argv) { | |||
method1(); | |||
method2(); | |||
} | |||
@SimpleAnnotation(id=1) | |||
public static void method1() { } | |||
public static void method2() { } | |||
} |
@@ -0,0 +1,5 @@ | |||
public aspect AnnotationAspect02 { | |||
before(): call(@SimpleAnnotation * *(..)) {} | |||
before(): call( * *(..)) {} | |||
} |
@@ -5,6 +5,7 @@ | |||
<mkdir dir="output"/> | |||
<javac destdir="output" debug="on" srcdir="." includes="SimpleAnnotation.java"/> | |||
<javac destdir="output" debug="on" srcdir="." includes="Annotation.java"/> | |||
<javac destdir="output" debug="on" srcdir="." includes="AnnotatedType.java"/> | |||
<zip file="testcode.jar" basedir="output" includes="**/*"/> | |||
<delete dir="output"/> | |||
</target> |
@@ -0,0 +1,50 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2004 IBM | |||
* 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: | |||
* Andy Clement - initial API and implementation | |||
*******************************************************************************/ | |||
package org.aspectj.systemtest.ajc150; | |||
import java.io.File; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.tools.ajc.CompilationResult; | |||
/** | |||
* Tests the use of Annotations in pointcuts | |||
*/ | |||
public class AnnotationPointcuts extends TestUtils { | |||
protected void setUp() throws Exception { | |||
super.setUp(); | |||
baseDir = new File("../tests/java5/annotations"); | |||
} | |||
// before(): call(@SimpleAnnotation * *(..)) { } | |||
// public void test001_usingAnnotationsInPointcuts() { | |||
// CompilationResult cR = binaryWeave("testcode.jar","AnnotationAspect02.aj",0,0); | |||
// System.err.println(cR.getStandardError()); | |||
// System.err.println(cR.getErrorMessages()); | |||
// System.err.println(cR.getInfoMessages()); | |||
// verifyWeavingMessagesOutput(cR,new String[]{}); | |||
//// assertTrue("Expected three message about ITDs not allowed on Annotations but got: #"+ | |||
//// cR.getErrorMessages().size()+": \n"+cR.getErrorMessages(), | |||
//// cR.getErrorMessages().size()==3); | |||
//// IMessage msg1_ctor = (IMessage)cR.getErrorMessages().get(0); | |||
//// IMessage msg2_method = (IMessage)cR.getErrorMessages().get(1); | |||
//// IMessage msg3_field = (IMessage)cR.getErrorMessages().get(2); | |||
//// assertTrue("Expected message about ITDCs on annotations not allowed, but got: \n"+msg1_ctor, | |||
//// msg1_ctor.toString().indexOf("can't make inter-type constructor declarations")!=-1); | |||
//// assertTrue("Expected message about ITDMs on annotations not allowed, but got: \n"+msg2_method, | |||
//// msg2_method.toString().indexOf("can't make inter-type method declarations")!=-1); | |||
//// assertTrue("Expected message about ITDFs on annotations not allowed, but got: \n"+msg3_field, | |||
//// msg3_field.toString().indexOf("can't make inter-type field declarations")!=-1); | |||
//// verifyWeavingMessagesOutput(cR,new String[]{}); | |||
// } | |||
} |
@@ -110,6 +110,14 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle | |||
return false; | |||
} | |||
public ResolvedTypeX[] getAnnotationTypes() { | |||
// The ctors don't allow annotations to be specified ... yet - but | |||
// that doesn't mean it is an error to call this method. | |||
// Normally the weaver will be working with subtypes of | |||
// this type - BcelField/BcelMethod | |||
return null; | |||
} | |||
public boolean isBridgeMethod() { | |||
return (modifiers & Constants.ACC_BRIDGE)!=0; | |||
} |
@@ -564,6 +564,10 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement { | |||
return delegate.hasAnnotation(ofType); | |||
} | |||
public ResolvedTypeX[] getAnnotationTypes() { | |||
return delegate.getAnnotationTypes(); | |||
} | |||
public boolean isAspect() { | |||
return delegate.isAspect(); | |||
} | |||
@@ -722,6 +726,7 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement { | |||
public abstract boolean isAnnotation(); | |||
public abstract boolean hasAnnotation(ResolvedTypeX ofType); | |||
public abstract ResolvedTypeX[] getAnnotationTypes(); | |||
public abstract ResolvedMember[] getDeclaredFields(); | |||
@@ -32,6 +32,8 @@ final class BcelField extends ResolvedMember { | |||
private Field field; | |||
private boolean isAjSynthetic; | |||
private boolean isSynthetic = false; | |||
private ResolvedTypeX[] resolvedAnnotations; | |||
private World world; | |||
BcelField(BcelObjectType declaringType, Field field) { | |||
super( | |||
@@ -41,7 +43,8 @@ final class BcelField extends ResolvedMember { | |||
field.getName(), | |||
field.getSignature()); | |||
this.field = field; | |||
unpackAttributes(declaringType.getResolvedTypeX().getWorld()); | |||
this.world = declaringType.getResolvedTypeX().getWorld(); | |||
unpackAttributes(world); | |||
checkedExceptions = TypeX.NONE; | |||
} | |||
@@ -84,4 +87,17 @@ final class BcelField extends ResolvedMember { | |||
} | |||
return false; | |||
} | |||
public ResolvedTypeX[] getAnnotationTypes() { | |||
if (resolvedAnnotations == null) { | |||
Annotation[] annotations = field.getAnnotations(); | |||
resolvedAnnotations = new ResolvedTypeX[annotations.length]; | |||
for (int i = 0; i < annotations.length; i++) { | |||
Annotation annotation = annotations[i]; | |||
ResolvedTypeX rtx = world.resolve(TypeX.forName(annotation.getTypeName())); | |||
resolvedAnnotations[i] = rtx; | |||
} | |||
} | |||
return resolvedAnnotations; | |||
} | |||
} |
@@ -37,6 +37,8 @@ final class BcelMethod extends ResolvedMember { | |||
private ShadowMunger associatedShadowMunger; | |||
private AjAttribute.EffectiveSignatureAttribute effectiveSignature; | |||
private AjAttribute.MethodDeclarationLineNumberAttribute declarationLineNumber; | |||
private ResolvedTypeX[] resolvedAnnotations; | |||
private World world; | |||
BcelMethod(BcelObjectType declaringType, Method method) { | |||
super( | |||
@@ -49,7 +51,8 @@ final class BcelMethod extends ResolvedMember { | |||
method.getName(), | |||
method.getSignature()); | |||
this.method = method; | |||
unpackAjAttributes(declaringType.getResolvedTypeX().getWorld()); | |||
this.world = declaringType.getResolvedTypeX().getWorld(); | |||
unpackAjAttributes(world); | |||
unpackJavaAttributes(); | |||
} | |||
@@ -146,4 +149,18 @@ final class BcelMethod extends ResolvedMember { | |||
} | |||
return false; | |||
} | |||
public ResolvedTypeX[] getAnnotationTypes() { | |||
if (resolvedAnnotations == null) { | |||
Annotation[] annotations = method.getAnnotations(); | |||
resolvedAnnotations = new ResolvedTypeX[annotations.length]; | |||
for (int i = 0; i < annotations.length; i++) { | |||
Annotation annotation = annotations[i]; | |||
ResolvedTypeX rtx = world.resolve(TypeX.forName(annotation.getTypeName())); | |||
resolvedAnnotations[i] = rtx; | |||
} | |||
} | |||
return resolvedAnnotations; | |||
} | |||
} |
@@ -47,6 +47,7 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName { | |||
private ResolvedTypeX superClass = null; | |||
private ResolvedMember[] fields = null; | |||
private ResolvedMember[] methods = null; | |||
private ResolvedTypeX[] resolvedAnnotations = null; | |||
// strangely non-lazy | |||
private ResolvedPointcutDefinition[] pointcuts = null; | |||
@@ -320,18 +321,7 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName { | |||
//if (lazyClassGen != null) lazyClassGen.print(); | |||
} | |||
// public Annotation[] getAnnotations() { | |||
// if (annotations == null) { | |||
// annotations = javaClass.getAnnotations(); | |||
//// This would be how to resolve annotations ... | |||
//// annotationsTypeXs = new ResolvedTypeX[annotations.length]; | |||
//// for (int i = 0; i < annotations.length; i++) { | |||
//// Annotation annotation = annotations[i]; | |||
//// getResolvedTypeX().getWorld().resolve(TypeX.forName(annotation.getTypeName())); | |||
//// } | |||
// } | |||
// return annotations; | |||
// } | |||
public boolean hasAnnotation(ResolvedTypeX ofType) { | |||
Annotation[] annotationsOnThisType = javaClass.getAnnotations(); | |||
@@ -341,6 +331,19 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName { | |||
} | |||
return false; | |||
} | |||
public ResolvedTypeX[] getAnnotationTypes() { | |||
if (resolvedAnnotations == null) { | |||
Annotation annotations[] = javaClass.getAnnotations(); | |||
resolvedAnnotations = new ResolvedTypeX[annotations.length]; | |||
for (int i = 0; i < annotations.length; i++) { | |||
Annotation annotation = annotations[i]; | |||
ResolvedTypeX rtx = getResolvedTypeX().getWorld().resolve(TypeX.forName(annotation.getTypeName())); | |||
resolvedAnnotations[i] = rtx; | |||
} | |||
} | |||
return resolvedAnnotations; | |||
} | |||
} | |||
@@ -21,13 +21,13 @@ import java.lang.reflect.Modifier; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.MessageUtil; | |||
import org.aspectj.util.FuzzyBoolean; | |||
import org.aspectj.weaver.ShadowMunger; | |||
import org.aspectj.weaver.BCException; | |||
import org.aspectj.weaver.ISourceContext; | |||
import org.aspectj.weaver.IntMap; | |||
import org.aspectj.weaver.ResolvedPointcutDefinition; | |||
import org.aspectj.weaver.ResolvedTypeX; | |||
import org.aspectj.weaver.Shadow; | |||
import org.aspectj.weaver.ShadowMunger; | |||
import org.aspectj.weaver.TypeX; | |||
import org.aspectj.weaver.WeaverMessages; | |||
import org.aspectj.weaver.ast.Test; |
@@ -77,7 +77,7 @@ public class WildAnnotationTypePattern extends AnnotationTypePattern { | |||
scope.getWorld().getMessageHandler().handleMessage(m); | |||
resolved = false; | |||
} | |||
return new ExactAnnotationTypePattern(et.getExactType()); | |||
return new ExactAnnotationTypePattern(et.getExactType().resolve(scope.getWorld())); | |||
} else { | |||
return this; | |||
} |
@@ -11,15 +11,14 @@ | |||
* ******************************************************************/ | |||
package org.aspectj.weaver.patterns; | |||
import java.util.List; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import junit.framework.TestCase; | |||
import org.aspectj.bridge.AbortException; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.IMessageHandler; | |||
import org.aspectj.bridge.MessageHandler; | |||
import org.aspectj.bridge.IMessage.Kind; | |||
import org.aspectj.weaver.BcweaverTests; | |||
import org.aspectj.weaver.ResolvedMember; | |||
@@ -186,5 +185,61 @@ public class AnnotationPatternMatchingTestCase extends TestCase { | |||
simpleAnnotationTP.matches(aField).alwaysTrue()); | |||
} | |||
public void testAnnotationTypeResolutionOnTypes() { | |||
ResolvedTypeX rtx = loadType("AnnotatedClass"); | |||
ResolvedTypeX[] types = rtx.getAnnotationTypes(); | |||
assertTrue("Did not expect null",types!=null); | |||
assertTrue("Expected 1 entry but got "+types.length,types.length==1); | |||
assertTrue("Should be 'p.SimpleAnnotation' but is "+types[0], | |||
types[0].equals(world.resolve("p.SimpleAnnotation"))); | |||
} | |||
public void testAnnotationTypeResolutionOnMethods() { | |||
ResolvedTypeX rtx = loadType("AnnotatedClass"); | |||
ResolvedMember aMethod = rtx.getDeclaredMethods()[1]; | |||
assertTrue("Haven't got the right method, I'm looking for 'm1()': "+aMethod.getName(), | |||
aMethod.getName().equals("m1")); | |||
ResolvedTypeX[] types = aMethod.getAnnotationTypes(); | |||
assertTrue("Did not expect null",types!=null); | |||
assertTrue("Expected 1 entry but got "+types.length,types.length==1); | |||
assertTrue("Should be 'p.SimpleAnnotation' but is "+types[0], | |||
types[0].equals(world.resolve("p.SimpleAnnotation"))); | |||
} | |||
public void testAnnotationTypeResolutionOnFields() { | |||
ResolvedTypeX rtx = loadType("AnnotatedClass"); | |||
ResolvedMember aField = rtx.getDeclaredFields()[0]; | |||
assertTrue("Haven't got the right field, I'm looking for 'i'"+aField.getName(), | |||
aField.getName().equals("i")); | |||
ResolvedTypeX[] types = aField.getAnnotationTypes(); | |||
assertTrue("Did not expect null",types!=null); | |||
assertTrue("Expected 1 entry but got "+types.length,types.length==1); | |||
assertTrue("Should be 'p.SimpleAnnotation' but is "+types[0], | |||
types[0].equals(world.resolve("p.SimpleAnnotation"))); | |||
} | |||
public void testWildPatternMatchingOnTypes() { | |||
ResolvedTypeX rtx = loadType("AnnotatedClass"); | |||
initAnnotationTypePatterns(); | |||
// Let's create something wild | |||
PatternParser p = new PatternParser("@Foo || @Boo"); | |||
AnnotationTypePattern ap = p.maybeParseAnnotationPattern(); | |||
ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
assertTrue("shouldnt match the type AnnotatedClass",ap.matches(rtx).alwaysFalse()); | |||
p = new PatternParser("@p.SimpleAnnotation || @Boo"); | |||
ap = p.maybeParseAnnotationPattern(); | |||
ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true); | |||
assertTrue("should match the type AnnotatedClass",ap.matches(rtx).alwaysTrue()); | |||
} | |||
} |
@@ -15,6 +15,8 @@ package org.aspectj.weaver.patterns; | |||
import junit.framework.TestCase; | |||
import org.aspectj.weaver.BcweaverTests; | |||
import org.aspectj.weaver.ResolvedTypeX; | |||
import org.aspectj.weaver.World; | |||
import org.aspectj.weaver.bcel.BcelShadow; | |||
import org.aspectj.weaver.bcel.BcelWorld; | |||
@@ -33,7 +35,7 @@ public class ParserTestCase extends TestCase { | |||
super(arg0); | |||
} | |||
World world = new BcelWorld(); | |||
World world = new BcelWorld(BcweaverTests.TESTDATA_PATH + "/testcode.jar"); | |||
public void testNamePatterns() { | |||
@@ -58,10 +60,23 @@ public class ParserTestCase extends TestCase { | |||
} catch (ParserException pe) { | |||
// good | |||
} | |||
} | |||
public void testParseWithAnnotation() { | |||
PatternParser parser = new PatternParser("execution(@p.SimpleAnnotation void Hello.*(..))"); | |||
KindedPointcut p = (KindedPointcut) parser.parsePointcut(); | |||
// XXX - needs finishing... | |||
// p.resolveBindings(makeSimpleScope(),new Bindings(3)); | |||
// System.err.println(p); | |||
// assertEquals(p.kind, BcelShadow.MethodExecution); | |||
// assertTrue(p.signature.getName().matches("foobar")); | |||
// p.signature.resolveBindings(makeSimpleScope(),new Bindings(3)); | |||
} | |||
public TestScope makeSimpleScope() { | |||
return new TestScope(new String[] {"int", "java.lang.String"}, new String[] {"a", "b"}, world); | |||
} | |||
} | |||