diff options
author | aclement <aclement> | 2005-03-23 21:31:49 +0000 |
---|---|---|
committer | aclement <aclement> | 2005-03-23 21:31:49 +0000 |
commit | 0d14ccfa4ce92c9adc2f849a4ee4f22c5b3a5ef7 (patch) | |
tree | 2c85206ea7b7989353eef7a9aaac59e9a0c88f32 /weaver | |
parent | fb01cad1cc839b23cba31cd4dd5f44f68bad4411 (diff) | |
download | aspectj-0d14ccfa4ce92c9adc2f849a4ee4f22c5b3a5ef7.tar.gz aspectj-0d14ccfa4ce92c9adc2f849a4ee4f22c5b3a5ef7.zip |
Enhancement 88862: declare annotation hitting ITDs.
Diffstat (limited to 'weaver')
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); |