public void testCallsAndExecutionsOfStaticMethods() {
runTest("binding with static methods");
}
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // annotation binding with ITDs
+
+ public void testAnnotationBindingAndITDs1() {
+ runTest("simple binding annotation values where itd method is annotated");
+ }
+
+ public void testAnnotationBindingAndITDs2() {
+ runTest("simple binding annotation values where itd field is annotated");
+ }
+
+ public void testAnnotationBindingAndITDs3() {
+ runTest("simple binding annotation values where itd ctor is annotated");
+ }
+
+ public void testAnnotationBindingAndITDs4() {
+ runTest("simple binding annotation values where itd method is annotated via declare");
+ }
+
+ public void testAnnotationBindingAndITDs5() {
+ runTest("simple binding annotation values where itd field is annotated via declare");
+ }
+
+ public void testAnnotationBindingAndITDs6() {
+ runTest("simple binding annotation values where itd field is annotated multiple times via declare");
+ }
+
+ public void testAnnotationBindingAndITDs7() {
+ runTest("simple binding annotation values where itd ctor is annotated via declare");
+ }
+
}
\ No newline at end of file
// more implementation work needed before this test passes
public void testAnnotatedITDs() {
+ try {
runTest("annotated itds");
+ } finally {
+ System.err.println(ajc.getLastCompilationResult().getStandardError());
+ }
}
public void testAnnotatedITDsWithWrongAnnotationType() {
<ajc-test dir="java5/annotations/itds" vm="1.5" title="nasty annotation and itds test">
<compile files="AnnotationsAndITDs.aj" options="-1.5">
- <message kind="warning" line="25" text="execution(@SomeAnnotation ...)"/>
- <message kind="warning" line="28" text="execution(@SomeAnnotation ...)"/>
- <message kind="warning" line="52" text="execution(@SomeAnnotation ...)"/>
- <message kind="warning" line="53" text="execution(@SomeAnnotation ...)"/>
+ <!-- first two are ITCs, second two are ITCs annotated via declare @ctor, third is default ctor -->
<message kind="warning" line="17" text="execution(@SomeAnnotation ...new(..)"/>
<message kind="warning" line="20" text="execution(@SomeAnnotation ...new(..)"/>
<message kind="warning" line="45" text="execution(@SomeAnnotation ...new(..)"/>
<message kind="warning" line="46" text="execution(@SomeAnnotation ...new(..)"/>
+ <message kind="warning" line="180" text="execution(@SomeAnnotation ...new(..)"/>
+
+ <!-- first four are fields annotated via declare, last two are directly annotated ITDs -->
+ <message kind="warning" line="59" text="set(@SomeAnnotation...)"/>
+ <message kind="warning" line="60" text="set(@SomeAnnotation...)"/>
<message kind="warning" line="70" text="set(@SomeAnnotation...)"/>
<message kind="warning" line="71" text="set(@SomeAnnotation...)"/>
<message kind="warning" line="76" text="set(@SomeAnnotation...)"/>
<message kind="warning" line="77" text="set(@SomeAnnotation...)"/>
+
+ <!-- annotations added via declare -->
<message kind="warning" line="175" text="si(@SomeAnnotation...)"/>
<message kind="warning" line="180" text="si(@SomeAnnotation...)"/>
+
+ <message kind="warning" line="25" text="execution(@SomeAnnotation ...)"/>
+ <message kind="warning" line="28" text="execution(@SomeAnnotation ...)"/>
+ <message kind="warning" line="52" text="execution(@SomeAnnotation ...)"/>
+ <message kind="warning" line="53" text="execution(@SomeAnnotation ...)"/>
+ <!--message kind="warning" line="70" text="set(@SomeAnnotation...)"/>
+ <message kind="warning" line="71" text="set(@SomeAnnotation...)"/-->
</compile>
<run class="AnnotationsAndITDs">
- <stdout>
- <line text="@type System"/>
- <line text="hello AnnotationsAndITDs"/>
- <line text="goodbye String"/>
- <line text="x Object"/>
- <line text="y Integer"/>
+ <stderr>
+ <line text="@type java.lang.System (AnnotationsAndITDs.aj:0)"/>
+ <line text="hello AnnotationsAndITDs (AnnotationsAndITDs.aj:17)"/>
+ <line text="goodbye java.lang.String (AnnotationsAndITDs.aj:20)"/>
+ <line text="goodbye java.lang.String (AnnotationsAndITDs.aj:20)"/>
+ <line text="y java.lang.Integer (AnnotationsAndITDs.aj:28)"/>
+ <line text="d java.lang.Double (AnnotationsAndITDs.aj:70)"/>
+ <line text="f java.lang.Double (AnnotationsAndITDs.aj:71)"/>
+ <line text="@type java.lang.System (AnnotationsAndITDs.aj:0)"/>
+ <line text="@field ITDMe2 (AnnotationsAndITDs.aj:59)"/>
+ <line text="@field ITDMe2 (AnnotationsAndITDs.aj:60)"/>
+ <line text="@cons java.lang.String (AnnotationsAndITDs.aj:45)"/>
+ <line text="@field ITDMe2 (AnnotationsAndITDs.aj:59)"/>
+ <line text="@field ITDMe2 (AnnotationsAndITDs.aj:60)"/>
+ <line text="@cons java.lang.String (AnnotationsAndITDs.aj:46)"/>
+ <line text="@cons java.lang.String (AnnotationsAndITDs.aj:46)"/>
+ <line text="@method ITDMe2 (AnnotationsAndITDs.aj:53)"/>
+ <line text="@field ITDMe2 (AnnotationsAndITDs.aj:76)"/>
+ <line text="@field ITDMe2 (AnnotationsAndITDs.aj:77)"/>
+
+ <!--
<line text="method bar has 1 params, first param annotation is @ParamAnnotation"/>
- <line text="d Double"/>
- <line text="f Double"/>
- <line text="@type System"/>
- <line text="@cons String"/>
- <line text="@cons String"/>
- <line text="@method ITDMe2"/>
- <line text="@method ITDMe2"/>
- <line text="@field ITDMe2"/>
- <line text="@field ITDMe2"/>
- </stdout>
+ -->
+ </stderr>
</run>
</ajc-test>
<message kind="warning" line="8" text="annotated field"/>
<message kind="warning" line="10" text="annotated method"/>
<message kind="warning" line="12" text="annotated constructor"/>
+ <message kind="warning" line="12" text="annotated field"/>
</compile>
</ajc-test>
<compile files="DeathByAnnotations.aj" options="-1.5,-emacssym" xlintfile="ignoreTypeNotExposed.properties"/>
<run class="p.q.DeathByAnnotations"/>
</ajc-test>
+
+ <!-- ======================================================================================= -->
+ <!-- annotation binding with ITDs -->
+ <!-- ======================================================================================= -->
+
+ <ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd method is annotated">
+ <compile files="BindingWithAnnotatedItds1.aj" options="-1.5"/>
+ <run class="BindingWithAnnotatedItds1">
+ <stderr>
+ <line text="Found apple at jp execution(int A.m()) (BindingWithAnnotatedItds1.aj:8)"/>
+ </stderr>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd field is annotated">
+ <compile files="BindingWithAnnotatedItds2.aj" options="-1.5"/>
+ <run class="BindingWithAnnotatedItds2">
+ <stderr>
+ <line text="Found banana at jp set(int A.i) (BindingWithAnnotatedItds2.aj:16)"/>
+ <line text="Found apple at jp set(String A.j) (BindingWithAnnotatedItds2.aj:17)"/>
+ <line text="Found orange at jp set(int[] A.k) (BindingWithAnnotatedItds2.aj:18)"/>
+ </stderr>
+ </run>
+ </ajc-test>
+ <ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd ctor is annotated">
+ <compile files="BindingWithAnnotatedItds3.aj" options="-1.5"/>
+ <run class="BindingWithAnnotatedItds3">
+ <stderr>
+ <line text="Found pear at jp execution(A(String)) (BindingWithAnnotatedItds3.aj:8)"/>
+ <line text="Found orange at jp execution(A(int)) (BindingWithAnnotatedItds3.aj:10)"/>
+ <line text="Found tomato at jp execution(A(boolean)) (BindingWithAnnotatedItds3.aj:12)"/>
+ </stderr>
+ </run>
+ </ajc-test>
+
+ <!-- ======================================================================================= -->
+ <!-- declare annotation targetting ITDs -->
+ <!-- ======================================================================================= -->
+
+
+ <ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd method is annotated via declare">
+ <compile files="BindingWithDeclaredAnnotationItds1.aj" options="-1.5"/>
+ <run class="BindingWithDeclaredAnnotationItds1">
+ <stderr>
+ <line text="Found orange at jp call(int A.m()) (BindingWithDeclaredAnnotationItds1.aj:16)"/>
+ <line text="Found orange at jp execution(int A.m()) (BindingWithDeclaredAnnotationItds1.aj:8)"/>
+ <line text="Found banana at jp call(int A.n()) (BindingWithDeclaredAnnotationItds1.aj:17)"/>
+ <line text="Found banana at jp execution(int A.n()) (BindingWithDeclaredAnnotationItds1.aj:10)"/>
+ <line text="Found tomato at jp call(int A.o()) (BindingWithDeclaredAnnotationItds1.aj:18)"/>
+ <line text="Found tomato at jp execution(int A.o()) (BindingWithDeclaredAnnotationItds1.aj:12)"/>
+ </stderr>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd field is annotated via declare">
+ <compile files="BindingWithDeclaredAnnotationItds2.aj" options="-1.5"/>
+ <run class="BindingWithDeclaredAnnotationItds2">
+ <stderr>
+ <line text="Found orange at jp set(int A.i) (BindingWithDeclaredAnnotationItds2.aj:16)"/>
+ <line text="Found banana at jp set(String A.j) (BindingWithDeclaredAnnotationItds2.aj:17)"/>
+ <line text="Found apple at jp set(boolean[] A.k) (BindingWithDeclaredAnnotationItds2.aj:18)"/>
+ </stderr>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd field is annotated multiple times via declare">
+ <compile files="BindingWithDeclaredAnnotationItds3.aj" options="-1.5"/>
+ <run class="BindingWithDeclaredAnnotationItds3">
+ <stderr>
+ <line text="Found fruit orange at jp set(int A.i) (BindingWithDeclaredAnnotationItds3.aj:13)"/>
+ <line text="Found drink margarita at jp set(int A.i) (BindingWithDeclaredAnnotationItds3.aj:13)"/>
+ </stderr>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd ctor is annotated via declare">
+ <compile files="BindingWithDeclaredAnnotationItds4.aj" options="-1.5"/>
+ <run class="BindingWithDeclaredAnnotationItds4">
+ <stderr>
+ <line text="Found pear at jp execution(A(String)) (BindingWithDeclaredAnnotationItds4.aj:8)"/>
+ <line text="Found orange at jp execution(A(int)) (BindingWithDeclaredAnnotationItds4.aj:10)"/>
+ <line text="Found tomato at jp execution(A(boolean)) (BindingWithDeclaredAnnotationItds4.aj:12)"/>
+ </stderr>
+ </run>
+ </ajc-test>
- <!-- ============================================================== -->
+ <!-- ============================================================== -->
<ajc-test dir="options/aspectpath" title="dirs on aspectpath">
<compile files="MyAspect.aj" options="-d out"/>
public class NewFieldTypeMunger extends ResolvedTypeMunger {
public NewFieldTypeMunger(ResolvedMember signature, Set superMethodsCalled) {
super(Field, signature);
+ signature.setAnnotatedElsewhere(true);
this.setSuperMethodsCalled(superMethodsCalled);
}
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
import org.aspectj.bridge.ISourceLocation;
public String[] parameterNames = null;
protected TypeX[] checkedExceptions = TypeX.NONE;
+ private Set annotationTypes = null;
+ // Some members are 'created' to represent other things (for example ITDs). These
+ // members have their annotations stored elsewhere, and this flag indicates that is
+ // the case. It is up to the caller to work out where that is!
+ // Once determined the caller may choose to stash the annotations in this member...
+ private boolean isAnnotatedElsewhere = false; // this field is not serialized.
// these three fields hold the source location of this member
public boolean isAjSynthetic() {
return true;
}
+
+ public boolean hasAnnotations() {
+ return (annotationTypes==null);
+ }
public boolean hasAnnotation(TypeX ofType) {
// 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 false;
+ if (annotationTypes==null) return false;
+ return annotationTypes.contains(ofType);
}
public ResolvedTypeX[] getAnnotationTypes() {
// 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;
+ if (annotationTypes == null) return null;
+ return (ResolvedTypeX[])annotationTypes.toArray(new ResolvedTypeX[]{});
}
+ public void setAnnotationTypes(TypeX[] annotationtypes) {
+ if (annotationTypes == null) annotationTypes = new HashSet();
+ for (int i = 0; i < annotationtypes.length; i++) {
+ TypeX typeX = annotationtypes[i];
+ annotationTypes.add(typeX);
+ }
+ }
+
+ public void addAnnotation(AnnotationX annotation) {
+ // FIXME asc only allows for annotation types, not instances - should it?
+ if (annotationTypes == null) annotationTypes = new HashSet();
+ annotationTypes.add(annotation.getSignature());
+ }
+
public boolean isBridgeMethod() {
return (modifiers & Constants.ACC_BRIDGE)!=0;
}
public ResolvedMember resolve(World world) {
+ // FIXME asc guard with a check on resolution having happened !
+ if (annotationTypes!=null) {
+ Set r = new HashSet();
+ for (Iterator iter = annotationTypes.iterator(); iter.hasNext();) {
+ TypeX element = (TypeX) iter.next();
+ r.add(world.resolve(element));
+ }
+ annotationTypes = r;
+ }
return this;
}
public void setCheckedExceptions(TypeX[] checkedExceptions) {
this.checkedExceptions = checkedExceptions;
}
+
+ public void setAnnotatedElsewhere(boolean b) {
+ isAnnotatedElsewhere = b;
+ }
+
+ public boolean isAnnotatedElsewhere() {
+ return isAnnotatedElsewhere;
+ }
}
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.NewConstructorTypeMunger;
import org.aspectj.weaver.NewFieldTypeMunger;
+import org.aspectj.weaver.NewMethodTypeMunger;
import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedTypeMunger;
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.WeaverMetrics;
import org.aspectj.weaver.WeaverStateInfo;
private final Map addedSuperInitializers = new HashMap(); // Interface -> IfaceInitList
private List addedThisInitializers = new ArrayList(); // List<NewFieldMunger>
private List addedClassInitializers = new ArrayList(); // List<NewFieldMunger>
+
+ private Map mapToAnnotations = new HashMap();
private BcelShadow clinitShadow = null;
* Weave any declare @method/@ctor statements into the members of the supplied class
*/
private boolean weaveDeclareAtMethodCtor(LazyClassGen clazz) {
+ List reportedProblems = new ArrayList();
+
+ List allDecams = world.getDeclareAnnotationOnMethods();
+ if (allDecams.isEmpty()) return false; // nothing to do
boolean isChanged = false;
- List decaMs = getMatchingSubset(world.getDeclareAnnotationOnMethods(),clazz.getType());
+
+ // deal with ITDs
+ List itdMethodsCtors = getITDSubset(clazz,ResolvedTypeMunger.Method);
+ itdMethodsCtors.addAll(getITDSubset(clazz,ResolvedTypeMunger.Constructor));
+ if (!itdMethodsCtors.isEmpty()) {
+ // Can't use the subset called 'decaMs' as it won't be right for ITDs...
+ isChanged = weaveAtMethodOnITDSRepeatedly(allDecams,itdMethodsCtors,reportedProblems);
+ }
+
+ // deal with all the other methods...
List members = clazz.getMethodGens();
- if (!members.isEmpty() && !decaMs.isEmpty()) {
- // go through all the fields
+ List decaMs = getMatchingSubset(allDecams,clazz.getType());
+ if (decaMs.isEmpty()) return false; // nothing to do
+ if (!members.isEmpty()) {
for (int memberCounter = 0;memberCounter<members.size();memberCounter++) {
LazyMethodGen mg = (LazyMethodGen)members.get(memberCounter);
if (!mg.getName().startsWith(NameMangler.PREFIX)) {
+
// Single first pass
List worthRetrying = new ArrayList();
boolean modificationOccured = false;
- // go through all the declare @field statements
+
for (Iterator iter = decaMs.iterator(); iter.hasNext();) {
DeclareAnnotation decaM = (DeclareAnnotation) iter.next();
if (decaM.matches(mg.getMemberView(),world)) {
- if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,true)) continue; // skip this one...
+ if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) continue; // skip this one...
mg.addAnnotation(decaM.getAnnotationX());
- //System.err.println("Mloc ("+mg+") ="+mg.getSourceLocation());
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaM.getSourceLocation(),clazz.getName(),mg.getMethod());
isChanged = true;
modificationOccured = true;
for (Iterator iter = worthRetrying.iterator(); iter.hasNext();) {
DeclareAnnotation decaM = (DeclareAnnotation) iter.next();
if (decaM.matches(mg.getMemberView(),world)) {
- if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,false)) continue; // skip this one...
+ if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) continue; // skip this one...
mg.addAnnotation(decaM.getAnnotationX());
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaM.getSourceLocation(),clazz.getName(),mg.getMethod());
isChanged = true;
*/
private List getMatchingSubset(List declareAnnotations, ResolvedTypeX type) {
List subset = new ArrayList();
- //System.err.println("For type="+type+"\nPrior set: "+declareAnnotations);
for (Iterator iter = declareAnnotations.iterator(); iter.hasNext();) {
DeclareAnnotation da = (DeclareAnnotation) iter.next();
if (da.couldEverMatch(type)) {
subset.add(da);
}
}
- //System.err.println("After set: "+subset);
return subset;
}
+
+ /**
+ * Get a subset of all the type mungers defined on this aspect
+ */
+ private List getITDSubset(LazyClassGen clazz,ResolvedTypeMunger.Kind wantedKind) {
+ List subset = new ArrayList();
+ Collection c = clazz.getBcelObjectType().getTypeMungers();
+ for (Iterator iter = c.iterator();iter.hasNext();) {
+ BcelTypeMunger typeMunger = (BcelTypeMunger)iter.next();
+ if (typeMunger.getMunger().getKind()==wantedKind)
+ subset.add(typeMunger);
+ }
+ return subset;
+ }
+
+ public LazyMethodGen locateAnnotationHolderForFieldMunger(LazyClassGen clazz,BcelTypeMunger fieldMunger) {
+ NewFieldTypeMunger nftm = (NewFieldTypeMunger)fieldMunger.getMunger();
+ ResolvedMember lookingFor =AjcMemberMaker.interFieldInitializer(nftm.getSignature(),clazz.getType());
+ List meths = clazz.getMethodGens();
+ for (Iterator iter = meths.iterator(); iter.hasNext();) {
+ LazyMethodGen element = (LazyMethodGen) iter.next();
+ if (element.getName().equals(lookingFor.getName())) return element;
+ }
+ return null;
+ }
+
+ // FIXME asc refactor this to neaten it up
+ public LazyMethodGen locateAnnotationHolderForMethodCtorMunger(LazyClassGen clazz,BcelTypeMunger methodCtorMunger) {
+ if (methodCtorMunger.getMunger() instanceof NewMethodTypeMunger) {
+ NewMethodTypeMunger nftm = (NewMethodTypeMunger)methodCtorMunger.getMunger();
+ ResolvedMember lookingFor =AjcMemberMaker.interMethodBody(nftm.getSignature(),methodCtorMunger.getAspectType());
+ List meths = clazz.getMethodGens();
+ for (Iterator iter = meths.iterator(); iter.hasNext();) {
+ LazyMethodGen element = (LazyMethodGen) iter.next();
+ if (element.getName().equals(lookingFor.getName()) && element.getParameterSignature().equals(lookingFor.getParameterSignature())) return element;
+ }
+ return null;
+ } else if (methodCtorMunger.getMunger() instanceof NewConstructorTypeMunger) {
+ NewConstructorTypeMunger nftm = (NewConstructorTypeMunger)methodCtorMunger.getMunger();
+ ResolvedMember lookingFor =AjcMemberMaker.postIntroducedConstructor(methodCtorMunger.getAspectType(),nftm.getSignature().getDeclaringType(),nftm.getSignature().getParameterTypes());
+ List meths = clazz.getMethodGens();
+ for (Iterator iter = meths.iterator(); iter.hasNext();) {
+ LazyMethodGen element = (LazyMethodGen) iter.next();
+ if (element.getName().equals(lookingFor.getName()) && element.getParameterSignature().equals(lookingFor.getParameterSignature())) return element;
+ }
+ return null;
+ } else {
+ throw new RuntimeException("Not sure what this is: "+methodCtorMunger);
+ }
+ }
+
+ /**
+ * Applies some set of declare @field constructs (List<DeclareAnnotation>) to some bunch
+ * of ITDfields (List<BcelTypeMunger>. It will iterate over the fields repeatedly until
+ * everything has been applied.
+ *
+ */
+ private boolean weaveAtFieldRepeatedly(List decaFs, List itdFields,List reportedErrors) {
+ boolean isChanged = false;
+ for (Iterator iter = itdFields.iterator(); iter.hasNext();) {
+ BcelTypeMunger fieldMunger = (BcelTypeMunger) iter.next();
+ ResolvedMember itdIsActually = fieldMunger.getSignature();
+ List worthRetrying = new ArrayList();
+ boolean modificationOccured = false;
+
+ for (Iterator iter2 = decaFs.iterator(); iter2.hasNext();) {
+ DeclareAnnotation decaF = (DeclareAnnotation) iter2.next();
+
+ if (decaF.matches(itdIsActually,world)) {
+ LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz,fieldMunger);
+ if (doesAlreadyHaveAnnotation(annotationHolder,itdIsActually,decaF,reportedErrors)) continue; // skip this one...
+ annotationHolder.addAnnotation(decaF.getAnnotationX());
+ //FIXME asc you need to add relationships for these things
+ // AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]);
+ isChanged = true;
+ modificationOccured = true;
+
+ } else {
+ if (!decaF.isStarredAnnotationPattern())
+ worthRetrying.add(decaF); // an annotation is specified that might be put on by a subsequent decaf
+ }
+ }
+
+ while (!worthRetrying.isEmpty() && modificationOccured) {
+ modificationOccured = false;
+ List forRemoval = new ArrayList();
+ for (Iterator iter2 = worthRetrying.iterator(); iter.hasNext();) {
+ DeclareAnnotation decaF = (DeclareAnnotation) iter2.next();
+ if (decaF.matches(itdIsActually,world)) {
+ LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz,fieldMunger);
+ if (doesAlreadyHaveAnnotation(annotationHolder,itdIsActually,decaF,reportedErrors)) continue; // skip this one...
+ annotationHolder.addAnnotation(decaF.getAnnotationX());
+ //FIXME asc you need to add relationships for these things
+ // AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]);
+ isChanged = true;
+ modificationOccured = true;
+ forRemoval.add(decaF);
+ }
+ worthRetrying.removeAll(forRemoval);
+ }
+ }
+ }
+ return isChanged;
+ }
+
+
+ /**
+ * Applies some set of declare @method/@ctor constructs (List<DeclareAnnotation>) to some bunch
+ * of ITDmembers (List<BcelTypeMunger>. It will iterate over the fields repeatedly until
+ * everything has been applied.
+ */
+ private boolean weaveAtMethodOnITDSRepeatedly(List decaMCs, List itdMethodsCtors,List reportedErrors) {
+ boolean isChanged = false;
+ for (Iterator iter = itdMethodsCtors.iterator(); iter.hasNext();) {
+ BcelTypeMunger methodctorMunger = (BcelTypeMunger) iter.next();
+ ResolvedMember itdIsActually = methodctorMunger.getSignature();
+ List worthRetrying = new ArrayList();
+ boolean modificationOccured = false;
+
+ for (Iterator iter2 = decaMCs.iterator(); iter2.hasNext();) {
+ DeclareAnnotation decaMC = (DeclareAnnotation) iter2.next();
+
+ if (decaMC.matches(itdIsActually,world)) {
+ LazyMethodGen annotationHolder = locateAnnotationHolderForMethodCtorMunger(clazz,methodctorMunger);
+ if (doesAlreadyHaveAnnotation(annotationHolder,itdIsActually,decaMC,reportedErrors)) continue; // skip this one...
+ annotationHolder.addAnnotation(decaMC.getAnnotationX());
+ itdIsActually.addAnnotation(decaMC.getAnnotationX());
+ isChanged=true;
+ //FIXME asc you need to add relationships for these things
+ // AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]);
+ isChanged = true;
+ modificationOccured = true;
+
+ } else {
+ if (!decaMC.isStarredAnnotationPattern())
+ worthRetrying.add(decaMC); // an annotation is specified that might be put on by a subsequent decaf
+ }
+ }
+
+ while (!worthRetrying.isEmpty() && modificationOccured) {
+ modificationOccured = false;
+ List forRemoval = new ArrayList();
+ for (Iterator iter2 = worthRetrying.iterator(); iter.hasNext();) {
+ DeclareAnnotation decaF = (DeclareAnnotation) iter2.next();
+ if (decaF.matches(itdIsActually,world)) {
+ LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz,methodctorMunger);
+ if (doesAlreadyHaveAnnotation(annotationHolder,itdIsActually,decaF,reportedErrors)) continue; // skip this one...
+ annotationHolder.addAnnotation(decaF.getAnnotationX());
+ //FIXME asc you need to add relationships for these things
+ // AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]);
+ isChanged = true;
+ modificationOccured = true;
+ forRemoval.add(decaF);
+ }
+ worthRetrying.removeAll(forRemoval);
+ }
+ }
+ }
+ return isChanged;
+ }
+
+
/**
* Weave any declare @field statements into the fields of the supplied class
+ *
+ * Interesting case relating to public ITDd fields. The annotations are really stored against
+ * the interfieldinit method in the aspect, but the public field is placed in the target
+ * type and then is processed in the 2nd pass over fields that occurs. I think it would be
+ * more expensive to avoid putting the annotation on that inserted public field than just to
+ * have it put there as well as on the interfieldinit method.
*/
private boolean weaveDeclareAtField(LazyClassGen clazz) {
// decafs and check that to see if an error needs to be reported - this
// would be expensive so lets skip it for now
- List decaFs = getMatchingSubset(world.getDeclareAnnotationOnFields(),clazz.getType());
+ List reportedProblems = new ArrayList();
+
+ List allDecafs = world.getDeclareAnnotationOnFields();
+ if (allDecafs.isEmpty()) return false; // nothing to do
+
+
boolean isChanged = false;
+ List itdFields = getITDSubset(clazz,ResolvedTypeMunger.Field);
+ if (itdFields!=null) {
+ isChanged = weaveAtFieldRepeatedly(allDecafs,itdFields,reportedProblems);
+ }
+
+ List decaFs = getMatchingSubset(allDecafs,clazz.getType());
+ if (decaFs.isEmpty()) return false; // nothing more to do
Field[] fields = clazz.getFieldGens();
- if (fields!=null && !decaFs.isEmpty()) {
- // go through all the fields
+ if (fields!=null) {
+
for (int fieldCounter = 0;fieldCounter<fields.length;fieldCounter++) {
BcelField aBcelField = new BcelField(clazz.getBcelObjectType(),fields[fieldCounter]);
- if (!aBcelField.getName().startsWith(NameMangler.PREFIX)) {
+ if (!aBcelField.getName().startsWith(NameMangler.PREFIX)) {
// Single first pass
List worthRetrying = new ArrayList();
boolean modificationOccured = false;
for (Iterator iter = decaFs.iterator(); iter.hasNext();) {
DeclareAnnotation decaF = (DeclareAnnotation) iter.next();
if (decaF.matches(aBcelField,world)) {
- if (doesAlreadyHaveAnnotation(aBcelField,decaF,true)) continue; // skip this one...
+ if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)) continue; // skip this one...
aBcelField.addAnnotation(decaF.getAnnotationX());
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]);
isChanged = true;
for (Iterator iter = worthRetrying.iterator(); iter.hasNext();) {
DeclareAnnotation decaF = (DeclareAnnotation) iter.next();
if (decaF.matches(aBcelField,world)) {
- if (doesAlreadyHaveAnnotation(aBcelField,decaF,false)) continue; // skip this one...
+ if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)) continue; // skip this one...
aBcelField.addAnnotation(decaF.getAnnotationX());
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]);
isChanged = true;
* Check if a resolved member (field/method/ctor) already has an annotation, if it
* does then put out a warning and return true
*/
- private boolean doesAlreadyHaveAnnotation(ResolvedMember rm,DeclareAnnotation deca,boolean reportProblems) {
+ private boolean doesAlreadyHaveAnnotation(ResolvedMember rm,DeclareAnnotation deca,List reportedProblems) {
if (rm.hasAnnotation(deca.getAnnotationTypeX())) {
- if (reportProblems) {
- world.getLint().elementAlreadyAnnotated.signal(
- new String[]{rm.toString(),deca.getAnnotationTypeX().toString()},
- rm.getSourceLocation(),new ISourceLocation[]{deca.getSourceLocation()});
+ if (world.getLint().elementAlreadyAnnotated.isEnabled()) {
+ Integer uniqueID = new Integer(rm.hashCode()*deca.hashCode());
+ if (!reportedProblems.contains(uniqueID)) {
+ reportedProblems.add(uniqueID);
+ world.getLint().elementAlreadyAnnotated.signal(
+ new String[]{rm.toString(),deca.getAnnotationTypeX().toString()},
+ rm.getSourceLocation(),new ISourceLocation[]{deca.getSourceLocation()});
+ }
}
- return true;
+ return true;
}
return false;
}
+ private boolean doesAlreadyHaveAnnotation(LazyMethodGen rm,ResolvedMember itdfieldsig,DeclareAnnotation deca,List reportedProblems) {
+ if (rm.hasAnnotation(deca.getAnnotationTypeX())) {
+ if (world.getLint().elementAlreadyAnnotated.isEnabled()) {
+ Integer uniqueID = new Integer(rm.hashCode()*deca.hashCode());
+ if (!reportedProblems.contains(uniqueID)) {
+ reportedProblems.add(uniqueID);
+ reportedProblems.add(new Integer(itdfieldsig.hashCode()*deca.hashCode()));
+ world.getLint().elementAlreadyAnnotated.signal(
+ new String[]{rm.toString(),deca.getAnnotationTypeX().toString()},
+ rm.getSourceLocation(),new ISourceLocation[]{deca.getSourceLocation()});
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
private Set findAspectsForMungers(LazyMethodGen mg) {
Set aspectsAffectingType = new HashSet();
for (Iterator iter = mg.matchedShadows.iterator(); iter.hasNext();) {
if (effective == null) {
enclosingShadow = BcelShadow.makeMethodExecution(world, mg, !canMatchBodyShadows);
} else if (effective.isWeaveBody()) {
- enclosingShadow =
- BcelShadow.makeShadowForMethod(
- world,
- mg,
- effective.getShadowKind(),
- effective.getEffectiveSignature());
+ ResolvedMember rm = effective.getEffectiveSignature();
+
+ // Annotations for things with effective signatures are never stored in the effective
+ // signature itself - we have to hunt for them. Storing them in the effective signature
+ // would mean keeping two sets up to date (no way!!)
+
+ fixAnnotationsForResolvedMember(rm,mg.getMemberView());
+
+ enclosingShadow =
+ BcelShadow.makeShadowForMethod(world,mg,effective.getShadowKind(),rm);
} else {
return false;
}
match(mg, h, enclosingShadow, shadowAccumulator);
}
}
- if (canMatch(enclosingShadow.getKind())) {
+ // FIXME asc change from string match if we can, rather brittle. this check actually prevents field-exec jps
+ if (canMatch(enclosingShadow.getKind()) && !mg.getName().startsWith("ajc$interFieldInit")) {
if (match(enclosingShadow, shadowAccumulator)) {
enclosingShadow.init();
}
match(BcelShadow.makeFieldGet(world, mg, ih, enclosingShadow), shadowAccumulator);
}
}
+
+ /**
+ * For a given resolvedmember, this will discover the real annotations for it.
+ * <b>Should only be used when the resolvedmember is the contents of an effective signature
+ * attribute, as thats the only time when the annotations aren't stored directly in the
+ * resolvedMember</b>
+ * @param rm the sig we want it to pretend to be 'int A.m()' or somesuch ITD like thing
+ * @param declaredSig the real sig 'blah.ajc$xxx'
+ */
+ private void fixAnnotationsForResolvedMember(ResolvedMember rm,ResolvedMember declaredSig) {
+ try {
+ TypeX memberHostType = declaredSig.getDeclaringType();
+ ResolvedTypeX[] annotations = (ResolvedTypeX[])mapToAnnotations.get(rm);
+ String methodName = declaredSig.getName();
+ // FIXME asc shouldnt really rely on string names !
+ if (annotations == null) {
+ if (rm.getKind()==Member.FIELD) {
+ if (methodName.startsWith("ajc$inlineAccessField")) {
+ ResolvedMember resolvedDooberry = world.resolve(rm);
+ annotations = resolvedDooberry.getAnnotationTypes();
+ } else {
+ ResolvedMember realthing = AjcMemberMaker.interFieldInitializer(rm,memberHostType);
+ ResolvedMember resolvedDooberry = world.resolve(realthing);
+ annotations = resolvedDooberry.getAnnotationTypes();
+ }
+ } else if (rm.getKind()==Member.METHOD && !rm.isAbstract()) {
+ if (methodName.startsWith("ajc$inlineAccessMethod")) {
+ ResolvedMember resolvedDooberry = world.resolve(declaredSig);
+ annotations = resolvedDooberry.getAnnotationTypes();
+ } else {
+ ResolvedMember realthing = AjcMemberMaker.interMethodBody(rm,memberHostType);
+ ResolvedMember resolvedDooberry = world.resolve(realthing);
+ annotations = resolvedDooberry.getAnnotationTypes();
+ }
+ } else if (rm.getKind()==Member.CONSTRUCTOR) {
+ ResolvedMember realThing = AjcMemberMaker.postIntroducedConstructor(memberHostType.resolve(world),rm.getDeclaringType(),rm.getParameterTypes());
+ ResolvedMember resolvedDooberry = world.resolve(realThing);
+ annotations = resolvedDooberry.getAnnotationTypes();
+ }
+ if (annotations == null)
+ annotations = new ResolvedTypeX[0];
+ mapToAnnotations.put(rm,annotations);
+ }
+ rm.setAnnotationTypes(annotations);
+ } catch (Throwable t) {
+ //FIXME asc remove this catch after more testing has confirmed the above stuff is OK
+ throw new RuntimeException("Unexpectedly went bang when searching for annotations on "+rm,t);
+ }
+ }
+
private void matchInvokeInstruction(LazyMethodGen mg,
InstructionHandle ih,
if (effectiveSig == null) return;
//System.err.println("call to inter-type member: " + effectiveSig);
if (effectiveSig.isWeaveBody()) return;
- if (canMatch(effectiveSig.getShadowKind()))
+
+
+ ResolvedMember rm = effectiveSig.getEffectiveSignature();
+
+ fixAnnotationsForResolvedMember(rm,declaredSig); // abracadabra
+
+ if (canMatch(effectiveSig.getShadowKind()))
match(BcelShadow.makeShadowForMethodCall(world, mg, ih, enclosingShadow,
- effectiveSig.getShadowKind(), effectiveSig.getEffectiveSignature()),
- shadowAccumulator);
+ effectiveSig.getShadowKind(), rm), shadowAccumulator);
}
} else {
if (canMatch(Shadow.MethodCall))
import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.NewConstructorTypeMunger;
+import org.aspectj.weaver.NewFieldTypeMunger;
+import org.aspectj.weaver.NewMethodTypeMunger;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.Shadow;
thisAnnotationVars = new HashMap();
// populate..
}
+
public void initializeTargetAnnotationVars() {
if (targetAnnotationVars != null) return;
if (getKind().isTargetSameAsThis()) {
// what the full set of annotations could be (due to static/dynamic type differences...)
}
}
+
public void initializeKindedAnnotationVars() {
if (kindedAnnotationVars != null) return;
kindedAnnotationVars = new HashMap();
// Then create one BcelVar entry in the map for each annotation, keyed by
// annotation type (TypeX).
- // FIXME asc Refactor these once all shadow kinds added - there is lots of commonality
+ // FIXME asc Refactor this code, there is duplication
ResolvedTypeX[] annotations = null;
- TypeX relevantType = null;
+ ResolvedMember itdMember =null;
+ Member relevantMember = getSignature();
+ TypeX relevantType = null;
+ TypeX aspect = null;
if (getKind() == Shadow.StaticInitialization) {
relevantType = getSignature().getDeclaringType();
annotations = relevantType.resolve(world).getAnnotationTypes();
- }
- if (getKind() == Shadow.ExceptionHandler) {
- relevantType = getSignature().getParameterTypes()[0];
- annotations = relevantType.resolve(world).getAnnotationTypes();
- }
- if (getKind() == Shadow.MethodCall || getKind() == Shadow.ConstructorCall) {
+
+ } else if (getKind() == Shadow.MethodCall || getKind() == Shadow.ConstructorCall) {
relevantType = getSignature().getDeclaringType();
- ResolvedMember rm[] = relevantType.getDeclaredMethods(world);
- ResolvedMember found = null;
- String searchString = getSignature().getName()+getSignature().getParameterSignature();
- for (int i = 0; i < rm.length && found==null; i++) {
- ResolvedMember member = rm[i];
- if ((member.getName()+member.getParameterSignature()).equals(searchString)) {
- found = member;
+ relevantMember = findMethod2(relevantType.getDeclaredMethods(world),getSignature());
+
+ if (relevantMember == null) {
+ // check the ITD'd dooberries
+ List mungers = relevantType.resolve(world).getInterTypeMungers();
+ for (Iterator iter = mungers.iterator(); iter.hasNext();) {
+ BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next();
+ if (typeMunger.getMunger() instanceof NewMethodTypeMunger ||
+ typeMunger.getMunger() instanceof NewConstructorTypeMunger) {
+ ResolvedMember fakerm = typeMunger.getSignature();
+ //if (fakerm.hasAnnotations())
+
+ ResolvedMember ajcMethod = (getSignature().getKind()==ResolvedMember.CONSTRUCTOR?
+ AjcMemberMaker.postIntroducedConstructor(typeMunger.getAspectType(),fakerm.getDeclaringType(),fakerm.getParameterTypes()):
+ AjcMemberMaker.interMethodBody(fakerm,typeMunger.getAspectType()));
+ ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod);
+ if (fakerm.getName().equals(getSignature().getName()) &&
+ fakerm.getParameterSignature().equals(getSignature().getParameterSignature())) {
+ relevantType = typeMunger.getAspectType();
+ relevantMember = rmm;
+ }
+ }
}
}
- annotations = found.getAnnotationTypes();
- }
- if (getKind() == Shadow.MethodExecution || getKind() == Shadow.ConstructorExecution ||
- getKind() == Shadow.AdviceExecution) {
+ annotations = relevantMember.getAnnotationTypes();
+
+ } else if (getKind() == Shadow.FieldSet || getKind() == Shadow.FieldGet) {
relevantType = getSignature().getDeclaringType();
- ResolvedMember rm[] = relevantType.getDeclaredMethods(world);
- ResolvedMember found = null;
- String searchString = getSignature().getName()+getSignature().getParameterSignature();
- for (int i = 0; i < rm.length && found==null; i++) {
- ResolvedMember member = rm[i];
- if ((member.getName()+member.getParameterSignature()).equals(searchString)) {
- found = member;
- }
+ relevantMember = findField(relevantType.getDeclaredFields(world),getSignature());
+
+ if (relevantMember==null) {
+ // check the ITD'd dooberries
+ List mungers = relevantType.resolve(world).getInterTypeMungers();
+ for (Iterator iter = mungers.iterator(); iter.hasNext();) {
+ BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next();
+ if (typeMunger.getMunger() instanceof NewFieldTypeMunger) {
+ ResolvedMember fakerm = typeMunger.getSignature();
+ //if (fakerm.hasAnnotations())
+ ResolvedMember ajcMethod = AjcMemberMaker.interFieldInitializer(fakerm,typeMunger.getAspectType());
+ ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod);
+ if (fakerm.equals(getSignature())) {
+ relevantType = typeMunger.getAspectType();
+ relevantMember = rmm;
+ }
+ }
+ }
}
- annotations = found.getAnnotationTypes();
- }
- if (getKind() == Shadow.PreInitialization || getKind() == Shadow.Initialization) {
+ annotations = relevantMember.getAnnotationTypes();
+
+ } else if (getKind() == Shadow.MethodExecution || getKind() == Shadow.ConstructorExecution ||
+ getKind() == Shadow.AdviceExecution) {
relevantType = getSignature().getDeclaringType();
ResolvedMember rm[] = relevantType.getDeclaredMethods(world);
- ResolvedMember found = null;
- String searchString = getSignature().getName()+getSignature().getParameterSignature();
- for (int i = 0; i < rm.length && found==null; i++) {
- ResolvedMember member = rm[i];
- if ((member.getName()+member.getParameterSignature()).equals(searchString)) {
- found = member;
- }
- }
- annotations = found.getAnnotationTypes();
- }
- if (getKind() == Shadow.FieldSet) {
- relevantType = getSignature().getDeclaringType();
- ResolvedMember rm[] = relevantType.getDeclaredFields(world);
- ResolvedMember found = null;
- for (int i = 0; i < rm.length && found==null; i++) {
- ResolvedMember member = rm[i];
- if ( member.getName().equals(getSignature().getName()) &&
- member.getType().equals(getSignature().getType())) {
- found = member;
+ relevantMember = findMethod2(relevantType.getDeclaredMethods(world),getSignature());
+
+ if (relevantMember == null) {
+ // check the ITD'd dooberries
+ List mungers = relevantType.resolve(world).getInterTypeMungers();
+ for (Iterator iter = mungers.iterator(); iter.hasNext();) {
+ BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next();
+ if (typeMunger.getMunger() instanceof NewMethodTypeMunger ||
+ typeMunger.getMunger() instanceof NewConstructorTypeMunger) {
+ ResolvedMember fakerm = typeMunger.getSignature();
+ //if (fakerm.hasAnnotations())
+
+ ResolvedMember ajcMethod = (getSignature().getKind()==ResolvedMember.CONSTRUCTOR?
+ AjcMemberMaker.postIntroducedConstructor(typeMunger.getAspectType(),fakerm.getDeclaringType(),fakerm.getParameterTypes()):
+ AjcMemberMaker.interMethodBody(fakerm,typeMunger.getAspectType()));
+ ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod);
+ if (fakerm.getName().equals(getSignature().getName()) &&
+ fakerm.getParameterSignature().equals(getSignature().getParameterSignature())) {
+ relevantType = typeMunger.getAspectType();
+ relevantMember = rmm;
+ }
+ }
}
}
- annotations = found.getAnnotationTypes();
- }
- if (getKind() == Shadow.FieldGet) {
+ annotations = relevantMember.getAnnotationTypes();
+
+ } else if (getKind() == Shadow.ExceptionHandler) {
+ relevantType = getSignature().getParameterTypes()[0];
+ annotations = relevantType.resolve(world).getAnnotationTypes();
+
+ } else if (getKind() == Shadow.PreInitialization || getKind() == Shadow.Initialization) {
relevantType = getSignature().getDeclaringType();
- ResolvedMember rm[] = relevantType.getDeclaredFields(world);
- ResolvedMember found = null;
- for (int i = 0; i < rm.length && found==null; i++) {
- ResolvedMember member = rm[i];
- if ( member.getName().equals(getSignature().getName()) &&
- member.getType().equals(getSignature().getType())) {
- found = member;
- }
- }
+ ResolvedMember found = findMethod2(relevantType.getDeclaredMethods(world),getSignature());
annotations = found.getAnnotationTypes();
}
if (annotations == null) {
// We can't have recognized the shadow - should blow up now to be on the safe side
- throw new BCException("Didn't recognize shadow: "+getKind());
+ throw new BCException("Couldn't discover annotations for shadow: "+getKind());
}
for (int i = 0; i < annotations.length; i++) {
ResolvedTypeX aTX = annotations[i];
- kindedAnnotationVars.put(aTX,
- new KindedAnnotationAccessVar(getKind(),aTX.resolve(world),relevantType,getSignature()));
+ KindedAnnotationAccessVar kaav = new KindedAnnotationAccessVar(getKind(),aTX.resolve(world),relevantType,relevantMember);
+ kindedAnnotationVars.put(aTX,kaav);
}
-
-
-
}
- public void initializeWithinAnnotationVars() {
+
+//FIXME asc whats the real diff between this one and the version in findMethod()?
+ ResolvedMember findMethod2(ResolvedMember rm[], Member sig) {
+ ResolvedMember found = null;
+ // String searchString = getSignature().getName()+getSignature().getParameterSignature();
+ for (int i = 0; i < rm.length && found==null; i++) {
+ ResolvedMember member = rm[i];
+ if (member.getName().equals(sig.getName()) && member.getParameterSignature().equals(sig.getParameterSignature()))
+ found = member;
+ }
+ return found;
+ }
+
+ private ResolvedMember findMethod(ResolvedTypeX aspectType, ResolvedMember ajcMethod) {
+ ResolvedMember decMethods[] = aspectType.getDeclaredMethods();
+ for (int i = 0; i < decMethods.length; i++) {
+ ResolvedMember member = decMethods[i];
+ if (member.equals(ajcMethod)) return member;
+ }
+ return null;
+ }
+
+
+
+ private ResolvedMember findField(ResolvedMember[] members,Member lookingFor) {
+ for (int i = 0; i < members.length; i++) {
+ ResolvedMember member = members[i];
+ if ( member.getName().equals(getSignature().getName()) &&
+ member.getType().equals(getSignature().getType())) {
+ return member;
+ }
+ }
+ return null;
+ }
+
+
+ public void initializeWithinAnnotationVars() {
if (withinAnnotationVars != null) return;
withinAnnotationVars = new HashMap();
boolean didSomething = false;
if (decA.matches(onType)) {
- //FIXME asc CRITICAL this should be guarded by the 'already has annotation' check below but isn't since the compiler is producing classfiles with deca affected things in...
+ //FIXME asc important this should be guarded by the 'already has annotation' check below but isn't since the compiler is producing classfiles with deca affected things in...
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decA.getSourceLocation(),onType.getSourceLocation());
if (onType.hasAnnotation(decA.getAnnotationX().getSignature())) {
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.Synthetic;
+import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.apache.bcel.generic.BranchHandle;
import org.aspectj.apache.bcel.generic.BranchInstruction;
import org.aspectj.apache.bcel.generic.CPInstruction;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.WeaverMessages;
private String[] declaredExceptions;
private InstructionList body; // leaving null for abstracts
private Attribute[] attributes;
- private AnnotationGen[] annotations;
+ // private AnnotationGen[] annotations;
/* private */ final LazyClassGen enclosingClass;
private final BcelMethod memberView;
int highestLineNumber = 0;
public void addAnnotation(AnnotationX ax) {
initialize();
-// if (!hasAnnotation(TypeX.forSignature(a.getTypeSignature()))) {
- AnnotationGen ag = new AnnotationGen(ax.getBcelAnnotation(),enclosingClass.getConstantPoolGen(),true);
- AnnotationGen[] newAnnotations = new AnnotationGen[annotations.length+1];
- System.arraycopy(annotations,0,newAnnotations,0,annotations.length);
- newAnnotations[annotations.length]=ag;
- annotations = newAnnotations;
- // FIXME asc does this mean we are managing two levels of annotations again?
- // one here and one in the memberView??!?
- memberView.addAnnotation(ax);
+ if (memberView==null) {
+ System.err.println("REPORT THIS! 01: Lost annotation: "+ax+" cant be put onto "+this);
+ return;
+ }
+ memberView.addAnnotation(ax);
}
-
+
+
+ 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;
+ }
+ return memberView.hasAnnotation(annotationTypeX);
+ }
+
private void initialize() {
- if (returnType != null) return;
+ if (returnType != null) return;
//System.err.println("initializing: " + getName() + ", " + enclosingClass.getName() + ", " + returnType + ", " + savedMethod);
this.declaredExceptions = gen.getExceptions();
this.attributes = gen.getAttributes();
- this.annotations = gen.getAnnotations();
+ //this.annotations = gen.getAnnotations();
this.maxLocals = gen.getMaxLocals();
// this.returnType = BcelWorld.makeBcelType(memberView.getReturnType());
gen.addAttribute(attributes[i]);
}
- if (annotations!=null) {
- for (int i = 0, len = annotations.length; i < len; i++) {
- gen.addAnnotation(annotations[i]);
+// We don't manage our own set of annotations...
+// if (annotations!=null) {
+// for (int i = 0, len = annotations.length; i < len; i++) {
+// gen.addAnnotation(annotations[i]);
+// }
+// }
+
+ // work with the annotations from the memberView rather
+ // than any set we know about. This assumes we only work with
+ // annotations on LazyMethodGens that represent real members.
+ if (memberView!=null && memberView.getAnnotations()!=null && memberView.getAnnotations().length!=0) {
+ AnnotationX[] ans = memberView.getAnnotations();
+ for (int i = 0, len = ans.length; i < len; i++) {
+ Annotation a= ans[i].getBcelAnnotation();
+ gen.addAnnotation(new AnnotationGen(a,gen.getConstantPool(),true));
}
}
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import org.aspectj.bridge.IMessage;
-import org.aspectj.bridge.MessageUtil;
import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.AnnotatedElement;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.NewFieldTypeMunger;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.ast.Literal;
import org.aspectj.weaver.ast.Test;
import org.aspectj.weaver.ast.Var;
+import org.aspectj.weaver.bcel.BcelTypeMunger;
/**
* @annotation(@Foo) or @annotation(foo)
toMatchAgainst = rMember.getParameterTypes()[0].resolve(shadow.getIWorld());
} else {
toMatchAgainst = rMember;
+ // FIXME asc I'd like to get rid of this bit of logic altogether, shame ITD fields don't have an effective sig attribute
+ // FIXME asc perf cache the result of discovering the member that contains the real annotations
+ if (rMember.isAnnotatedElsewhere()) {
+ if (kind==Shadow.FieldGet || kind==Shadow.FieldSet) {
+ List mungers = rMember.getDeclaringType().resolve(shadow.getIWorld()).getInterTypeMungers(); // FIXME asc should include supers with getInterTypeMungersIncludingSupers?
+ for (Iterator iter = mungers.iterator(); iter.hasNext();) {
+ BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next();
+ if (typeMunger.getMunger() instanceof NewFieldTypeMunger) {
+ ResolvedMember fakerm = typeMunger.getSignature();
+ if (fakerm.equals(member)) {
+ ResolvedMember ajcMethod = AjcMemberMaker.interFieldInitializer(fakerm,typeMunger.getAspectType());
+ ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod);
+ toMatchAgainst = rmm;
+ }
+ }
+ }
+ }
+ }
}
annotationTypePattern.resolve(shadow.getIWorld());
return annotationTypePattern.matches(toMatchAgainst);
}
+ private ResolvedMember findMethod(ResolvedTypeX aspectType, ResolvedMember ajcMethod) {
+ ResolvedMember decMethods[] = aspectType.getDeclaredMethods();
+ for (int i = 0; i < decMethods.length; i++) {
+ ResolvedMember member = decMethods[i];
+ if (member.equals(ajcMethod)) return member;
+ }
+ return null;
+ }
+
/* (non-Javadoc)
* @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings)
*/
protected Test findResidueInternal(Shadow shadow, ExposedState state) {
- if (shadow.getKind()!=Shadow.MethodCall &&
- shadow.getKind()!=Shadow.ConstructorCall &&
- shadow.getKind()!=Shadow.ConstructorExecution &&
- shadow.getKind()!=Shadow.MethodExecution &&
- shadow.getKind()!=Shadow.FieldSet &&
- shadow.getKind()!=Shadow.FieldGet &&
- shadow.getKind()!=Shadow.StaticInitialization &&
- shadow.getKind()!=Shadow.PreInitialization &&
- shadow.getKind()!=Shadow.AdviceExecution &&
- shadow.getKind()!=Shadow.Initialization &&
- shadow.getKind()!=Shadow.ExceptionHandler
- ) {
- IMessage lim = MessageUtil.error("Binding not supported in @pcds (1.5.0 M2 limitation) for "+shadow.getKind()+" join points, see: " +
- getSourceLocation());
- shadow.getIWorld().getMessageHandler().handleMessage(lim);
- throw new BCException("Binding not supported in @pcds (1.5.0 M2 limitation) for "+shadow.getKind()+" join points, see: " +
- getSourceLocation());
- }
+
if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
import org.aspectj.lang.reflect.FieldSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.AjcMemberMaker;
import org.aspectj.weaver.Constants;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.NewFieldTypeMunger;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
+import org.aspectj.weaver.bcel.BcelTypeMunger;
public class SignaturePattern extends PatternNode {
return false;
}
annotationPattern.resolve(world);
+
+ // optimization before we go digging around for annotations on ITDs
+ if (annotationPattern instanceof AnyAnnotationTypePattern) return true;
+
+ // fake members represent ITD'd fields - for their annotations we should go and look up the
+ // relevant member in the original aspect
+ if (rMember.isAnnotatedElsewhere() && member.getKind()==Member.FIELD) {
+ // FIXME asc duplicate of code in AnnotationPattern.matchInternal()? same fixmes apply here.
+ ResolvedMember [] mems = rMember.getDeclaringType().resolve(world).getDeclaredFields(); // FIXME asc should include supers with getInterTypeMungersIncludingSupers?
+ List mungers = rMember.getDeclaringType().resolve(world).getInterTypeMungers();
+ for (Iterator iter = mungers.iterator(); iter.hasNext();) {
+ BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next();
+ if (typeMunger.getMunger() instanceof NewFieldTypeMunger) {
+ ResolvedMember fakerm = typeMunger.getSignature();
+ ResolvedMember ajcMethod = AjcMemberMaker.interFieldInitializer(fakerm,typeMunger.getAspectType());
+ ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod);
+ if (fakerm.equals(member)) {
+ rMember = rmm;
+ }
+ }
+ }
+ }
+
return annotationPattern.matches(rMember).alwaysTrue();
}
+ private ResolvedMember findMethod(ResolvedTypeX aspectType, ResolvedMember ajcMethod) {
+ ResolvedMember decMethods[] = aspectType.getDeclaredMethods();
+ for (int i = 0; i < decMethods.length; i++) {
+ ResolvedMember member = decMethods[i];
+ if (member.equals(ajcMethod)) return member;
+ }
+ return null;
+ }
+
public boolean matchesIgnoringAnnotations(Member member, World world) {
//XXX performance gains would come from matching on name before resolving
// to fail fast. ASC 30th Nov 04 => Not necessarily, it didn't make it faster for me.
// String n2 = this.getName().maybeGetSimpleName();
// if (n2!=null && !n1.equals(n2)) return false;
- // FIXME ASC :
if (member == null) return false;
ResolvedMember sig = member.resolve(world);