diff options
author | Andy Clement <aclement@gopivotal.com> | 2013-10-01 10:00:14 -0700 |
---|---|---|
committer | Andy Clement <aclement@gopivotal.com> | 2013-10-18 11:36:29 -0700 |
commit | 2314eaf48a35a249e63fae12151ce926ea98c97c (patch) | |
tree | 27fb10ca8254958b652f22e8adf229c506fb1e47 /weaver/src | |
parent | aba10968da43b517e68308e14681a14311a76d42 (diff) | |
download | aspectj-2314eaf48a35a249e63fae12151ce926ea98c97c.tar.gz aspectj-2314eaf48a35a249e63fae12151ce926ea98c97c.zip |
418129: annos on top most implementor method
Diffstat (limited to 'weaver/src')
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java | 100 | ||||
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/BcelWorld.java | 17 | ||||
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java | 30 |
3 files changed, 135 insertions, 12 deletions
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java index fbb4d9292..2c352a258 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java @@ -68,6 +68,7 @@ import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.IClassWeaver; import org.aspectj.weaver.IntMap; import org.aspectj.weaver.Member; +import org.aspectj.weaver.MemberKind; import org.aspectj.weaver.MissingResolvedTypeWithKnownSignature; import org.aspectj.weaver.NameMangler; import org.aspectj.weaver.NewConstructorTypeMunger; @@ -532,8 +533,7 @@ class BcelClassWeaver implements IClassWeaver { // finally, if we changed, we add in the introduced methods. if (isChanged) { clazz.getOrCreateWeaverStateInfo(inReweavableMode); - weaveInAddedMethods(); // FIXME asc are these potentially affected - // by declare annotation? + weaveInAddedMethods(); } if (inReweavableMode) { @@ -893,15 +893,91 @@ class BcelClassWeaver implements IClassWeaver { isChanged = weaveAtMethodOnITDSRepeatedly(allDecams, itdMethodsCtors, reportedProblems); } - // deal with all the other methods... - List<LazyMethodGen> members = clazz.getMethodGens(); List<DeclareAnnotation> decaMs = getMatchingSubset(allDecams, clazz.getType()); if (decaMs.isEmpty()) { return false; // nothing to do } + + Set<DeclareAnnotation> unusedDecams = new HashSet<DeclareAnnotation>(); + unusedDecams.addAll(decaMs); + + // These methods may have been targeted with declare annotation. Example: ITD on an interface + // where the top most implementor gets a real method. The top most implementor method + // is an 'addedLazyMethodGen' + if (addedLazyMethodGens!=null) { + for (LazyMethodGen method: addedLazyMethodGens) { + // They have no resolvedmember of their own, conjure one up for matching purposes + ResolvedMember resolvedmember = + new ResolvedMemberImpl(ResolvedMember.METHOD,method.getEnclosingClass().getType(),method.getAccessFlags(), + BcelWorld.fromBcel(method.getReturnType()),method.getName(), + BcelWorld.fromBcel(method.getArgumentTypes()),UnresolvedType.forNames(method.getDeclaredExceptions())); + resolvedmember.setAnnotationTypes(method.getAnnotationTypes()); + resolvedmember.setAnnotations(method.getAnnotations()); + + List<DeclareAnnotation> worthRetrying = new ArrayList<DeclareAnnotation>(); + boolean modificationOccured = false; + for (DeclareAnnotation decam: decaMs) { + if (decam.matches(resolvedmember, world)) { + if (doesAlreadyHaveAnnotation(resolvedmember, decam, reportedProblems,false)) { + // remove the declare @method since don't want an error when the annotation is already there + unusedDecams.remove(decam); + continue; + } + + AnnotationGen a = ((BcelAnnotation) decam.getAnnotation()).getBcelAnnotation(); + // create copy to get the annotation type into the right constant pool + AnnotationAJ aj = new BcelAnnotation(new AnnotationGen(a, clazz.getConstantPool(), true),world); + method.addAnnotation(aj); + resolvedmember.addAnnotation(decam.getAnnotation()); + + AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decam.getSourceLocation(), + clazz.getName(), resolvedmember, world.getModelAsAsmManager()); + reportMethodCtorWeavingMessage(clazz, resolvedmember, decam, method.getDeclarationLineNumber()); + isChanged = true; + modificationOccured = true; + unusedDecams.remove(decam); + } else if (!decam.isStarredAnnotationPattern()) { + // an annotation is specified that might be put on by a subsequent decaf + worthRetrying.add(decam); + } + } + + // Multiple secondary passes + while (!worthRetrying.isEmpty() && modificationOccured) { + modificationOccured = false; + // lets have another go + List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>(); + for (DeclareAnnotation decam : worthRetrying) { + if (decam.matches(resolvedmember, world)) { + if (doesAlreadyHaveAnnotation(resolvedmember, decam, reportedProblems,false)) { + // remove the declare @method since don't + // want an error when + // the annotation is already there + unusedDecams.remove(decam); + continue; // skip this one... + } + AnnotationGen a = ((BcelAnnotation) decam.getAnnotation()).getBcelAnnotation(); + // create copy to get the annotation type into the right constant pool + AnnotationAJ aj = new BcelAnnotation(new AnnotationGen(a, clazz.getConstantPool(), true),world); + method.addAnnotation(aj); + resolvedmember.addAnnotation(decam.getAnnotation()); + AsmRelationshipProvider.addDeclareAnnotationMethodRelationship(decam.getSourceLocation(), + clazz.getName(), resolvedmember, world.getModelAsAsmManager());// getMethod()); + isChanged = true; + modificationOccured = true; + forRemoval.add(decam); + unusedDecams.remove(decam); + } + } + worthRetrying.removeAll(forRemoval); + } + } + } + + + // deal with all the other methods... + List<LazyMethodGen> members = clazz.getMethodGens(); if (!members.isEmpty()) { - Set<DeclareAnnotation> unusedDecams = new HashSet<DeclareAnnotation>(); - unusedDecams.addAll(decaMs); for (int memberCounter = 0; memberCounter < members.size(); memberCounter++) { LazyMethodGen mg = members.get(memberCounter); if (!mg.getName().startsWith(NameMangler.PREFIX)) { @@ -913,7 +989,7 @@ class BcelClassWeaver implements IClassWeaver { for (DeclareAnnotation decaM : decaMs) { if (decaM.matches(mg.getMemberView(), world)) { - if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems)) { + if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems,true)) { // remove the declare @method since don't want // an error when the annotation is already there unusedDecams.remove(decaM); @@ -954,7 +1030,7 @@ class BcelClassWeaver implements IClassWeaver { List<DeclareAnnotation> forRemoval = new ArrayList<DeclareAnnotation>(); for (DeclareAnnotation decaM : worthRetrying) { if (decaM.matches(mg.getMemberView(), world)) { - if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems)) { + if (doesAlreadyHaveAnnotation(mg.getMemberView(), decaM, reportedProblems,true)) { // remove the declare @method since don't // want an error when // the annotation is already there @@ -1347,7 +1423,7 @@ class BcelClassWeaver implements IClassWeaver { unusedDecafs.remove(decaf); } else { if (!dontAddTwice(decaf, dontAddMeTwice)) { - if (doesAlreadyHaveAnnotation(field, decaf, reportedProblems)) { + if (doesAlreadyHaveAnnotation(field, decaf, reportedProblems,true )) { // remove the declare @field since don't want an error when the annotation is already there unusedDecafs.remove(decaf); continue; @@ -1389,7 +1465,7 @@ class BcelClassWeaver implements IClassWeaver { } else { // below code is for recursive things unusedDecafs.remove(decaF); - if (doesAlreadyHaveAnnotation(field, decaF, reportedProblems)) { + if (doesAlreadyHaveAnnotation(field, decaF, reportedProblems,true)) { continue; } field.addAnnotation(decaF.getAnnotation()); @@ -1486,9 +1562,9 @@ 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, List<Integer> reportedProblems) { + private boolean doesAlreadyHaveAnnotation(ResolvedMember rm, DeclareAnnotation deca, List<Integer> reportedProblems, boolean reportError) { if (rm.hasAnnotation(deca.getAnnotationType())) { - if (world.getLint().elementAlreadyAnnotated.isEnabled()) { + if (reportError && world.getLint().elementAlreadyAnnotated.isEnabled()) { Integer uniqueID = new Integer(rm.hashCode() * deca.hashCode()); if (!reportedProblems.contains(uniqueID)) { reportedProblems.add(uniqueID); diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java index 9fce00cd4..4dfb30e68 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java @@ -345,6 +345,22 @@ public class BcelWorld extends World implements Repository { return ret; } + public static Type[] makeBcelTypes(String[] types) { + if (types == null || types.length==0 ) { + return null; + } + Type[] ret = new Type[types.length]; + for (int i=0, len=types.length; i<len; i++) { + ret[i] = makeBcelType(types[i]); + } + return ret; + } + + public static Type makeBcelType(String type) { + return Type.getType(type); + } + + static String[] makeBcelTypesAsClassNames(UnresolvedType[] types) { String[] ret = new String[types.length]; for (int i = 0, len = types.length; i < len; i++) { @@ -1239,4 +1255,5 @@ public class BcelWorld extends World implements Repository { public void demote(ResolvedType type) { typeMap.demote(type); } + } diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java index b66c6106d..ea0248335 100644 --- a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java +++ b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java @@ -124,6 +124,15 @@ public final class LazyMethodGen implements Traceable { List<BcelShadow> matchedShadows; // Used for interface introduction - this is the type of the interface the method is technically on public ResolvedType definingType = null; + + static class LightweightBcelMethod extends BcelMethod { + + LightweightBcelMethod(BcelObjectType declaringType, Method method) { + super(declaringType, method); + // TODO Auto-generated constructor stub + } + + } public LazyMethodGen(int modifiers, Type returnType, String name, Type[] paramTypes, String[] declaredExceptions, LazyClassGen enclosingClass) { @@ -304,6 +313,27 @@ public final class LazyMethodGen implements Traceable { memberView.addParameterAnnotation(parameterNumber, anno); } } + + public ResolvedType[] getAnnotationTypes() { + initialize(); + if (memberView == null && newAnnotations!=null && newAnnotations.size()!=0) { + // TODO Ignoring removed annotations for now + ResolvedType[] annotationTypes = new ResolvedType[newAnnotations.size()]; + for (int a=0,len=newAnnotations.size();a<len;a++) { + annotationTypes[a] = newAnnotations.get(a).getType(); + } + return annotationTypes; + } + return null; + } + + public AnnotationAJ[] getAnnotations() { + initialize(); + if (memberView == null && newAnnotations!=null && newAnnotations.size()!=0) { + return newAnnotations.toArray(new AnnotationAJ[newAnnotations.size()]); + } + return null; + } public boolean hasAnnotation(UnresolvedType annotationType) { initialize(); |