summaryrefslogtreecommitdiffstats
path: root/weaver
diff options
context:
space:
mode:
authoraclement <aclement>2005-03-23 21:31:49 +0000
committeraclement <aclement>2005-03-23 21:31:49 +0000
commit0d14ccfa4ce92c9adc2f849a4ee4f22c5b3a5ef7 (patch)
tree2c85206ea7b7989353eef7a9aaac59e9a0c88f32 /weaver
parentfb01cad1cc839b23cba31cd4dd5f44f68bad4411 (diff)
downloadaspectj-0d14ccfa4ce92c9adc2f849a4ee4f22c5b3a5ef7.tar.gz
aspectj-0d14ccfa4ce92c9adc2f849a4ee4f22c5b3a5ef7.zip
Enhancement 88862: declare annotation hitting ITDs.
Diffstat (limited to 'weaver')
-rw-r--r--weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java1
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedMember.java50
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java342
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelShadow.java197
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java2
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java52
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java52
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java36
8 files changed, 593 insertions, 139 deletions
diff --git a/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java b/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java
index 3ef81e57b..91951118f 100644
--- a/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java
+++ b/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java
@@ -21,6 +21,7 @@ import java.util.Set;
public class NewFieldTypeMunger extends ResolvedTypeMunger {
public NewFieldTypeMunger(ResolvedMember signature, Set superMethodsCalled) {
super(Field, signature);
+ signature.setAnnotatedElsewhere(true);
this.setSuperMethodsCalled(superMethodsCalled);
}
diff --git a/weaver/src/org/aspectj/weaver/ResolvedMember.java b/weaver/src/org/aspectj/weaver/ResolvedMember.java
index 21385a7f2..e4e7eae29 100644
--- a/weaver/src/org/aspectj/weaver/ResolvedMember.java
+++ b/weaver/src/org/aspectj/weaver/ResolvedMember.java
@@ -17,6 +17,9 @@ import java.io.DataInputStream;
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;
@@ -28,6 +31,12 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle
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
@@ -101,13 +110,18 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle
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() {
@@ -115,9 +129,24 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle
// 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;
}
@@ -172,6 +201,15 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle
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;
}
@@ -244,5 +282,13 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle
public void setCheckedExceptions(TypeX[] checkedExceptions) {
this.checkedExceptions = checkedExceptions;
}
+
+ public void setAnnotatedElsewhere(boolean b) {
+ isAnnotatedElsewhere = b;
+ }
+
+ public boolean isAnnotatedElsewhere() {
+ return isAnnotatedElsewhere;
+ }
}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
index 0581840eb..e2906bcd2 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
@@ -15,6 +15,7 @@ package org.aspectj.weaver.bcel;
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;
@@ -61,11 +62,15 @@ import org.aspectj.weaver.IClassWeaver;
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;
@@ -115,6 +120,8 @@ class BcelClassWeaver implements IClassWeaver {
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;
@@ -415,26 +422,40 @@ class BcelClassWeaver implements IClassWeaver {
* 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;
@@ -452,7 +473,7 @@ class BcelClassWeaver implements IClassWeaver {
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;
@@ -474,19 +495,185 @@ class BcelClassWeaver implements IClassWeaver {
*/
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) {
@@ -498,14 +685,26 @@ class BcelClassWeaver implements IClassWeaver {
// 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;
@@ -513,7 +712,7 @@ class BcelClassWeaver implements IClassWeaver {
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;
@@ -532,7 +731,7 @@ class BcelClassWeaver implements IClassWeaver {
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;
@@ -552,18 +751,39 @@ class BcelClassWeaver implements IClassWeaver {
* 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();) {
@@ -982,12 +1202,16 @@ class BcelClassWeaver implements IClassWeaver {
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;
}
@@ -1000,7 +1224,8 @@ class BcelClassWeaver implements IClassWeaver {
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();
}
@@ -1259,6 +1484,56 @@ class BcelClassWeaver implements IClassWeaver {
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,
@@ -1292,10 +1567,15 @@ class BcelClassWeaver implements IClassWeaver {
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))
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
index ab5be0f71..b015f6d3f 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
@@ -59,6 +59,9 @@ import org.aspectj.weaver.BCException;
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;
@@ -1283,6 +1286,7 @@ public class BcelShadow extends Shadow {
thisAnnotationVars = new HashMap();
// populate..
}
+
public void initializeTargetAnnotationVars() {
if (targetAnnotationVars != null) return;
if (getKind().isTargetSameAsThis()) {
@@ -1308,6 +1312,7 @@ public class BcelShadow extends Shadow {
// what the full set of annotations could be (due to static/dynamic type differences...)
}
}
+
public void initializeKindedAnnotationVars() {
if (kindedAnnotationVars != null) return;
kindedAnnotationVars = new HashMap();
@@ -1316,100 +1321,156 @@ public class BcelShadow extends Shadow {
// 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();
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
index 3f1134b6f..7d4bd8d59 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
@@ -1134,7 +1134,7 @@ public class BcelWeaver implements IWeaver {
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())) {
diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
index d97fefac6..f465bc2f1 100644
--- a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
+++ b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
@@ -32,6 +32,7 @@ import org.aspectj.apache.bcel.classfile.Attribute;
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;
@@ -58,6 +59,7 @@ import org.aspectj.weaver.BCException;
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;
@@ -84,7 +86,7 @@ public final class LazyMethodGen {
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;
@@ -181,19 +183,25 @@ public final class LazyMethodGen {
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);
@@ -204,7 +212,7 @@ public final class LazyMethodGen {
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());
@@ -799,9 +807,21 @@ public final class LazyMethodGen {
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));
}
}
diff --git a/weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java
index e396576de..b7c8ed7b4 100644
--- a/weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java
+++ b/weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java
@@ -14,18 +14,19 @@ import java.io.DataOutputStream;
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;
@@ -35,6 +36,7 @@ import org.aspectj.weaver.VersionedDataInputStream;
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)
@@ -110,12 +112,39 @@ public class AnnotationPointcut extends NameBindingPointcut {
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)
@@ -148,24 +177,7 @@ public class AnnotationPointcut extends NameBindingPointcut {
*/
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) {
diff --git a/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
index 633e15748..13f8be048 100644
--- a/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
+++ b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
@@ -30,15 +30,18 @@ import org.aspectj.lang.reflect.ConstructorSignature;
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 {
@@ -132,9 +135,41 @@ 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.
@@ -143,7 +178,6 @@ public class SignaturePattern extends PatternNode {
// 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);