]> source.dussan.org Git - aspectj.git/commitdiff
fixes for 115252 from Helen (xlint on incorrect annotation usage in signatures)
authoraclement <aclement>
Fri, 18 Nov 2005 15:04:21 +0000 (15:04 +0000)
committeraclement <aclement>
Fri, 18 Nov 2005 15:04:21 +0000 (15:04 +0000)
13 files changed:
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java
tests/src/org/aspectj/systemtest/ajc150/Ajc150Tests.java
tests/src/org/aspectj/systemtest/ajc150/ajc150.xml
weaver/src/org/aspectj/weaver/AnnotationTargetKind.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/BoundedReferenceType.java
weaver/src/org/aspectj/weaver/Lint.java
weaver/src/org/aspectj/weaver/ReferenceType.java
weaver/src/org/aspectj/weaver/ReferenceTypeDelegate.java
weaver/src/org/aspectj/weaver/ResolvedType.java
weaver/src/org/aspectj/weaver/XlintDefault.properties
weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
weaver/src/org/aspectj/weaver/reflect/ReflectionBasedReferenceTypeDelegate.java

index 9e6a24faeccfca703f665265b3b2c06e097ccd20..d8df9e7b930099c2a189b3427c685302acc9158c 100644 (file)
@@ -44,6 +44,7 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
 import org.aspectj.weaver.AbstractReferenceTypeDelegate;
+import org.aspectj.weaver.AnnotationTargetKind;
 import org.aspectj.weaver.AnnotationX;
 import org.aspectj.weaver.ReferenceType;
 import org.aspectj.weaver.ResolvedMember;
@@ -78,6 +79,9 @@ public class EclipseSourceType extends AbstractReferenceTypeDelegate {
        private CompilationUnitDeclaration unit;
        private boolean annotationsResolved = false;
        private ResolvedType[] resolvedAnnotations = null;
+               
+       private boolean discoveredAnnotationTargetKinds = false;
+       private AnnotationTargetKind[] annotationTargetKinds;
        
        protected EclipseFactory eclipseWorld() {
                return factory;
@@ -336,6 +340,58 @@ public class EclipseSourceType extends AbstractReferenceTypeDelegate {
                return null;
        }
        
+       public boolean canAnnotationTargetType() {
+               if (isAnnotation()) {
+                       return ((binding.getAnnotationTagBits() & TagBits.AnnotationForType) != 0 );
+               }
+               return false;
+       }
+       
+       public AnnotationTargetKind[] getAnnotationTargetKinds() {
+               if (discoveredAnnotationTargetKinds) return annotationTargetKinds;
+               discoveredAnnotationTargetKinds = true;
+               annotationTargetKinds = null; // null means we have no idea or the @Target annotation hasn't been used
+//             if (isAnnotation()) {
+//             Annotation[] annotationsOnThisType = declaration.annotations;
+//             if (annotationsOnThisType != null) {
+//                     for (int i = 0; i < annotationsOnThisType.length; i++) {
+//                         Annotation a = annotationsOnThisType[i];
+//                         if (a.resolvedType != null) {
+//                             String packageName = new String(a.resolvedType.qualifiedPackageName()).concat(".");
+//                                 String sourceName = new String(a.resolvedType.qualifiedSourceName());
+//                                 if ((packageName + sourceName).equals(UnresolvedType.AT_TARGET.getName())) {
+//                                     MemberValuePair[] pairs = a.memberValuePairs();
+//                                     for (int j = 0; j < pairs.length; j++) {
+//                                                             MemberValuePair pair = pairs[j];
+//                                                             targetKind = pair.value.toString();
+//                                                             return targetKind;
+//                                                     }
+//                                 }
+//                                     }
+//                             }
+//             }
+//             }
+//         return targetKind;
+               if (isAnnotation()) {
+                       List targetKinds = new ArrayList();
+                       
+                       if ((binding.getAnnotationTagBits() & TagBits.AnnotationForAnnotationType) != 0) targetKinds.add(AnnotationTargetKind.ANNOTATION_TYPE);
+                       if ((binding.getAnnotationTagBits() & TagBits.AnnotationForConstructor)    != 0) targetKinds.add(AnnotationTargetKind.CONSTRUCTOR);
+                       if ((binding.getAnnotationTagBits() & TagBits.AnnotationForField)          != 0) targetKinds.add(AnnotationTargetKind.FIELD);
+                       if ((binding.getAnnotationTagBits() & TagBits.AnnotationForLocalVariable)  != 0) targetKinds.add(AnnotationTargetKind.LOCAL_VARIABLE);
+                       if ((binding.getAnnotationTagBits() & TagBits.AnnotationForMethod)         != 0) targetKinds.add(AnnotationTargetKind.METHOD);
+                       if ((binding.getAnnotationTagBits() & TagBits.AnnotationForPackage)        != 0) targetKinds.add(AnnotationTargetKind.PACKAGE);
+                       if ((binding.getAnnotationTagBits() & TagBits.AnnotationForParameter)      != 0) targetKinds.add(AnnotationTargetKind.PARAMETER);
+                       if ((binding.getAnnotationTagBits() & TagBits.AnnotationForType)           != 0) targetKinds.add(AnnotationTargetKind.TYPE);
+                       
+                       if (!targetKinds.isEmpty()) {
+                               annotationTargetKinds = new AnnotationTargetKind[targetKinds.size()];
+                               return (AnnotationTargetKind[]) targetKinds.toArray(annotationTargetKinds);     
+                       }
+               }
+               return annotationTargetKinds;
+       }
+       
        public boolean hasAnnotation(UnresolvedType ofType) {
 
                // Make sure they are resolved
@@ -553,4 +609,5 @@ public class EclipseSourceType extends AbstractReferenceTypeDelegate {
        public void ensureDelegateConsistent() {
                // do nothing, currently these can't become inconsistent (phew)
        }
+       
 }
index 08209ca26b1bdee0089395b24c83f20ac685f52e..18b73fd8cf47661729c9725a962ecc3364b6da72 100644 (file)
@@ -718,6 +718,15 @@ public class Ajc150Tests extends org.aspectj.testing.XMLBasedAjcTestCase {
    */
   public void testNPEinWeavingAdaptor_pr116626() { runTest("NPE in WeavingAdaptor");}
   
+  public void testXlintMessageForImproperAnnotationType_pr115252_Exact() {runTest("xlint message for improper exact annotation type");}
+  public void testXlintMessageForImproperAnnotationType_pr115252_OR() {runTest("xlint message for improper annotation type inside OR");}
+  public void testXlintMessageForImproperAnnotationType_pr115252_AND() {runTest("xlint message for improper annotation type inside AND");}
+  public void testXlintMessageForImproperAnnotationType_pr115252_Return() {runTest("xlint message for improper annotated return type");}  
+  public void testXlintMessageForImproperAnnotationType_pr115252_Declaring() {runTest("xlint message for improper annotated declaring type");}  
+  public void testXlintMessageForImproperAnnotationType_pr115252_Parameter() {runTest("xlint message for improper annotated parameter type");}  
+  public void testXlintMessageForImproperAnnotationType_pr115252_Throws() {runTest("xlint message for improper annotated throws pattern");}  
+  public void testXlintMessageForImproperAnnotationType_pr115252_MoreThanOne() {runTest("xlint message for more than one improper annotated parameter type");}  
+    
   // helper methods.....
   
   public SyntheticRepository createRepos(File cpentry) {
index de7cf19d2d92da08d9324863866a292a8922e364..7398978850c2e8835100d88831f4f21598d83e8f 100644 (file)
     <ajc-test dir="bugs150/pr113066" title="possible static imports bug - 1">
         <compile files="Consts.java,TestNPE.java" options="-1.5"/>
     </ajc-test>
-    
+  
+    <ajc-test dir="bugs150" title="parameterized type and around advice">
+        <compile files="pr115250.aj" options="-1.5 -Xlint:ignore"/>
+        <run class="pr115250"/>
+          <!--stderr>
+            <line text="Advice running"/>
+          </stderr>
+        </run-->
+    </ajc-test>
+      
     <ajc-test dir="bugs150/pr115788" title="parser exception">
         <compile files="AAA.java">
           <message kind="warning" line="3" text="no match for this type name: Screen"/>
         </compile>
     </ajc-test>
 
+       <ajc-test dir="bugs150/pr115252" title="xlint message for improper exact annotation type">
+        <compile files="ExactAnnotationTypePattern.java" options="-1.5">
+                       <message kind="warning" line="20" text="field blah"/>
+               <message kind="warning" line="28" text="does not match because annotation @TypeAnnotation has @Target{ElementType.TYPE} [Xlint:unmatchedTargetKind]"/>
+               <message kind="warning" line="37" text="does not match because annotation @FieldAnnotation has @Target{ElementType.FIELD} [Xlint:unmatchedTargetKind]"/>
+            <message kind="warning" line="46" text="does not match because annotation @MethodAnnotation has @Target{ElementType.METHOD} [Xlint:unmatchedTargetKind]"/>
+        </compile>
+    </ajc-test>
+
+       <ajc-test dir="bugs150/pr115252" title="xlint message for improper annotation type inside OR">
+        <compile files="OrTypePattern.java" options="-1.5">
+            <message kind="warning" line="26" text="does not match because annotation @FieldAnnotation has @Target{ElementType.FIELD} [Xlint:unmatchedTargetKind]"/>
+               <message kind="warning" line="31" text="does not match because annotation @TypeAnnotation has @Target{ElementType.TYPE} [Xlint:unmatchedTargetKind]"/>
+               <message kind="warning" line="31" text="does not match because annotation @FieldAnnotation has @Target{ElementType.FIELD} [Xlint:unmatchedTargetKind]"/>
+        </compile>
+    </ajc-test>
+
+       <ajc-test dir="bugs150/pr115252" title="xlint message for improper annotation type inside AND">
+        <compile files="AndTypePattern.java" options="-1.5">
+            <message kind="warning" line="23" text="does not match because annotation @FieldAnnotation has @Target{ElementType.FIELD} [Xlint:unmatchedTargetKind]"/>
+        </compile>
+    </ajc-test>
+
+       <ajc-test dir="bugs150/pr115252" title="xlint message for improper annotated return type">
+        <compile files="AnnotationReturnType.java" options="-1.5">
+            <!-- warnings coming from matching pointcuts and corresponding declare warnings -->
+                       <message kind="warning" line="12" text="(@TypeAnnotation *) *(..)"/>
+                       <message kind="warning" line="12" text="(@(TypeAnnotation || MethodAnnotation) *) *(..)"/>
+            <!-- xlint warnings that were put in as part of fix for pr115252 -->
+               <message kind="warning" line="32" text="does not match because annotation @MethodAnnotation has @Target{ElementType.METHOD} [Xlint:unmatchedTargetKind]"/>
+               <message kind="warning" line="37" text="does not match because annotation @MethodAnnotation has @Target{ElementType.METHOD} [Xlint:unmatchedTargetKind]"/>
+        </compile>
+    </ajc-test>
+
+       <ajc-test dir="bugs150/pr115252" title="xlint message for improper annotated declaring type">
+        <compile files="AnnotationDeclaringType.java" options="-1.5">
+            <!-- warning coming from matching pointcuts and corresponding declare warnings -->
+                       <message kind="warning" line="13" text="* (@TypeAnnotation *).*(..)"/>
+            <!-- xlint warning that was put in as part of fix for pr115252 -->
+               <message kind="warning" line="27" text="does not match because annotation @MethodAnnotation has @Target{ElementType.METHOD} [Xlint:unmatchedTargetKind]"/>
+        </compile>
+    </ajc-test>
+
+       <ajc-test dir="bugs150/pr115252" title="xlint message for improper annotated parameter type">
+        <compile files="AnnotationParameterType.java" options="-1.5">
+            <!-- warning coming from matching pointcuts and corresponding declare warnings -->
+                       <message kind="warning" line="12" text="* *(@TypeAnnotation *)"/>
+            <!-- xlint warning that was put in as part of fix for pr115252 -->
+               <message kind="warning" line="31" text="does not match because annotation @MethodAnnotation has @Target{ElementType.METHOD} [Xlint:unmatchedTargetKind]"/>
+        </compile>
+    </ajc-test>
+
+       <ajc-test dir="bugs150/pr115252" title="xlint message for improper annotated throws pattern">
+        <compile files="AnnotationThrowsPattern.java" options="-1.5">
+            <!-- warnings coming from matching pointcuts and corresponding declare warnings -->
+                       <message kind="warning" line="12" text="(* *.*(..) throws (@TypeAnnotation *))"/>
+                       <message kind="warning" line="12" text="* *.*(..) throws !(@MethodAnnotation *)"/>
+                       <message kind="warning" line="14" text="(* *.*(..) throws !(@TypeAnnotation *))"/>
+                       <message kind="warning" line="14" text="* *.*(..) throws !(@MethodAnnotation *)"/>
+            <!-- xlint warnings that were put in as part of fix for pr115252 -->
+               <message kind="warning" line="40" text="does not match because annotation @MethodAnnotation has @Target{ElementType.METHOD} [Xlint:unmatchedTargetKind]"/>
+               <message kind="warning" line="46" text="does not match because annotation @MethodAnnotation has @Target{ElementType.METHOD} [Xlint:unmatchedTargetKind]"/>
+        </compile>
+    </ajc-test>
+
+       <ajc-test dir="bugs150/pr115252" title="xlint message for more than one improper annotated parameter type">
+        <compile files="MoreThanOneTargetAnnotation.java" options="-1.5">
+            <!-- xlint warning that was put in as part of fix for pr115252 -->
+               <message kind="warning" line="28" text="does not match because annotation @MethodAndFieldAnnotation has @Target{ElementType.FIELD,ElementType.METHOD} [Xlint:unmatchedTargetKind]"/>
+               <message kind="warning" line="38" text="does not match because annotation @TypeAndMethodAnnotation has @Target{ElementType.METHOD,ElementType.TYPE} [Xlint:unmatchedTargetKind]"/>
+        </compile>
+    </ajc-test>
+
     <!-- ============================================================================ -->
     <!-- ============================================================================ -->
     
         <compile files="Base.java,Colored.java,WrongTarget.aj" options="-1.5" xlintfile="ignoreTypeNotExposed.properties">
            <message kind="error" line="8" text="The annotation @MethodColoring is disallowed for this location"/>
            <message kind="error" line="9" text="The annotation @TypeColoring is disallowed for this location"/>
-        </compile>
+           <!-- xlint warnings that were put in as part of fix for pr115252 -->
+           <message kind="warning" line="13" text="does not match because annotation @MethodColoring has @Target{ElementType.METHOD} [Xlint:unmatchedTargetKind]"/>
+           <message kind="warning" line="16" text="does not match because annotation @TypeColoring has @Target{ElementType.TYPE} [Xlint:unmatchedTargetKind]"/>
+  </compile>
    </ajc-test>
     
    <ajc-test dir="java5/annotations/declare/atfield" title="declare @field - right target - source weaving">
diff --git a/weaver/src/org/aspectj/weaver/AnnotationTargetKind.java b/weaver/src/org/aspectj/weaver/AnnotationTargetKind.java
new file mode 100644 (file)
index 0000000..e037041
--- /dev/null
@@ -0,0 +1,51 @@
+/********************************************************************
+ * Copyright (c) 2005 Contributors. All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *       Helen Hawkins - Initial implementation
+ *******************************************************************/
+package org.aspectj.weaver;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import org.aspectj.util.TypeSafeEnum;
+
+/**
+ * A TypeSafeEnum similar to the Java5 ElementType Enum
+ */
+public class AnnotationTargetKind extends TypeSafeEnum {
+
+       public AnnotationTargetKind(String name, int key) {
+               super(name, key);
+       }
+       
+    public static AnnotationTargetKind read(DataInputStream s) throws IOException {
+        int key = s.readByte();
+        switch(key) {
+            case 1: return ANNOTATION_TYPE;
+            case 2: return CONSTRUCTOR;
+            case 3: return FIELD;
+            case 4: return LOCAL_VARIABLE;
+            case 5: return METHOD;
+            case 6: return PACKAGE;
+            case 7: return PARAMETER;
+            case 8: return TYPE;
+        }
+        throw new BCException("weird annotation target kind " + key);
+    }
+
+       public static final AnnotationTargetKind ANNOTATION_TYPE = new AnnotationTargetKind("ANNOTATION_TYPE", 1);
+       public static final AnnotationTargetKind CONSTRUCTOR = new AnnotationTargetKind("CONSTRUCTOR", 2);
+       public static final AnnotationTargetKind FIELD = new AnnotationTargetKind("FIELD", 3);
+       public static final AnnotationTargetKind LOCAL_VARIABLE = new AnnotationTargetKind("LOCAL_VARIABLE", 4);
+       public static final AnnotationTargetKind METHOD = new AnnotationTargetKind("METHOD", 5);
+       public static final AnnotationTargetKind PACKAGE = new AnnotationTargetKind("PACKAGE", 6);
+       public static final AnnotationTargetKind PARAMETER = new AnnotationTargetKind("PARAMETER", 7);
+       public static final AnnotationTargetKind TYPE = new AnnotationTargetKind("TYPE", 8);
+
+}
index fe8bda13bbb4db0bb9d8783dd88fd70b03c52826..f2f7dac99a9a73adfd1948f7247c873c0afeb22b 100644 (file)
@@ -185,6 +185,14 @@ public class BoundedReferenceType extends ReferenceType {
                        return resolvedTypeX.getRetentionPolicy();
                }
 
+               public boolean canAnnotationTargetType() {
+                       return resolvedTypeX.canAnnotationTargetType();
+               }
+               
+               public AnnotationTargetKind[] getAnnotationTargetKinds() {
+                       return resolvedTypeX.getAnnotationTargetKinds();
+               }
+               
                public boolean isGeneric() {
                        return resolvedTypeX.isGenericType();
                }
index e8b237079f27823108eba3949605c3eb4e670bde..ff7cb5332573fb4d1a6695dcedfdb30867359e3f 100644 (file)
@@ -51,6 +51,9 @@ public class Lint {
        public final Kind unmatchedSuperTypeInCall = 
                new Kind("unmatchedSuperTypeInCall", "does not match because declaring type is {0}, if match desired use target({1})");
 
+       public final Kind unmatchedTargetKind = 
+               new Kind("unmatchedTargetKind", "does not match because annotation {0} has @Target{1}");
+       
        public final Kind canNotImplementLazyTjp = 
                new Kind("canNotImplementLazyTjp", "can not implement lazyTjp on this joinpoint {0} because around advice is used");
 
index 22a21a12c077f0a24a7ede0a8401cb10609a9e30..fbf9ec0df3c7c818aa95f271866e8c37527360fa 100644 (file)
@@ -158,6 +158,14 @@ public class ReferenceType extends ResolvedType {
     public boolean isAnnotationWithRuntimeRetention() {
         return delegate.isAnnotationWithRuntimeRetention();
     }
+    
+    public boolean canAnnotationTargetType() {
+       return delegate.canAnnotationTargetType();
+    }
+    
+    public AnnotationTargetKind[] getAnnotationTargetKinds() {
+       return delegate.getAnnotationTargetKinds();
+    }
       
     // true iff the statement "this = (ThisType) other" would compile
     public final boolean isCoerceableFrom(ResolvedType o) {
index 2c49ef54d57fc1df4d6f2ae602964488cfa6b924..d00a4d288099106f640900d53b43d89d8cad3a9b 100644 (file)
@@ -25,8 +25,6 @@ public interface ReferenceTypeDelegate {
        // TODO asc move to proxy
        public void addAnnotation(AnnotationX annotationX);
        public void ensureDelegateConsistent(); // Required evil because of mutator methods in delegates :(  (see pr85132)
-
-       
        
        public boolean isAspect();
     public boolean isAnnotationStyleAspect();
@@ -34,6 +32,8 @@ public interface ReferenceTypeDelegate {
     public boolean isEnum();
     public boolean isAnnotation();
     public String getRetentionPolicy();
+    public boolean canAnnotationTargetType();
+    public AnnotationTargetKind[] getAnnotationTargetKinds();
     public boolean isAnnotationWithRuntimeRetention();
        public boolean isClass();
        public boolean isGeneric();
@@ -61,4 +61,5 @@ public interface ReferenceTypeDelegate {
        public boolean doesNotExposeShadowMungers();
        
        public String getDeclaredGenericSignature();
+       
 }
\ No newline at end of file
index e4cbb5be7db30338f0ae0b20d7300e2a6b03e961..a590b7440c66f867911032578fa211c6224482c3 100644 (file)
@@ -633,8 +633,21 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl
        public AnnotationX[] getAnnotations() {
                throw new RuntimeException("ResolvedType.getAnnotations() should never be called");
        }
-
     
+       /**
+        * Note: Only overridden by ReferenceType subtype
+        */
+       public boolean canAnnotationTargetType() {
+               return false;
+       }
+       
+       /**
+        * Note: Only overridden by ReferenceType subtype
+        */     
+       public AnnotationTargetKind[] getAnnotationTargetKinds() {
+               return null;
+       }
+       
     /**
      * Note: Only overridden by Name subtype.
      */
index bb40c00cde4a16f6c69905b659ac7a98869fee59..e495f4aa4cf81bbbe6990a90a797c67e45088278 100644 (file)
@@ -32,3 +32,5 @@ uncheckedArgument = warning
 noExplicitConstructorCall = warning
 
 aspectExcludedByConfiguration = ignore
+
+unmatchedTargetKind = warning
index cacd98fa00ef651dc5278b1fcbba753738d1e80e..a6d499a9a11505c68e4159ff6dd58cc76a7138eb 100644 (file)
@@ -33,6 +33,7 @@ import org.aspectj.bridge.ISourceLocation;
 import org.aspectj.weaver.AbstractReferenceTypeDelegate;
 import org.aspectj.weaver.AjAttribute;
 import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.AnnotationTargetKind;
 import org.aspectj.weaver.AnnotationX;
 import org.aspectj.weaver.BCException;
 import org.aspectj.weaver.ReferenceType;
@@ -88,6 +89,8 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate {
        
        private boolean discoveredRetentionPolicy = false;
        private String retentionPolicy;
+       private boolean discoveredAnnotationTargetKinds = false;
+       private AnnotationTargetKind[] annotationTargetKinds;
        
        
        /**
@@ -470,6 +473,60 @@ public class BcelObjectType extends AbstractReferenceTypeDelegate {
            return retentionPolicy;
        }
        
+       public boolean canAnnotationTargetType() {
+               AnnotationTargetKind[] targetKinds = getAnnotationTargetKinds();
+               if (targetKinds == null) return true;
+               for (int i = 0; i < targetKinds.length; i++) {
+                       if (targetKinds[i].equals(AnnotationTargetKind.TYPE)) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+       
+       public AnnotationTargetKind[] getAnnotationTargetKinds() {
+               if (discoveredAnnotationTargetKinds) return annotationTargetKinds;
+               discoveredAnnotationTargetKinds = true;
+               annotationTargetKinds = null; // null means we have no idea or the @Target annotation hasn't been used
+               List targetKinds = new ArrayList();
+               if (isAnnotation()) {
+               Annotation[] annotationsOnThisType = javaClass.getAnnotations();
+               for (int i = 0; i < annotationsOnThisType.length; i++) {
+                   Annotation a = annotationsOnThisType[i];
+                   if (a.getTypeName().equals(UnresolvedType.AT_TARGET.getName())) {
+                       List values = a.getValues();
+                       for (Iterator it = values.iterator(); it.hasNext();) {
+                        ElementNameValuePair element = (ElementNameValuePair) it.next();
+                        ElementValue v = element.getValue();
+                        String targetKind = v.stringifyValue();
+                        if (targetKind.equals("ANNOTATION_TYPE")) {
+                                                       targetKinds.add(AnnotationTargetKind.ANNOTATION_TYPE);
+                        } else if (targetKind.equals("CONSTRUCTOR")) {
+                                                       targetKinds.add(AnnotationTargetKind.CONSTRUCTOR);
+                                               } else if (targetKind.equals("FIELD")) {
+                                                       targetKinds.add(AnnotationTargetKind.FIELD);
+                                               } else if (targetKind.equals("LOCAL_VARIABLE")) {
+                                                       targetKinds.add(AnnotationTargetKind.LOCAL_VARIABLE);
+                                               } else if (targetKind.equals("METHOD")) {
+                                                       targetKinds.add(AnnotationTargetKind.METHOD);
+                                               } else if (targetKind.equals("PACKAGE")) {
+                                                       targetKinds.add(AnnotationTargetKind.PACKAGE);
+                                               } else if (targetKind.equals("PARAMETER")) {
+                                                       targetKinds.add(AnnotationTargetKind.PARAMETER);
+                                               } else if (targetKind.equals("TYPE")) {
+                                                       targetKinds.add(AnnotationTargetKind.TYPE);
+                                               } 
+                    }
+                   }
+               }
+                       if (!targetKinds.isEmpty()) {
+                               annotationTargetKinds = new AnnotationTargetKind[targetKinds.size()];
+                               return (AnnotationTargetKind[]) targetKinds.toArray(annotationTargetKinds);     
+                       }
+               }
+               return annotationTargetKinds;
+       }
+       
        public boolean isSynthetic() {
                return getResolvedTypeX().isSynthetic();
        }
index 1581309794a58fb8daf1e098090b43b1098bcc95..3759d12d7749b38f3c4937f3baaa15e6dd92ba5a 100644 (file)
@@ -18,16 +18,20 @@ import java.io.IOException;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
+import org.aspectj.bridge.ISourceLocation;
 import org.aspectj.lang.Signature;
 import org.aspectj.lang.reflect.FieldSignature;
 import org.aspectj.lang.reflect.MethodSignature;
 import org.aspectj.util.FuzzyBoolean;
 import org.aspectj.weaver.AjAttribute;
 import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.AnnotationTargetKind;
 import org.aspectj.weaver.Constants;
 import org.aspectj.weaver.ISourceContext;
 import org.aspectj.weaver.JoinPointSignature;
@@ -71,23 +75,175 @@ public class SignaturePattern extends PatternNode {
     public SignaturePattern resolveBindings(IScope scope, Bindings bindings) { 
                if (returnType != null) {
                        returnType = returnType.resolveBindings(scope, bindings, false, false);
+                       checkForIncorrectTargetKind(returnType,scope,false);
                } 
                if (declaringType != null) {
                        declaringType = declaringType.resolveBindings(scope, bindings, false, false);
+                       checkForIncorrectTargetKind(declaringType,scope,false);
                }
                if (parameterTypes != null) {
                        parameterTypes = parameterTypes.resolveBindings(scope, bindings, false, false);
+                       checkForIncorrectTargetKind(parameterTypes,scope,false);
                }
                if (throwsPattern != null) {
                        throwsPattern = throwsPattern.resolveBindings(scope, bindings);
+                       if (throwsPattern.getForbidden().getTypePatterns().length > 0 
+                                       || throwsPattern.getRequired().getTypePatterns().length > 0) {
+                               checkForIncorrectTargetKind(throwsPattern,scope,false);                         
+                       }
                }
                if (annotationPattern != null) {
                        annotationPattern = annotationPattern.resolveBindings(scope,bindings,false);
+                       checkForIncorrectTargetKind(annotationPattern,scope,true);
                }
                
        return this;
     }
     
+    // bug 115252 - adding an xlint warning if the annnotation target type is 
+    // wrong. This logic, or similar, may have to be applied elsewhere in the case
+    // of pointcuts which don't go through SignaturePattern.resolveBindings(..)
+    private void checkForIncorrectTargetKind(PatternNode patternNode, IScope scope, boolean targetsOtherThanTypeAllowed) {
+       // return if we're not in java5 mode, if the unmatchedTargetKind Xlint
+       // warning has been turned off, or if the patternNode is *
+       if (!scope.getWorld().isInJava5Mode()
+                       || scope.getWorld().getLint().unmatchedTargetKind == null
+                       || (patternNode instanceof AnyTypePattern)) {
+                       return;
+               }
+               if (patternNode instanceof ExactAnnotationTypePattern) {
+                       ResolvedType resolvedType = ((ExactAnnotationTypePattern)patternNode).getAnnotationType().resolve(scope.getWorld());
+                       if (targetsOtherThanTypeAllowed) {
+                               AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
+                               if (targetKinds == null) return;
+                               reportUnmatchedTargetKindMessage(targetKinds,patternNode,scope,true);
+                       } else if (!targetsOtherThanTypeAllowed && !resolvedType.canAnnotationTargetType()) {
+                               // everything is incorrect since we've already checked whether we have the TYPE target annotation
+                               AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
+                               if (targetKinds == null) return;
+                               reportUnmatchedTargetKindMessage(targetKinds,patternNode,scope,false);
+                       }
+               } else {
+                       TypePatternVisitor visitor = new TypePatternVisitor(scope,targetsOtherThanTypeAllowed);
+                       patternNode.traverse(visitor,null);
+                       if (visitor.containedIncorrectTargetKind()) {
+                               Set keys = visitor.getIncorrectTargetKinds().keySet();                          
+                               for (Iterator iter = keys.iterator(); iter.hasNext();) {
+                                       PatternNode node = (PatternNode)iter.next();
+                                       AnnotationTargetKind[] targetKinds =  (AnnotationTargetKind[]) visitor.getIncorrectTargetKinds().get(node);
+                                       reportUnmatchedTargetKindMessage(targetKinds,node,scope,false);
+                               }
+                       }
+               }
+    }
+    
+    private void reportUnmatchedTargetKindMessage(
+               AnnotationTargetKind[] annotationTargetKinds,  
+               PatternNode node,
+               IScope scope,
+               boolean checkMatchesMemberKindName) {
+       StringBuffer targetNames = new StringBuffer("{");
+       for (int i = 0; i < annotationTargetKinds.length; i++) {
+                       AnnotationTargetKind targetKind = annotationTargetKinds[i];
+                       if (checkMatchesMemberKindName && kind.getName().equals(targetKind.getName())) {
+                               return;
+                       }
+                       if (i < (annotationTargetKinds.length - 1)) {
+                               targetNames.append("ElementType." + targetKind.getName() + ",");
+                       } else {
+                               targetNames.append("ElementType." + targetKind.getName() + "}");
+                       }
+               }
+               scope.getWorld().getLint().unmatchedTargetKind.signal(new String[] {node.toString(),targetNames.toString()}, getSourceLocation(), new ISourceLocation[0]);
+    }
+    
+    /**
+     * Class which visits the nodes in the TypePattern tree until an
+     * ExactTypePattern is found. Once this is found it creates a new
+     * ExactAnnotationTypePattern and checks whether the targetKind
+     * (created via the @Target annotation) matches ElementType.TYPE if
+     * this is the only target kind which is allowed, or matches the
+     * signature pattern kind if there is no restriction.
+     */
+    private class TypePatternVisitor extends AbstractPatternNodeVisitor {
+
+       private IScope scope;
+       private Map incorrectTargetKinds /* PatternNode -> AnnotationTargetKind[] */ = new HashMap();
+       private boolean targetsOtherThanTypeAllowed;
+
+       /**
+        * @param requiredTarget - the signature pattern Kind
+        * @param scope
+        */
+       public TypePatternVisitor(IScope scope, boolean targetsOtherThanTypeAllowed) {
+               this.scope = scope;
+               this.targetsOtherThanTypeAllowed = targetsOtherThanTypeAllowed;
+       }
+       
+       public Object visit(WildAnnotationTypePattern node, Object data) {
+               node.getTypePattern().accept(this,data);
+               return node;
+       }
+       
+       /**
+        * Do the ExactAnnotationTypePatterns have the incorrect target?
+        */
+       public Object visit(ExactAnnotationTypePattern node, Object data) {
+               ResolvedType resolvedType = node.getAnnotationType().resolve(scope.getWorld());
+                       if (targetsOtherThanTypeAllowed) {
+                               AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
+                               if (targetKinds == null) return data;
+                               List incorrectTargets = new ArrayList();
+                               for (int i = 0; i < targetKinds.length; i++) {
+                                       if (targetKinds[i].getName().equals(kind.getName())) {
+                                               return data;
+                                       }
+                                       incorrectTargets.add(targetKinds[i]);
+                               }
+                               if (incorrectTargets.isEmpty()) return data;
+                               AnnotationTargetKind[] kinds = new AnnotationTargetKind[incorrectTargets.size()];
+                               incorrectTargetKinds.put(node,(AnnotationTargetKind[]) incorrectTargets.toArray(kinds));        
+                       } else if (!targetsOtherThanTypeAllowed && !resolvedType.canAnnotationTargetType()) {
+                               AnnotationTargetKind[] targetKinds = resolvedType.getAnnotationTargetKinds();
+                               if (targetKinds == null) return data;
+                               incorrectTargetKinds.put(node,targetKinds);
+                       }
+               return data;
+       }
+       
+       public Object visit(ExactTypePattern node, Object data) {
+               ExactAnnotationTypePattern eatp =  new ExactAnnotationTypePattern(node.getExactType().resolve(scope.getWorld()));
+               eatp.accept(this,data);         
+               return data;
+       }
+       
+       public Object visit(AndTypePattern node, Object data) {
+               node.getLeft().accept(this,data);
+               node.getRight().accept(this,data);
+               return node;
+       }
+
+       public Object visit(OrTypePattern node, Object data) {
+               node.getLeft().accept(this,data);
+               node.getRight().accept(this,data);
+               return node;
+       }
+
+       public Object visit(AnyWithAnnotationTypePattern node, Object data) {
+               node.getAnnotationPattern().accept(this,data);
+               return node;
+       }
+       
+       public boolean containedIncorrectTargetKind() {
+               return (incorrectTargetKinds.size() != 0);
+       }
+       
+       public Map getIncorrectTargetKinds() {
+               return incorrectTargetKinds;
+       }
+    }
+    
+    
        public void postRead(ResolvedType enclosingType) {
                if (returnType != null) {
                        returnType.postRead(enclosingType);
index 61cf94cf261a5e8ac33a28e49bb6fc2a9e30bf41..622e8c1433d6d611a862df61dd40001c4335b253 100644 (file)
@@ -17,6 +17,7 @@ import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.Collections;
 
+import org.aspectj.weaver.AnnotationTargetKind;
 import org.aspectj.weaver.AnnotationX;
 import org.aspectj.weaver.ReferenceType;
 import org.aspectj.weaver.ReferenceTypeDelegate;
@@ -132,6 +133,14 @@ public class ReflectionBasedReferenceTypeDelegate implements ReferenceTypeDelega
                return null;
        }
 
+       public boolean canAnnotationTargetType() {
+               return false;
+       }
+       
+       public AnnotationTargetKind[] getAnnotationTargetKinds() {
+               return null;
+       }
+       
        /* (non-Javadoc)
         * @see org.aspectj.weaver.ReferenceTypeDelegate#isClass()
         */