Преглед на файлове

Enhancement 88862: declare annotation hitting ITDs.

tags/V1_5_0M2
aclement преди 19 години
родител
ревизия
0d14ccfa4c

+ 32
- 0
tests/src/org/aspectj/systemtest/ajc150/AnnotationBinding.java Целия файл

@@ -267,4 +267,36 @@ public class AnnotationBinding extends XMLBasedAjcTestCase {
public void testCallsAndExecutionsOfStaticMethods() {
runTest("binding with static methods");
}
/////////////////////////////////////////////////////////////////////////////////
// annotation binding with ITDs
public void testAnnotationBindingAndITDs1() {
runTest("simple binding annotation values where itd method is annotated");
}
public void testAnnotationBindingAndITDs2() {
runTest("simple binding annotation values where itd field is annotated");
}
public void testAnnotationBindingAndITDs3() {
runTest("simple binding annotation values where itd ctor is annotated");
}
public void testAnnotationBindingAndITDs4() {
runTest("simple binding annotation values where itd method is annotated via declare");
}
public void testAnnotationBindingAndITDs5() {
runTest("simple binding annotation values where itd field is annotated via declare");
}
public void testAnnotationBindingAndITDs6() {
runTest("simple binding annotation values where itd field is annotated multiple times via declare");
}
public void testAnnotationBindingAndITDs7() {
runTest("simple binding annotation values where itd ctor is annotated via declare");
}
}

+ 4
- 0
tests/src/org/aspectj/systemtest/ajc150/Annotations.java Целия файл

@@ -76,7 +76,11 @@ public class Annotations extends XMLBasedAjcTestCase {
// more implementation work needed before this test passes
public void testAnnotatedITDs() {
try {
runTest("annotated itds");
} finally {
System.err.println(ajc.getLastCompilationResult().getStandardError());
}
}

public void testAnnotatedITDsWithWrongAnnotationType() {

+ 125
- 21
tests/src/org/aspectj/systemtest/ajc150/ajc150.xml Целия файл

@@ -486,39 +486,57 @@
<ajc-test dir="java5/annotations/itds" vm="1.5" title="nasty annotation and itds test">
<compile files="AnnotationsAndITDs.aj" options="-1.5">
<message kind="warning" line="25" text="execution(@SomeAnnotation ...)"/>
<message kind="warning" line="28" text="execution(@SomeAnnotation ...)"/>
<message kind="warning" line="52" text="execution(@SomeAnnotation ...)"/>
<message kind="warning" line="53" text="execution(@SomeAnnotation ...)"/>
<!-- first two are ITCs, second two are ITCs annotated via declare @ctor, third is default ctor -->
<message kind="warning" line="17" text="execution(@SomeAnnotation ...new(..)"/>
<message kind="warning" line="20" text="execution(@SomeAnnotation ...new(..)"/>
<message kind="warning" line="45" text="execution(@SomeAnnotation ...new(..)"/>
<message kind="warning" line="46" text="execution(@SomeAnnotation ...new(..)"/>
<message kind="warning" line="180" text="execution(@SomeAnnotation ...new(..)"/>

<!-- first four are fields annotated via declare, last two are directly annotated ITDs -->
<message kind="warning" line="59" text="set(@SomeAnnotation...)"/>
<message kind="warning" line="60" text="set(@SomeAnnotation...)"/>
<message kind="warning" line="70" text="set(@SomeAnnotation...)"/>
<message kind="warning" line="71" text="set(@SomeAnnotation...)"/>
<message kind="warning" line="76" text="set(@SomeAnnotation...)"/>
<message kind="warning" line="77" text="set(@SomeAnnotation...)"/>

<!-- annotations added via declare -->
<message kind="warning" line="175" text="si(@SomeAnnotation...)"/>
<message kind="warning" line="180" text="si(@SomeAnnotation...)"/>
<message kind="warning" line="25" text="execution(@SomeAnnotation ...)"/>
<message kind="warning" line="28" text="execution(@SomeAnnotation ...)"/>
<message kind="warning" line="52" text="execution(@SomeAnnotation ...)"/>
<message kind="warning" line="53" text="execution(@SomeAnnotation ...)"/>
<!--message kind="warning" line="70" text="set(@SomeAnnotation...)"/>
<message kind="warning" line="71" text="set(@SomeAnnotation...)"/-->
</compile>
<run class="AnnotationsAndITDs">
<stdout>
<line text="@type System"/>
<line text="hello AnnotationsAndITDs"/>
<line text="goodbye String"/>
<line text="x Object"/>
<line text="y Integer"/>
<stderr>
<line text="@type java.lang.System (AnnotationsAndITDs.aj:0)"/>
<line text="hello AnnotationsAndITDs (AnnotationsAndITDs.aj:17)"/>
<line text="goodbye java.lang.String (AnnotationsAndITDs.aj:20)"/>
<line text="goodbye java.lang.String (AnnotationsAndITDs.aj:20)"/>
<line text="y java.lang.Integer (AnnotationsAndITDs.aj:28)"/>
<line text="d java.lang.Double (AnnotationsAndITDs.aj:70)"/>
<line text="f java.lang.Double (AnnotationsAndITDs.aj:71)"/>
<line text="@type java.lang.System (AnnotationsAndITDs.aj:0)"/>
<line text="@field ITDMe2 (AnnotationsAndITDs.aj:59)"/>
<line text="@field ITDMe2 (AnnotationsAndITDs.aj:60)"/>
<line text="@cons java.lang.String (AnnotationsAndITDs.aj:45)"/>
<line text="@field ITDMe2 (AnnotationsAndITDs.aj:59)"/>
<line text="@field ITDMe2 (AnnotationsAndITDs.aj:60)"/>
<line text="@cons java.lang.String (AnnotationsAndITDs.aj:46)"/>
<line text="@cons java.lang.String (AnnotationsAndITDs.aj:46)"/>
<line text="@method ITDMe2 (AnnotationsAndITDs.aj:53)"/>
<line text="@field ITDMe2 (AnnotationsAndITDs.aj:76)"/>
<line text="@field ITDMe2 (AnnotationsAndITDs.aj:77)"/>
<!--
<line text="method bar has 1 params, first param annotation is @ParamAnnotation"/>
<line text="d Double"/>
<line text="f Double"/>
<line text="@type System"/>
<line text="@cons String"/>
<line text="@cons String"/>
<line text="@method ITDMe2"/>
<line text="@method ITDMe2"/>
<line text="@field ITDMe2"/>
<line text="@field ITDMe2"/>
</stdout>
-->
</stderr>
</run>
</ajc-test>

@@ -1066,6 +1084,7 @@
<message kind="warning" line="8" text="annotated field"/>
<message kind="warning" line="10" text="annotated method"/>
<message kind="warning" line="12" text="annotated constructor"/>
<message kind="warning" line="12" text="annotated field"/>
</compile>
</ajc-test>

@@ -2022,9 +2041,94 @@
<compile files="DeathByAnnotations.aj" options="-1.5,-emacssym" xlintfile="ignoreTypeNotExposed.properties"/>
<run class="p.q.DeathByAnnotations"/>
</ajc-test>
<!-- ======================================================================================= -->
<!-- annotation binding with ITDs -->
<!-- ======================================================================================= -->

<ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd method is annotated">
<compile files="BindingWithAnnotatedItds1.aj" options="-1.5"/>
<run class="BindingWithAnnotatedItds1">
<stderr>
<line text="Found apple at jp execution(int A.m()) (BindingWithAnnotatedItds1.aj:8)"/>
</stderr>
</run>
</ajc-test>
<ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd field is annotated">
<compile files="BindingWithAnnotatedItds2.aj" options="-1.5"/>
<run class="BindingWithAnnotatedItds2">
<stderr>
<line text="Found banana at jp set(int A.i) (BindingWithAnnotatedItds2.aj:16)"/>
<line text="Found apple at jp set(String A.j) (BindingWithAnnotatedItds2.aj:17)"/>
<line text="Found orange at jp set(int[] A.k) (BindingWithAnnotatedItds2.aj:18)"/>
</stderr>
</run>
</ajc-test>

<ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd ctor is annotated">
<compile files="BindingWithAnnotatedItds3.aj" options="-1.5"/>
<run class="BindingWithAnnotatedItds3">
<stderr>
<line text="Found pear at jp execution(A(String)) (BindingWithAnnotatedItds3.aj:8)"/>
<line text="Found orange at jp execution(A(int)) (BindingWithAnnotatedItds3.aj:10)"/>
<line text="Found tomato at jp execution(A(boolean)) (BindingWithAnnotatedItds3.aj:12)"/>
</stderr>
</run>
</ajc-test>
<!-- ======================================================================================= -->
<!-- declare annotation targetting ITDs -->
<!-- ======================================================================================= -->
<ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd method is annotated via declare">
<compile files="BindingWithDeclaredAnnotationItds1.aj" options="-1.5"/>
<run class="BindingWithDeclaredAnnotationItds1">
<stderr>
<line text="Found orange at jp call(int A.m()) (BindingWithDeclaredAnnotationItds1.aj:16)"/>
<line text="Found orange at jp execution(int A.m()) (BindingWithDeclaredAnnotationItds1.aj:8)"/>
<line text="Found banana at jp call(int A.n()) (BindingWithDeclaredAnnotationItds1.aj:17)"/>
<line text="Found banana at jp execution(int A.n()) (BindingWithDeclaredAnnotationItds1.aj:10)"/>
<line text="Found tomato at jp call(int A.o()) (BindingWithDeclaredAnnotationItds1.aj:18)"/>
<line text="Found tomato at jp execution(int A.o()) (BindingWithDeclaredAnnotationItds1.aj:12)"/>
</stderr>
</run>
</ajc-test>
<ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd field is annotated via declare">
<compile files="BindingWithDeclaredAnnotationItds2.aj" options="-1.5"/>
<run class="BindingWithDeclaredAnnotationItds2">
<stderr>
<line text="Found orange at jp set(int A.i) (BindingWithDeclaredAnnotationItds2.aj:16)"/>
<line text="Found banana at jp set(String A.j) (BindingWithDeclaredAnnotationItds2.aj:17)"/>
<line text="Found apple at jp set(boolean[] A.k) (BindingWithDeclaredAnnotationItds2.aj:18)"/>
</stderr>
</run>
</ajc-test>
<ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd field is annotated multiple times via declare">
<compile files="BindingWithDeclaredAnnotationItds3.aj" options="-1.5"/>
<run class="BindingWithDeclaredAnnotationItds3">
<stderr>
<line text="Found fruit orange at jp set(int A.i) (BindingWithDeclaredAnnotationItds3.aj:13)"/>
<line text="Found drink margarita at jp set(int A.i) (BindingWithDeclaredAnnotationItds3.aj:13)"/>
</stderr>
</run>
</ajc-test>
<ajc-test dir="java5/annotations/binding" title="simple binding annotation values where itd ctor is annotated via declare">
<compile files="BindingWithDeclaredAnnotationItds4.aj" options="-1.5"/>
<run class="BindingWithDeclaredAnnotationItds4">
<stderr>
<line text="Found pear at jp execution(A(String)) (BindingWithDeclaredAnnotationItds4.aj:8)"/>
<line text="Found orange at jp execution(A(int)) (BindingWithDeclaredAnnotationItds4.aj:10)"/>
<line text="Found tomato at jp execution(A(boolean)) (BindingWithDeclaredAnnotationItds4.aj:12)"/>
</stderr>
</run>
</ajc-test>

<!-- ============================================================== -->
<!-- ============================================================== -->
<ajc-test dir="options/aspectpath" title="dirs on aspectpath">
<compile files="MyAspect.aj" options="-d out"/>

+ 1
- 0
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);
}


+ 48
- 2
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;
}
}

+ 311
- 31
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))

+ 129
- 68
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();

+ 1
- 1
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())) {

+ 36
- 16
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));
}
}

+ 32
- 20
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) {

+ 35
- 1
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);

Loading…
Отказ
Запис