]> source.dussan.org Git - aspectj.git/commitdiff
Enhancement 88862: declare annotation hitting ITDs.
authoraclement <aclement>
Wed, 23 Mar 2005 21:31:49 +0000 (21:31 +0000)
committeraclement <aclement>
Wed, 23 Mar 2005 21:31:49 +0000 (21:31 +0000)
tests/src/org/aspectj/systemtest/ajc150/AnnotationBinding.java
tests/src/org/aspectj/systemtest/ajc150/Annotations.java
tests/src/org/aspectj/systemtest/ajc150/ajc150.xml
weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java
weaver/src/org/aspectj/weaver/ResolvedMember.java
weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java
weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java

index fb013fbd7e0f6d7f145be6d0b90aac81b29e461b..b8055c706c5294f938050d2e0368f73a6d757ac1 100644 (file)
@@ -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");
+  }  
+  
 }
\ No newline at end of file
index 3a099a2ab60f0879b9dba9fe21ad66b5e268c808..b0efd89490d7ea964780f54c4d2e69c5eefd2bcf 100644 (file)
@@ -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() {
index c80d5f6818acd231d3ec967c5f11f74c2863875a..46d57ee6a2b1e264a129c24c4c5684ae8b2bfc29 100644 (file)
     
     <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>
 
             <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>
 
       <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"/>
index 3ef81e57b5afa0463dc68686bcf00ea848f2ba0f..91951118f3b4cc883a4172371bb049095a3da4eb 100644 (file)
@@ -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);
        }
 
index 21385a7f20e84ed046005ccccc785f24b39eac1b..e4e7eae296eb0e814110c4eaece0d28e9cc79480 100644 (file)
@@ -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;
+       }
 }
    
index 0581840eb4f91b0e833ccd6ac6bb8de46eb2b25f..e2906bcd2385494a0cfbbe921063a3eeb09f016d 100644 (file)
@@ -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))
index ab5be0f71112a55eea92d62fb81594b0505f049e..b015f6d3fd010a9d9b062837874c3adb61be0f28 100644 (file)
@@ -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();
        
index 3f1134b6f0a4ec988fa34a793e4e2a98488181bb..7d4bd8d59b20b414e0fecd534602a137ed0b0497 100644 (file)
@@ -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())) {
index d97fefac63e51774702880c01ef2f84424fed713..f465bc2f1ee674617cb4553b4c28c1d5d044eb1f 100644 (file)
@@ -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));
           }
         }
         
index e396576de1987732a65f9d6402ca2a6346eab977..b7c8ed7b49a4857b0f2572112921cb6e5f9ddea9 100644 (file)
@@ -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) {
index 633e15748bdc9a554e7160b75bd3d71a2170f600..13f8be04804a761311744885ef5ddaa8f3046a0c 100644 (file)
@@ -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);