@@ -156,9 +156,10 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration { | |||
classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute())); | |||
if (!Modifier.isAbstract(declaredModifiers)) { | |||
super.generateCode(classScope, classFile); | |||
super.generateCode(classScope, classFile); // this makes the interMethodBody | |||
} | |||
// annotations on the ITD declaration get put on this method | |||
generateDispatchMethod(classScope, classFile); | |||
} | |||
@@ -176,7 +177,13 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration { | |||
classFile.generateMethodInfoHeader(dispatchBinding); | |||
int methodAttributeOffset = classFile.contentsOffset; | |||
int attributeNumber = classFile.generateMethodInfoAttribute(dispatchBinding, | |||
// Watch out! We are passing in 'binding' here (instead of dispatchBinding) so that | |||
// the dispatch binding attributes will include the annotations from the 'binding'. | |||
// There is a chance that something else on the binding (e.g. throws clause) might | |||
// damage the attributes generated for the dispatch binding. | |||
int attributeNumber = classFile.generateMethodInfoAttribute(binding, | |||
false, | |||
makeEffectiveSignatureAttribute(signature, Shadow.MethodCall, false)); | |||
int codeAttributeOffset = classFile.contentsOffset; |
@@ -42,6 +42,7 @@ public class AllTestsAspectJ150 { | |||
suite.addTest(Autoboxing.suite()); | |||
suite.addTest(Annotations.suite()); | |||
suite.addTest(AnnotationBinding.suite()); | |||
suite.addTest(RuntimeAnnotations.suite()); | |||
suite.addTest(SuppressedWarnings.suite()); | |||
suite.addTest(DeclareAnnotationTests.suite()); |
@@ -27,9 +27,12 @@ import java.util.Set; | |||
import org.aspectj.apache.bcel.Constants; | |||
import org.aspectj.apache.bcel.classfile.Field; | |||
import org.aspectj.apache.bcel.classfile.Method; | |||
import org.aspectj.apache.bcel.classfile.annotation.Annotation; | |||
import org.aspectj.apache.bcel.generic.BranchInstruction; | |||
import org.aspectj.apache.bcel.generic.CPInstruction; | |||
import org.aspectj.apache.bcel.generic.ConstantPoolGen; | |||
import org.aspectj.apache.bcel.generic.FieldGen; | |||
import org.aspectj.apache.bcel.generic.FieldInstruction; | |||
import org.aspectj.apache.bcel.generic.INVOKESPECIAL; | |||
import org.aspectj.apache.bcel.generic.IndexedInstruction; | |||
@@ -41,6 +44,7 @@ import org.aspectj.apache.bcel.generic.InstructionList; | |||
import org.aspectj.apache.bcel.generic.InstructionTargeter; | |||
import org.aspectj.apache.bcel.generic.InvokeInstruction; | |||
import org.aspectj.apache.bcel.generic.LocalVariableInstruction; | |||
import org.aspectj.apache.bcel.generic.MethodGen; | |||
import org.aspectj.apache.bcel.generic.NEW; | |||
import org.aspectj.apache.bcel.generic.ObjectType; | |||
import org.aspectj.apache.bcel.generic.PUTFIELD; | |||
@@ -49,6 +53,7 @@ import org.aspectj.apache.bcel.generic.RET; | |||
import org.aspectj.apache.bcel.generic.ReturnInstruction; | |||
import org.aspectj.apache.bcel.generic.Select; | |||
import org.aspectj.apache.bcel.generic.Type; | |||
import org.aspectj.apache.bcel.generic.annotation.AnnotationGen; | |||
import org.aspectj.bridge.IMessage; | |||
import org.aspectj.bridge.ISourceLocation; | |||
import org.aspectj.bridge.WeaveMessage; | |||
@@ -66,8 +71,8 @@ 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.ResolvedType; | |||
import org.aspectj.weaver.ResolvedTypeMunger; | |||
import org.aspectj.weaver.Shadow; | |||
import org.aspectj.weaver.ShadowMunger; | |||
import org.aspectj.weaver.UnresolvedType; | |||
@@ -463,46 +468,55 @@ class BcelClassWeaver implements IClassWeaver { | |||
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; | |||
for (Iterator iter = decaMs.iterator(); iter.hasNext();) { | |||
DeclareAnnotation decaM = (DeclareAnnotation) iter.next(); | |||
if (decaM.matches(mg.getMemberView(),world)) { | |||
if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) continue; // skip this one... | |||
mg.addAnnotation(decaM.getAnnotationX()); | |||
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaM.getSourceLocation(),clazz.getName(),mg.getMethod()); | |||
reportMethodCtorWeavingMessage(clazz, mg, decaM); | |||
isChanged = true; | |||
modificationOccured = true; | |||
} else { | |||
if (!decaM.isStarredAnnotationPattern()) | |||
worthRetrying.add(decaM); // an annotation is specified that might be put on by a subsequent decaf | |||
} | |||
} | |||
// Multiple secondary passes | |||
while (!worthRetrying.isEmpty() && modificationOccured) { | |||
modificationOccured = false; | |||
// lets have another go | |||
List forRemoval = new ArrayList(); | |||
for (Iterator iter = worthRetrying.iterator(); iter.hasNext();) { | |||
DeclareAnnotation decaM = (DeclareAnnotation) iter.next(); | |||
if (decaM.matches(mg.getMemberView(),world)) { | |||
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; | |||
modificationOccured = true; | |||
forRemoval.add(decaM); | |||
} | |||
} | |||
worthRetrying.removeAll(forRemoval); | |||
} | |||
// Single first pass | |||
List worthRetrying = new ArrayList(); | |||
boolean modificationOccured = false; | |||
for (Iterator iter = decaMs.iterator(); iter.hasNext();) { | |||
DeclareAnnotation decaM = (DeclareAnnotation) iter.next(); | |||
if (decaM.matches(mg.getMemberView(),world)) { | |||
if (doesAlreadyHaveAnnotation(mg.getMemberView(),decaM,reportedProblems)) continue; // skip this one... | |||
Annotation a = decaM.getAnnotationX().getBcelAnnotation(); | |||
AnnotationGen ag = new AnnotationGen(a,clazz.getConstantPoolGen(),true); | |||
Method oldMethod = mg.getMethod(); | |||
MethodGen myGen = new MethodGen(oldMethod,clazz.getClassName(),clazz.getConstantPoolGen()); | |||
myGen.addAnnotation(ag); | |||
Method newMethod = myGen.getMethod(); | |||
mg.addAnnotation(decaM.getAnnotationX()); | |||
members.set(memberCounter,new LazyMethodGen(newMethod,clazz)); | |||
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaM.getSourceLocation(),clazz.getName(),mg.getMethod()); | |||
reportMethodCtorWeavingMessage(clazz, mg, decaM); | |||
isChanged = true; | |||
modificationOccured = true; | |||
} else { | |||
if (!decaM.isStarredAnnotationPattern()) | |||
worthRetrying.add(decaM); // an annotation is specified that might be put on by a subsequent decaf | |||
} | |||
} | |||
// Multiple secondary passes | |||
while (!worthRetrying.isEmpty() && modificationOccured) { | |||
modificationOccured = false; | |||
// lets have another go | |||
List forRemoval = new ArrayList(); | |||
for (Iterator iter = worthRetrying.iterator(); iter.hasNext();) { | |||
DeclareAnnotation decaM = (DeclareAnnotation) iter.next(); | |||
if (decaM.matches(mg.getMemberView(),world)) { | |||
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; | |||
modificationOccured = true; | |||
forRemoval.add(decaM); | |||
} | |||
} | |||
worthRetrying.removeAll(forRemoval); | |||
} | |||
} | |||
} | |||
} | |||
@@ -599,14 +613,16 @@ class BcelClassWeaver implements IClassWeaver { | |||
// 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; | |||
NewMethodTypeMunger nftm = (NewMethodTypeMunger)methodCtorMunger.getMunger(); | |||
ResolvedMember lookingFor = AjcMemberMaker.interMethodDispatcher(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()); | |||
@@ -683,20 +699,20 @@ class BcelClassWeaver implements IClassWeaver { | |||
boolean isChanged = false; | |||
for (Iterator iter = itdMethodsCtors.iterator(); iter.hasNext();) { | |||
BcelTypeMunger methodctorMunger = (BcelTypeMunger) iter.next(); | |||
ResolvedMember itdIsActually = methodctorMunger.getSignature(); | |||
ResolvedMember unMangledInterMethod = 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)) { | |||
if (decaMC.matches(unMangledInterMethod,world)) { | |||
LazyMethodGen annotationHolder = locateAnnotationHolderForMethodCtorMunger(clazz,methodctorMunger); | |||
if (doesAlreadyHaveAnnotation(annotationHolder,itdIsActually,decaMC,reportedErrors)) continue; // skip this one... | |||
if (annotationHolder == null || doesAlreadyHaveAnnotation(annotationHolder,unMangledInterMethod,decaMC,reportedErrors)){ | |||
continue; // skip this one... | |||
} | |||
annotationHolder.addAnnotation(decaMC.getAnnotationX()); | |||
itdIsActually.addAnnotation(decaMC.getAnnotationX()); | |||
isChanged=true; | |||
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaMC.getSourceLocation(),itdIsActually.getSourceLocation()); | |||
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaMC.getSourceLocation(),unMangledInterMethod.getSourceLocation()); | |||
modificationOccured = true; | |||
} else { | |||
if (!decaMC.isStarredAnnotationPattern()) | |||
@@ -709,12 +725,12 @@ class BcelClassWeaver implements IClassWeaver { | |||
List forRemoval = new ArrayList(); | |||
for (Iterator iter2 = worthRetrying.iterator(); iter.hasNext();) { | |||
DeclareAnnotation decaMC = (DeclareAnnotation) iter2.next(); | |||
if (decaMC.matches(itdIsActually,world)) { | |||
if (decaMC.matches(unMangledInterMethod,world)) { | |||
LazyMethodGen annotationHolder = locateAnnotationHolderForFieldMunger(clazz,methodctorMunger); | |||
if (doesAlreadyHaveAnnotation(annotationHolder,itdIsActually,decaMC,reportedErrors)) continue; // skip this one... | |||
if (doesAlreadyHaveAnnotation(annotationHolder,unMangledInterMethod,decaMC,reportedErrors)) continue; // skip this one... | |||
annotationHolder.addAnnotation(decaMC.getAnnotationX()); | |||
itdIsActually.addAnnotation(decaMC.getAnnotationX()); | |||
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaMC.getSourceLocation(),itdIsActually.getSourceLocation()); | |||
unMangledInterMethod.addAnnotation(decaMC.getAnnotationX()); | |||
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaMC.getSourceLocation(),unMangledInterMethod.getSourceLocation()); | |||
isChanged = true; | |||
modificationOccured = true; | |||
forRemoval.add(decaMC); | |||
@@ -726,6 +742,16 @@ class BcelClassWeaver implements IClassWeaver { | |||
return isChanged; | |||
} | |||
private boolean dontAddTwice(DeclareAnnotation decaF, Annotation [] dontAddMeTwice){ | |||
for (int i = 0; i < dontAddMeTwice.length; i++){ | |||
Annotation ann = dontAddMeTwice[i]; | |||
if (ann != null && decaF.getAnnotationX().getTypeName().equals(ann.getTypeName())){ | |||
dontAddMeTwice[i] = null; // incase it really has been added twice! | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* Weave any declare @field statements into the fields of the supplied class | |||
@@ -769,12 +795,37 @@ class BcelClassWeaver implements IClassWeaver { | |||
// Single first pass | |||
List worthRetrying = new ArrayList(); | |||
boolean modificationOccured = false; | |||
Annotation [] dontAddMeTwice = fields[fieldCounter].getAnnotations(); | |||
// go through all the declare @field statements | |||
for (Iterator iter = decaFs.iterator(); iter.hasNext();) { | |||
DeclareAnnotation decaF = (DeclareAnnotation) iter.next(); | |||
if (decaF.matches(aBcelField,world)) { | |||
if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)) continue; // skip this one... | |||
aBcelField.addAnnotation(decaF.getAnnotationX()); | |||
if (!dontAddTwice(decaF,dontAddMeTwice)){ | |||
if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)){ | |||
continue; | |||
} | |||
if(decaF.getAnnotationX().isRuntimeVisible()){ // isAnnotationWithRuntimeRetention(clazz.getJavaClass(world))){ | |||
//if(decaF.getAnnotationTypeX().isAnnotationWithRuntimeRetention(world)){ | |||
// it should be runtime visible, so put it on the Field | |||
Annotation a = decaF.getAnnotationX().getBcelAnnotation(); | |||
AnnotationGen ag = new AnnotationGen(a,clazz.getConstantPoolGen(),true); | |||
FieldGen myGen = new FieldGen(fields[fieldCounter],clazz.getConstantPoolGen()); | |||
myGen.addAnnotation(ag); | |||
Field newField = myGen.getField(); | |||
aBcelField.addAnnotation(decaF.getAnnotationX()); | |||
clazz.replaceField(fields[fieldCounter],newField); | |||
fields[fieldCounter]=newField; | |||
} else{ | |||
aBcelField.addAnnotation(decaF.getAnnotationX()); | |||
} | |||
} | |||
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]); | |||
reportFieldAnnotationWeavingMessage(clazz, fields, fieldCounter, decaF); | |||
isChanged = true; | |||
@@ -793,6 +844,7 @@ class BcelClassWeaver implements IClassWeaver { | |||
for (Iterator iter = worthRetrying.iterator(); iter.hasNext();) { | |||
DeclareAnnotation decaF = (DeclareAnnotation) iter.next(); | |||
if (decaF.matches(aBcelField,world)) { | |||
// below code is for recursive things | |||
if (doesAlreadyHaveAnnotation(aBcelField,decaF,reportedProblems)) continue; // skip this one... | |||
aBcelField.addAnnotation(decaF.getAnnotationX()); | |||
AsmRelationshipProvider.getDefault().addDeclareAnnotationRelationship(decaF.getSourceLocation(),clazz.getName(),fields[fieldCounter]); | |||
@@ -846,7 +898,7 @@ class BcelClassWeaver implements IClassWeaver { | |||
} | |||
private boolean doesAlreadyHaveAnnotation(LazyMethodGen rm,ResolvedMember itdfieldsig,DeclareAnnotation deca,List reportedProblems) { | |||
if (rm.hasAnnotation(deca.getAnnotationTypeX())) { | |||
if (rm != null && rm.hasAnnotation(deca.getAnnotationTypeX())) { | |||
if (world.getLint().elementAlreadyAnnotated.isEnabled()) { | |||
Integer uniqueID = new Integer(rm.hashCode()*deca.hashCode()); | |||
if (!reportedProblems.contains(uniqueID)) { | |||
@@ -1592,7 +1644,7 @@ class BcelClassWeaver implements IClassWeaver { | |||
ResolvedMember resolvedDooberry = world.resolve(declaredSig); | |||
annotations = resolvedDooberry.getAnnotationTypes(); | |||
} else { | |||
ResolvedMember realthing = AjcMemberMaker.interMethodBody(rm,memberHostType); | |||
ResolvedMember realthing = AjcMemberMaker.interMethodDispatcher(rm,memberHostType); | |||
ResolvedMember resolvedDooberry = world.resolve(realthing); | |||
annotations = resolvedDooberry.getAnnotationTypes(); | |||
} |
@@ -1336,6 +1336,68 @@ public class BcelShadow extends Shadow { | |||
// what the full set of annotations could be (due to static/dynamic type differences...) | |||
} | |||
} | |||
protected Member getRelevantMember(Member relevantMember, ResolvedType relevantType){ | |||
if (relevantMember != null){ | |||
return relevantMember; | |||
} | |||
relevantMember = getSignature().resolve(world); | |||
// 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.getName().equals(getSignature().getName()) && | |||
fakerm.getParameterSignature().equals(getSignature().getParameterSignature())){ | |||
if (relevantMember.getKind()==ResolvedMember.CONSTRUCTOR){ | |||
relevantMember = AjcMemberMaker.interConstructor( | |||
relevantType, | |||
(ResolvedMember)relevantMember, | |||
typeMunger.getAspectType()); | |||
} else { | |||
relevantMember = AjcMemberMaker.interMethod((ResolvedMember)relevantMember, | |||
typeMunger.getAspectType(), false); | |||
} | |||
// in the above.. what about if it's on an Interface? Can that happen? | |||
// then the last arg of the above should be true | |||
return relevantMember; | |||
} | |||
} | |||
} | |||
return null; | |||
} | |||
protected ResolvedType [] getAnnotations(Member relevantMember, ResolvedType relevantType){ | |||
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.interMethodDispatcher(fakerm,typeMunger.getAspectType())); | |||
//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; | |||
return relevantMember.getAnnotationTypes(); | |||
} | |||
} | |||
} | |||
} | |||
return relevantMember.getAnnotationTypes(); | |||
} | |||
public void initializeKindedAnnotationVars() { | |||
if (kindedAnnotationVars != null) return; | |||
@@ -1355,30 +1417,9 @@ public class BcelShadow extends Shadow { | |||
} else if (getKind() == Shadow.MethodCall || getKind() == Shadow.ConstructorCall) { | |||
relevantMember = findMethod2(relevantType.resolve(world).getDeclaredMethods(),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 = relevantMember.getAnnotationTypes(); | |||
annotations = getAnnotations(relevantMember,relevantType); | |||
relevantMember = getRelevantMember(relevantMember,relevantType); | |||
} else if (getKind() == Shadow.FieldSet || getKind() == Shadow.FieldGet) { | |||
relevantMember = findField(relevantType.getDeclaredFields(),getSignature()); | |||
@@ -1407,29 +1448,8 @@ public class BcelShadow extends Shadow { | |||
ResolvedMember rm[] = relevantType.getDeclaredMethods(); | |||
relevantMember = findMethod2(relevantType.getDeclaredMethods(),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 = relevantMember.getAnnotationTypes(); | |||
annotations = getAnnotations(relevantMember,relevantType); | |||
relevantMember = getRelevantMember(relevantMember,relevantType); | |||
} else if (getKind() == Shadow.ExceptionHandler) { | |||
relevantType = getSignature().getParameterTypes()[0].resolve(world); |
@@ -55,6 +55,7 @@ import org.aspectj.weaver.ResolvedType; | |||
import org.aspectj.weaver.UnresolvedType; | |||
import org.aspectj.weaver.WeaverMessages; | |||
import org.aspectj.weaver.WeaverStateInfo; | |||
import org.aspectj.weaver.patterns.DeclareAnnotation; | |||
import org.aspectj.weaver.patterns.Pointcut; | |||
@@ -708,13 +709,14 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
} | |||
private boolean mungeNewMethod(BcelClassWeaver weaver, NewMethodTypeMunger munger) { | |||
ResolvedMember signature = munger.getSignature(); | |||
// TODO asc I'm confused? Why do we treat the 'real method' (the inter method body) as the dispatch method? | |||
ResolvedMember dispatchMethod = munger.getInterMethodBody(aspectType); | |||
ResolvedMember unMangledInterMethod = munger.getSignature(); | |||
// do matching on the unMangled one, but actually add them to the mangled method | |||
ResolvedMember interMethodBody = munger.getInterMethodBody(aspectType); | |||
ResolvedMember interMethodDispatcher = munger.getInterMethodDispatcher(aspectType); | |||
LazyClassGen gen = weaver.getLazyClassGen(); | |||
ResolvedType onType = weaver.getWorld().resolve(signature.getDeclaringType(),munger.getSourceLocation()); | |||
ResolvedType onType = weaver.getWorld().resolve(unMangledInterMethod.getDeclaringType(),munger.getSourceLocation()); | |||
if (onType.isRawType()) onType = onType.getGenericType(); | |||
boolean onInterface = onType.isInterface(); | |||
@@ -730,50 +732,62 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
} | |||
if (onType.equals(gen.getType())) { | |||
ResolvedMember introMethod = | |||
AjcMemberMaker.interMethod(signature, aspectType, onInterface); | |||
ResolvedMember mangledInterMethod = | |||
AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, onInterface); | |||
AnnotationX annotationsOnRealMember[] = null; | |||
LazyMethodGen mg = makeMethodGen(gen, mangledInterMethod); | |||
// pr98901 | |||
// For copying the annotations across, we have to discover the real member in the aspect | |||
// which is holding them. | |||
if (weaver.getWorld().isInJava5Mode() && !onInterface && munger.getSignature().isPublic() && !munger.getSignature().isAbstract()) { | |||
ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,dispatchMethod); | |||
if (weaver.getWorld().isInJava5Mode()){ | |||
AnnotationX annotationsOnRealMember[] = null; | |||
ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,interMethodDispatcher); | |||
if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+ | |||
dispatchMethod+"' on aspect "+aspectType); | |||
interMethodDispatcher+"' on aspect "+aspectType); | |||
annotationsOnRealMember = realMember.getAnnotations(); | |||
} | |||
LazyMethodGen mg = makeMethodGen(gen, introMethod); | |||
if (annotationsOnRealMember!=null) { | |||
for (int i = 0; i < annotationsOnRealMember.length; i++) { | |||
AnnotationX annotationX = annotationsOnRealMember[i]; | |||
Annotation a = annotationX.getBcelAnnotation(); | |||
AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true); | |||
mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld())); | |||
if (annotationsOnRealMember!=null) { | |||
for (int i = 0; i < annotationsOnRealMember.length; i++) { | |||
AnnotationX annotationX = annotationsOnRealMember[i]; | |||
Annotation a = annotationX.getBcelAnnotation(); | |||
AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true); | |||
mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld())); | |||
} | |||
} | |||
// the below loop fixes the very special (and very stupid) | |||
// case where an aspect declares an annotation | |||
// on an ITD it declared on itself. | |||
List allDecams = weaver.getWorld().getDeclareAnnotationOnMethods(); | |||
for (Iterator i = allDecams.iterator(); i.hasNext();){ | |||
DeclareAnnotation decaMC = (DeclareAnnotation) i.next(); | |||
if (decaMC.matches(unMangledInterMethod,weaver.getWorld()) | |||
&& mg.getEnclosingClass().getType() == aspectType) { | |||
mg.addAnnotation(decaMC.getAnnotationX()); | |||
} | |||
} | |||
} | |||
if (!onInterface && !Modifier.isAbstract(introMethod.getModifiers())) { | |||
if (!onInterface && !Modifier.isAbstract(mangledInterMethod.getModifiers())) { | |||
InstructionList body = mg.getBody(); | |||
InstructionFactory fact = gen.getFactory(); | |||
int pos = 0; | |||
if (!signature.isStatic()) { | |||
if (!unMangledInterMethod.isStatic()) { | |||
body.append(InstructionFactory.createThis()); | |||
pos++; | |||
} | |||
Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes()); | |||
Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes()); | |||
for (int i = 0, len = paramTypes.length; i < len; i++) { | |||
Type paramType = paramTypes[i]; | |||
body.append(InstructionFactory.createLoad(paramType, pos)); | |||
pos+=paramType.getSize(); | |||
} | |||
body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod)); | |||
body.append(Utility.createInvoke(fact, weaver.getWorld(), interMethodBody)); | |||
body.append( | |||
InstructionFactory.createReturn( | |||
BcelWorld.makeBcelType(introMethod.getReturnType()))); | |||
BcelWorld.makeBcelType(mangledInterMethod.getReturnType()))); | |||
} else { | |||
//??? this is okay | |||
//if (!(mg.getBody() == null)) throw new RuntimeException("bas"); | |||
@@ -788,7 +802,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
return true; | |||
} else if (onInterface && !Modifier.isAbstract(signature.getModifiers())) { | |||
} else if (onInterface && !Modifier.isAbstract(unMangledInterMethod.getModifiers())) { | |||
// This means the 'gen' should be the top most implementor | |||
// - if it is *not* then something went wrong after we worked | |||
@@ -808,19 +822,19 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
return false; | |||
} else { | |||
ResolvedMember introMethod = | |||
AjcMemberMaker.interMethod(signature, aspectType, false); | |||
ResolvedMember mangledInterMethod = | |||
AjcMemberMaker.interMethod(unMangledInterMethod, aspectType, false); | |||
LazyMethodGen mg = makeMethodGen(gen, introMethod); | |||
LazyMethodGen mg = makeMethodGen(gen, mangledInterMethod); | |||
Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes()); | |||
Type returnType = BcelWorld.makeBcelType(introMethod.getReturnType()); | |||
Type[] paramTypes = BcelWorld.makeBcelTypes(mangledInterMethod.getParameterTypes()); | |||
Type returnType = BcelWorld.makeBcelType(mangledInterMethod.getReturnType()); | |||
InstructionList body = mg.getBody(); | |||
InstructionFactory fact = gen.getFactory(); | |||
int pos = 0; | |||
if (!introMethod.isStatic()) { | |||
if (!mangledInterMethod.isStatic()) { | |||
body.append(InstructionFactory.createThis()); | |||
pos++; | |||
} | |||
@@ -829,7 +843,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
body.append(InstructionFactory.createLoad(paramType, pos)); | |||
pos+=paramType.getSize(); | |||
} | |||
body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod)); | |||
body.append(Utility.createInvoke(fact, weaver.getWorld(), interMethodBody)); | |||
body.append(InstructionFactory.createReturn(returnType)); | |||
mg.definingType = onType; | |||
@@ -844,12 +858,28 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
} | |||
} | |||
private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember dispatchMethod) { | |||
private ResolvedMember getRealMemberForITDFromAspect(ResolvedType aspectType,ResolvedMember lookingFor) { | |||
ResolvedMember aspectMethods[] = aspectType.getDeclaredMethods(); | |||
UnresolvedType [] lookingForParams = lookingFor.getParameterTypes(); | |||
ResolvedMember realMember = null; | |||
for (int i = 0; realMember==null && i < aspectMethods.length; i++) { | |||
ResolvedMember member = aspectMethods[i]; | |||
if (member.getName().equals(dispatchMethod.getName())) realMember = member; | |||
if (member.getName().equals(lookingFor.getName())){ | |||
UnresolvedType [] memberParams = member.getParameterTypes(); | |||
if (memberParams.length == lookingForParams.length){ | |||
boolean matchOK = true; | |||
for (int j = 0; j < memberParams.length && matchOK; j++){ | |||
UnresolvedType memberParam = memberParams[j]; | |||
UnresolvedType lookingForParam = lookingForParams[j].resolve(aspectType.getWorld()); | |||
if (lookingForParam.isTypeVariableReference()) lookingForParam = lookingForParam.getUpperBound(); | |||
if (!memberParam.equals(lookingForParam)){ | |||
matchOK=false; | |||
} | |||
} | |||
if (matchOK) realMember = member; | |||
} | |||
} | |||
} | |||
return realMember; | |||
} | |||
@@ -898,6 +928,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
BcelClassWeaver weaver, | |||
NewConstructorTypeMunger newConstructorTypeMunger) | |||
{ | |||
final LazyClassGen currentClass = weaver.getLazyClassGen(); | |||
final InstructionFactory fact = currentClass.getFactory(); | |||
@@ -919,17 +950,50 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
ResolvedMember explicitConstructor = newConstructorTypeMunger.getExplicitConstructor(); | |||
//int declaredParameterCount = newConstructorTypeMunger.getDeclaredParameterCount(); | |||
LazyMethodGen freshConstructor = | |||
LazyMethodGen mg = | |||
makeMethodGen(currentClass, newConstructorMember); | |||
currentClass.addMethodGen(freshConstructor); | |||
// pr98901 | |||
// For copying the annotations across, we have to discover the real member in the aspect | |||
// which is holding them. | |||
if (weaver.getWorld().isInJava5Mode()){ | |||
ResolvedMember interMethodDispatcher =AjcMemberMaker.postIntroducedConstructor(aspectType,onType,newConstructorTypeMunger.getSignature().getParameterTypes()); | |||
AnnotationX annotationsOnRealMember[] = null; | |||
ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,interMethodDispatcher); | |||
if (realMember==null) throw new BCException("Couldn't find ITD holder member '"+ | |||
interMethodDispatcher+"' on aspect "+aspectType); | |||
annotationsOnRealMember = realMember.getAnnotations(); | |||
if (annotationsOnRealMember!=null) { | |||
for (int i = 0; i < annotationsOnRealMember.length; i++) { | |||
AnnotationX annotationX = annotationsOnRealMember[i]; | |||
Annotation a = annotationX.getBcelAnnotation(); | |||
AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true); | |||
mg.addAnnotation(new AnnotationX(ag.getAnnotation(),weaver.getWorld())); | |||
} | |||
} | |||
// the below loop fixes the very special (and very stupid) | |||
// case where an aspect declares an annotation | |||
// on an ITD it declared on itself. | |||
List allDecams = weaver.getWorld().getDeclareAnnotationOnMethods(); | |||
for (Iterator i = allDecams.iterator(); i.hasNext();){ | |||
DeclareAnnotation decaMC = (DeclareAnnotation) i.next(); | |||
if (decaMC.matches(explicitConstructor,weaver.getWorld()) | |||
&& mg.getEnclosingClass().getType() == aspectType) { | |||
mg.addAnnotation(decaMC.getAnnotationX()); | |||
} | |||
} | |||
} | |||
currentClass.addMethodGen(mg); | |||
//weaver.addLazyMethodGen(freshConstructor); | |||
InstructionList body = freshConstructor.getBody(); | |||
InstructionList body = mg.getBody(); | |||
// add to body: push arts for call to pre, from actual args starting at 1 (skipping this), going to | |||
// declared argcount + 1 | |||
UnresolvedType[] declaredParams = newConstructorTypeMunger.getSignature().getParameterTypes(); | |||
Type[] paramTypes = freshConstructor.getArgumentTypes(); | |||
Type[] paramTypes = mg.getArgumentTypes(); | |||
int frameIndex = 1; | |||
for (int i = 0, len = declaredParams.length; i < len; i++) { | |||
body.append(InstructionFactory.createLoad(paramTypes[i], frameIndex)); | |||
@@ -941,7 +1005,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
body.append(Utility.createInvoke(fact, null, preMethod)); | |||
// create a local, and store return pre stuff into it. | |||
int arraySlot = freshConstructor.allocateLocal(1); | |||
int arraySlot = mg.allocateLocal(1); | |||
body.append(InstructionFactory.createStore(Type.OBJECT, arraySlot)); | |||
// put this on the stack | |||
@@ -1063,6 +1127,21 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
return false; | |||
} | |||
ResolvedMember interMethodBody = munger.getInitMethod(aspectType); | |||
AnnotationX annotationsOnRealMember[] = null; | |||
// pr98901 | |||
// For copying the annotations across, we have to discover the real member in the aspect | |||
// which is holding them. | |||
if (weaver.getWorld().isInJava5Mode()){ | |||
// the below line just gets the method with the same name in aspectType.getDeclaredMethods(); | |||
ResolvedMember realMember = getRealMemberForITDFromAspect(aspectType,interMethodBody); | |||
if (realMember==null) throw new BCException("Couldn't find ITD init member '"+ | |||
interMethodBody+"' on aspect "+aspectType); | |||
annotationsOnRealMember = realMember.getAnnotations(); | |||
} | |||
if (onType.equals(gen.getType())) { | |||
if (onInterface) { | |||
LazyMethodGen mg = makeMethodGen(gen, | |||
@@ -1076,7 +1155,18 @@ public class BcelTypeMunger extends ConcreteTypeMunger { | |||
weaver.addInitializer(this); | |||
FieldGen fg = makeFieldGen(gen, | |||
AjcMemberMaker.interFieldClassField(field, aspectType)); | |||
gen.addField(fg.getField(),getSourceLocation()); | |||
if (annotationsOnRealMember!=null) { | |||
for (int i = 0; i < annotationsOnRealMember.length; i++) { | |||
AnnotationX annotationX = annotationsOnRealMember[i]; | |||
Annotation a = annotationX.getBcelAnnotation(); | |||
AnnotationGen ag = new AnnotationGen(a,weaver.getLazyClassGen().getConstantPoolGen(),true); | |||
fg.addAnnotation(ag); | |||
} | |||
} | |||
gen.addField(fg.getField(),getSourceLocation()); | |||
} | |||
return true; | |||
} else if (onInterface && gen.getType().isTopmostImplementor(onType)) { |