]> source.dussan.org Git - aspectj.git/commitdiff
Java8 support: methodparameters, typeannotations
authorAndy Clement <andrew.clement@gmail.com>
Fri, 24 May 2013 23:45:27 +0000 (16:45 -0700)
committerAndy Clement <andrew.clement@gmail.com>
Fri, 24 May 2013 23:45:27 +0000 (16:45 -0700)
Can read/write MethodParameters attribute.
Can read/write type annotation attributes.

16 files changed:
bcel-builder/src/org/aspectj/apache/bcel/Constants.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/Attribute.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/ClassVisitor.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/Method.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/AnnotationGen.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/ElementValue.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeAnnos.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisAnnos.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisParamAnnos.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeParamAnnos.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisAnnos.java
bcel-builder/src/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisParamAnnos.java
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/BcelTestCase.java
bcel-builder/testsrc/org/aspectj/apache/bcel/classfile/tests/TypeAnnotationsTest.java
bcel-builder/verifier-src/org/aspectj/apache/bcel/verifier/DescendingVisitor.java
bcel-builder/verifier-src/org/aspectj/apache/bcel/verifier/EmptyClassVisitor.java

index 2604d8e5460b24e2c53dcfe2c720d34f0d775954..4499284c202f8ea4c458abba03a30fc92132310d 100644 (file)
@@ -59,8 +59,8 @@ import org.aspectj.apache.bcel.generic.Type;
 /**
  * Constants for the project, mostly defined in the JVM specification.
  * 
- * @version $Id: Constants.java,v 1.7 2011/09/28 01:14:54 aclement Exp $
  * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
+ * @author Andy Clement
  */
 public interface Constants {
        // Major and minor version of the code
@@ -76,6 +76,10 @@ public interface Constants {
        public final static short MINOR_1_5 = 0;
        public final static short MAJOR_1_6 = 50;
        public final static short MINOR_1_6 = 0;
+       public final static short MAJOR_1_7 = 51;
+       public final static short MINOR_1_7 = 0;
+       public final static short MAJOR_1_8 = 52;
+       public final static short MINOR_1_8 = 0;
        // Defaults
        public final static short MAJOR = MAJOR_1_1;
        public final static short MINOR = MINOR_1_1;
@@ -609,13 +613,20 @@ public interface Constants {
        public static final byte ATTR_ENCLOSING_METHOD = 17;
        public static final byte ATTR_ANNOTATION_DEFAULT = 18;
        public static final byte ATTR_BOOTSTRAPMETHODS = 19;
-
-       public static final short KNOWN_ATTRIBUTES = 20;
-
-       public static final String[] ATTRIBUTE_NAMES = { "SourceFile", "ConstantValue", "Code", "Exceptions", "LineNumberTable",
-                       "LocalVariableTable", "InnerClasses", "Synthetic", "Deprecated", "PMGClass", "Signature", "StackMap",
-                       "RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", "RuntimeVisibleParameterAnnotations",
-                       "RuntimeInvisibleParameterAnnotations", "LocalVariableTypeTable", "EnclosingMethod", "AnnotationDefault","BootstrapMethods" };
+       public static final byte ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = 20;
+       public static final byte ATTR_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = 21;
+       public static final byte ATTR_METHOD_PARAMETERS = 22;
+
+       public static final short KNOWN_ATTRIBUTES = 23;
+
+       public static final String[] ATTRIBUTE_NAMES = { 
+               "SourceFile", "ConstantValue", "Code", "Exceptions", "LineNumberTable", "LocalVariableTable",
+               "InnerClasses", "Synthetic", "Deprecated", "PMGClass", "Signature", "StackMap",
+               "RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", "RuntimeVisibleParameterAnnotations",
+               "RuntimeInvisibleParameterAnnotations", "LocalVariableTypeTable", "EnclosingMethod", 
+               "AnnotationDefault","BootstrapMethods", "RuntimeVisibleTypeAnnotations", "RuntimeInvisibleTypeAnnotations",
+               "MethodParameters"
+               };
 
        /**
         * Constants used in the StackMap attribute.
index 939fa36be78064e3370c624e1eb6938318f35a3e..817628295a759ad511dc6da5f19e6f02da8ba299 100644 (file)
@@ -64,6 +64,7 @@ import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisParamAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisParamAnnos;
+import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisTypeAnnos;
 
 /**
  * Abstract super class for <em>Attribute</em> objects. Currently the <em>ConstantValue</em>, <em>SourceFile</em>, <em>Code</em>,
@@ -159,6 +160,10 @@ public abstract class Attribute implements Cloneable, Node, Serializable {
                        return new EnclosingMethod(idx, len, file, cpool);
                case Constants.ATTR_BOOTSTRAPMETHODS:
                        return new BootstrapMethods(idx,len,file,cpool);
+               case Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS:
+                       return new RuntimeVisTypeAnnos(idx, len, file, cpool);
+               case Constants.ATTR_METHOD_PARAMETERS:
+                       return new MethodParameters(idx, len, file, cpool);
                default:
                        throw new IllegalStateException();
                }
index c411cb5d691b8eeb949a6100321cfc2b36458783..9280083a86130b2e03a87e7937a1b5f05cc2e8fc 100644 (file)
@@ -2,8 +2,10 @@ package org.aspectj.apache.bcel.classfile;
 
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisParamAnnos;
+import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisTypeAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisParamAnnos;
+import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisTypeAnnos;
 
 /* ====================================================================
  * The Apache Software License, Version 1.1
@@ -151,7 +153,13 @@ public interface ClassVisitor {
 
        public void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisParamAnnos obj);
 
+       public void visitRuntimeVisibleTypeAnnotations(RuntimeVisTypeAnnos obj);
+
+       public void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisTypeAnnos obj);
+
        public void visitAnnotationDefault(AnnotationDefault obj);
 
        public void visitLocalVariableTypeTable(LocalVariableTypeTable obj);
+
+       public void visitMethodParameters(MethodParameters methodParameters);
 }
index d354b7fe1942038658b99f8c425380d3a1c1dd35..46aeac84504a518b9446ab05ef9c60e9cc263a30 100644 (file)
@@ -1,5 +1,3 @@
-package org.aspectj.apache.bcel.classfile;
-
 /* ====================================================================
  * The Apache Software License, Version 1.1
  *
@@ -53,6 +51,8 @@ package org.aspectj.apache.bcel.classfile;
  * information on the Apache Software Foundation, please see
  * <http://www.apache.org/>.
  */
+package org.aspectj.apache.bcel.classfile;
+
 import java.io.DataInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
index af442522d69d00f847d765caafda2de1fc89a447..9a0a4290987161622c047930ea1760598a221c3a 100644 (file)
@@ -1,5 +1,5 @@
 /* *******************************************************************
- * Copyright (c) 2004 IBM Corporation
+ * Copyright (c) 2004, 2013 IBM Corporation
  * 
  * All rights reserved. 
  * This program and the accompanying materials are made available 
@@ -127,13 +127,16 @@ public class AnnotationGen {
 
        public String toShortString() {
                StringBuffer s = new StringBuffer();
-               s.append("@" + getTypeName() + "(");
-               for (int i = 0; i < pairs.size(); i++) {
-                       s.append(pairs.get(i));
-                       if (i + 1 < pairs.size())
-                               s.append(",");
+               s.append("@").append(getTypeName());
+               if (pairs.size()!=0) {
+                       s.append("(");
+                       for (int i = 0; i < pairs.size(); i++) {
+                               s.append(pairs.get(i));
+                               if (i + 1 < pairs.size())
+                                       s.append(",");
+                       }
+                       s.append(")");
                }
-               s.append(")");
                return s.toString();
        }
 
index 511afe2b164731b41753321d73c9802652ffb11c..06f7c727300841b713394903711c9d2490e96b3c 100644 (file)
@@ -1,5 +1,5 @@
 /* *******************************************************************
- * Copyright (c) 2004 IBM
+ * Copyright (c) 2004, 2013 IBM, VMware
  * All rights reserved. 
  * This program and the accompanying materials are made available 
  * under the terms of the Eclipse Public License v1.0 
index a6b6534dffa203df5d4483572c5cb89ea5be45a4..05c83a6ee8beb8e10e57092a86241830df311a36 100644 (file)
@@ -1,3 +1,14 @@
+/* *******************************************************************
+ * Copyright (c) 2004, 2013 IBM, VMware
+ * 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://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement -     initial implementation {date}
+ * ******************************************************************/
 package org.aspectj.apache.bcel.classfile.annotation;
 
 import java.io.ByteArrayInputStream;
index a2ab520d3c5cfefa73064ca3a5dcbe3adfaab402..a6b2e529f1c371826afba22affd7b80fd7feb504 100644 (file)
@@ -1,3 +1,14 @@
+/* *******************************************************************
+ * Copyright (c) 2004, 2013 IBM, VMware
+ * 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://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement -     initial implementation {date}
+ * ******************************************************************/
 package org.aspectj.apache.bcel.classfile.annotation;
 
 import java.io.DataInputStream;
index b5d7bb1195b21d577125320d2582666a4b985753..cb2eb8d7a8a9a097d7d5e7f2b5f0bc716a6b35f1 100644 (file)
@@ -1,3 +1,14 @@
+/* *******************************************************************
+ * Copyright (c) 2004, 2013 IBM, VMware
+ * 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://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement -     initial implementation {date}
+ * ******************************************************************/
 package org.aspectj.apache.bcel.classfile.annotation;
 
 import java.io.DataInputStream;
index 4bd8644c5a3ef83d4a23e270c7b1791987a24ac0..ad92c9fceaf3a91e5ade0b425163175e4410afff 100644 (file)
@@ -1,3 +1,14 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM
+ * 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://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement -     initial implementation {date}
+ * ******************************************************************/
 package org.aspectj.apache.bcel.classfile.annotation;
 
 import java.io.ByteArrayInputStream;
@@ -12,7 +23,7 @@ import org.aspectj.apache.bcel.classfile.ConstantPool;
 
 public abstract class RuntimeParamAnnos extends Attribute {
        
-       private List /*Annotation[]*/<AnnotationGen[]> parameterAnnotations;
+       private List<AnnotationGen[]> parameterAnnotations;
        private boolean visible;
        
 
index aa3f49eac74202ab2675d94d9148d4f541372313..3b07cccc70647c159258fd64971eecc5d0d3ad47 100644 (file)
@@ -1,3 +1,14 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM
+ * 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://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement -     initial implementation {date}
+ * ******************************************************************/
 package org.aspectj.apache.bcel.classfile.annotation;
 
 import java.io.DataInputStream;
index ccd1aa7d2dc545c252087783adabc3098f68190c..b47d8aac11354702fff48dfebf4265fbd0b0831f 100644 (file)
@@ -1,3 +1,14 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM
+ * 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://www.eclipse.org/legal/epl-v10.html 
+ *  
+ * Contributors: 
+ *     Andy Clement -     initial implementation {date}
+ * ******************************************************************/
 package org.aspectj.apache.bcel.classfile.annotation;
 
 import java.io.DataInputStream;
index 2689aae0408147ede798a0ab213d36ebc10f8a80..3311c538675afdeebbf57acf26e4aa1dffdc4499 100644 (file)
@@ -1,5 +1,5 @@
 /* *******************************************************************
- * Copyright (c) 2004 IBM
+ * Copyright (c) 2004, 2013 IBM, VMware
  * All rights reserved. 
  * This program and the accompanying materials are made available 
  * under the terms of the Eclipse Public License v1.0 
@@ -20,6 +20,7 @@ import junit.framework.TestCase;
 
 import org.aspectj.apache.bcel.classfile.Attribute;
 import org.aspectj.apache.bcel.classfile.ConstantPool;
+import org.aspectj.apache.bcel.classfile.Field;
 import org.aspectj.apache.bcel.classfile.JavaClass;
 import org.aspectj.apache.bcel.classfile.Method;
 import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
@@ -47,6 +48,11 @@ public class BcelTestCase extends TestCase {
                return repos.loadClass(clazzname);
        }
 
+       protected JavaClass getClassFromJava8Jar(String clazzname) throws ClassNotFoundException {
+               SyntheticRepository repos = createRepos("java8testcode.jar");
+               return repos.loadClass(clazzname);
+       }
+
        protected Method getMethod(JavaClass cl, String methodname) {
                Method[] methods = cl.getMethods();
                for (int i = 0; i < methods.length; i++) {
@@ -58,6 +64,17 @@ public class BcelTestCase extends TestCase {
                return null;
        }
 
+       protected Field getField(JavaClass cl, String fieldname) {
+               Field[] fields = cl.getFields();
+               for (int i = 0; i < fields.length; i++) {
+                       Field f = fields[i];
+                       if (f.getName().equals(fieldname)) {
+                               return f;
+                       }
+               }
+               return null;
+       }
+
        protected boolean wipe(String name) {
                return new File("testdata" + File.separator + name).delete();
        }
@@ -148,5 +165,14 @@ public class BcelTestCase extends TestCase {
                elements.add(nvGen);
                return new AnnotationGen(t, elements, visibility, cp);
        }
+       
+       public Attribute getAttribute(Attribute[] attrs, byte tag) {
+               for (Attribute attr: attrs) {
+                       if (attr.getTag() == tag) {
+                               return attr;
+                       }
+               }
+               return null;
+       }
 
 }
index dcb36432f9211b48fc08153611e04b05b3f438bc..df4c2a4016d02b90b29288695962c4f7f2d906bb 100644 (file)
@@ -1,5 +1,5 @@
 /* *******************************************************************
- * Copyright (c) 2004 IBM
+ * Copyright (c) 2013 VMware
  * All rights reserved. 
  * This program and the accompanying materials are made available 
  * under the terms of the Eclipse Public License v1.0 
  * Contributors: 
  *     Andy Clement -     initial implementation 
  * ******************************************************************/
-
 package org.aspectj.apache.bcel.classfile.tests;
 
+import org.aspectj.apache.bcel.Constants;
+import org.aspectj.apache.bcel.classfile.Attribute;
+import org.aspectj.apache.bcel.classfile.Field;
 import org.aspectj.apache.bcel.classfile.JavaClass;
-import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
-import org.aspectj.apache.bcel.generic.ClassGen;
-
+import org.aspectj.apache.bcel.classfile.Method;
+import org.aspectj.apache.bcel.classfile.annotation.RuntimeTypeAnnos;
+import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisTypeAnnos;
+import org.aspectj.apache.bcel.classfile.annotation.TypeAnnotationGen;
 
 public class TypeAnnotationsTest extends BcelTestCase {
        
-
        protected void setUp() throws Exception {
                super.setUp();
        }
        
-       public void testMarkerAnnotationsOnTypes() throws ClassNotFoundException {
-               JavaClass clazz = getClassFromJar("MarkedType");
-               ClassGen cg = new ClassGen(clazz);
-               AnnotationGen[] annotations = cg.getAnnotations();
-               assertTrue("Should be a MarkerAnnotation and a MarkerAnnotationInvisible - but found: "+annotations.length,annotations.length==2);
+       public Attribute getAttribute(Attribute[] attrs, byte tag) {
+               for (Attribute attr: attrs) {
+                       if (attr.getTag() == tag) {
+                               return attr;
+                       }
+               }
+               return null;
        }
        
+       public void testClassTypeParameter() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnClassTypeParameter");
+               RuntimeVisTypeAnnos rvta = (RuntimeVisTypeAnnos)getAttribute(jc.getAttributes(), Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
+               assertTrue(rvta.areVisible());
+               TypeAnnotationGen[] tas = rvta.getTypeAnnotations();
+               assertEquals(2,tas.length);
+               checkTypeAnnotationClassTypeParameter(tas[0],0,"@Anno");
+               checkTypeAnnotationClassTypeParameter(tas[1],1,"@Anno(value=2)");
+       }
+       
+       public void testMethodTypeParameter() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnMethodTypeParameter");
+               Method m = getMethod(jc, "m");
+               RuntimeVisTypeAnnos rvta = (RuntimeVisTypeAnnos)getAttribute(m.getAttributes(), Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
+               assertTrue(rvta.areVisible());
+               TypeAnnotationGen[] tas = rvta.getTypeAnnotations();
+               assertEquals(1,tas.length);
+               checkTypeAnnotationMethodTypeParameter(tas[0],0,"@Anno");
+       }
+       
+       public void testSuperinterface() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnSuperinterface1");
+               RuntimeVisTypeAnnos rvta = (RuntimeVisTypeAnnos)getAttribute(jc.getAttributes(), Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
+               assertTrue(rvta.areVisible());
+               TypeAnnotationGen[] tas = rvta.getTypeAnnotations();
+               assertEquals(1,tas.length);
+               TypeAnnotationGen ta = tas[0];
+               checkTypeAnnotationClassExtends(ta, 0, "@Anno");
+       }
+       
+       public void testSupertypes() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnSupertypes");
+               RuntimeVisTypeAnnos rvta = (RuntimeVisTypeAnnos)getAttribute(jc.getAttributes(), Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
+               assertTrue(rvta.areVisible());
+               TypeAnnotationGen[] tas = rvta.getTypeAnnotations();
+               assertEquals(3,tas.length);
+               checkTypeAnnotationClassExtends(tas[0],-1,"@Anno(value=1)");
+               checkTypeAnnotationClassExtends(tas[1],0,"@Anno");
+               checkTypeAnnotationClassExtends(tas[2],1,"@Anno(value=2)");
+       }
+
+       public void testClassTypeParameterBound() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnClassTypeParameterBound");
+               RuntimeVisTypeAnnos rvta = (RuntimeVisTypeAnnos)getAttribute(jc.getAttributes(), Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
+               assertTrue(rvta.areVisible());
+               TypeAnnotationGen[] tas = rvta.getTypeAnnotations();
+               assertEquals(3,tas.length);
+               checkTypeAnnotationClassTypeParameterBound(tas[0],0,0,"@Anno");
+               checkTypePath(tas[0],TypeAnnotationGen.NO_TYPE_PATH);
+               checkTypeAnnotationClassTypeParameterBound(tas[1],0,1,"@Anno(value=2)");
+               checkTypePath(tas[1],TypeAnnotationGen.NO_TYPE_PATH);
+               checkTypeAnnotationClassTypeParameterBound(tas[2],0,1,"@Anno(value=3)");
+               checkTypePath(tas[2],new int[]{TypeAnnotationGen.TYPE_PATH_ENTRY_KIND_TYPE_ARGUMENT,0});
+       }
+
+       public void testMethodTypeParameterBound() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnMethodTypeParameterBound");
+               Method m = getMethod(jc, "m");
+               RuntimeVisTypeAnnos rvta = (RuntimeVisTypeAnnos)getAttribute(m.getAttributes(), Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
+               assertTrue(rvta.areVisible());
+               TypeAnnotationGen[] tas = rvta.getTypeAnnotations();
+               assertEquals(3,tas.length);
+               checkTypeAnnotationMethodTypeParameterBound(tas[0],0,0,"@Anno");
+               checkTypePath(tas[0],TypeAnnotationGen.NO_TYPE_PATH);
+               checkTypeAnnotationMethodTypeParameterBound(tas[1],0,1,"@Anno(value=2)");
+               checkTypePath(tas[1],TypeAnnotationGen.NO_TYPE_PATH);
+               checkTypeAnnotationMethodTypeParameterBound(tas[2],0,1,"@Anno(value=3)");
+               checkTypePath(tas[2],new int[]{TypeAnnotationGen.TYPE_PATH_ENTRY_KIND_TYPE_ARGUMENT,1});
+       }
+
+       public void testField() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnField");
+               Field f = getField(jc,"f1");
+               RuntimeVisTypeAnnos rvta = (RuntimeVisTypeAnnos)getAttribute(f.getAttributes(), Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
+               assertTrue(rvta.areVisible());
+               TypeAnnotationGen[] tas = rvta.getTypeAnnotations();
+               assertEquals(1,tas.length);
+               checkTypeAnnotationField(tas[0],"@Anno");
+               checkTypePath(tas[0],TypeAnnotationGen.NO_TYPE_PATH);
+               
+               tas = getTypeAnnotations(getField(jc,"f2"),true);
+               checkTypeAnnotationField(tas[0],"@Anno");
+               checkTypePath(tas[0],new int[]{TypeAnnotationGen.TYPE_PATH_ENTRY_KIND_TYPE_ARGUMENT,0});
+               
+               tas = getTypeAnnotations(getField(jc,"f3"),true);
+               checkTypeAnnotationField(tas[0],"@Anno");
+               checkTypePath(tas[0],new int[]{TypeAnnotationGen.TYPE_PATH_ENTRY_KIND_ARRAY,0});
+               
+               tas = getTypeAnnotations(getField(jc,"f4"),true);
+               checkTypeAnnotationField(tas[0],"@Anno");
+               checkTypePath(tas[0],new int[]{
+                               TypeAnnotationGen.TYPE_PATH_ENTRY_KIND_ARRAY,0,
+                               TypeAnnotationGen.TYPE_PATH_ENTRY_KIND_TYPE_ARGUMENT,0
+                               });
+       }
+
+       public void testMethodReturn() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnMethodReturn");
+               TypeAnnotationGen[] tas = getTypeAnnotations(getMethod(jc,"m"), true);
+               checkTypeAnnotationMethodReturn(tas[0],"@Anno");
+               checkTypePath(tas[0],TypeAnnotationGen.NO_TYPE_PATH);
+       }
+
+       public void testMethodReceiver() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnMethodReceiver");
+               TypeAnnotationGen[] tas = getTypeAnnotations(getMethod(jc,"m"), true);
+               checkTypeAnnotationMethodReceiver(tas[0],"@Anno");
+               checkTypePath(tas[0],TypeAnnotationGen.NO_TYPE_PATH);
+       }
+
+       public void testMethodFormalParameter() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnMethodFormalParameter");
+               TypeAnnotationGen[] tas = getTypeAnnotations(getMethod(jc,"m"), true);
+               checkTypeAnnotationMethodFormalParameter(tas[0],0, "@Anno");
+               checkTypePath(tas[0],TypeAnnotationGen.NO_TYPE_PATH);
+       }
+
+       public void testThrows() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnThrows");
+               TypeAnnotationGen[] tas = getTypeAnnotations(getMethod(jc,"m"), true);
+               checkTypeAnnotationThrows(tas[0],0, "@Anno");
+               checkTypePath(tas[0],TypeAnnotationGen.NO_TYPE_PATH);
+               checkTypeAnnotationThrows(tas[1],1, "@Anno(value=2)");
+               checkTypePath(tas[1],TypeAnnotationGen.NO_TYPE_PATH);
+       }
+       
+       public void testLocalVariable() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnLocalVariable");
+               // TODO I think the attribute should be on the code for the method, not the method
+               TypeAnnotationGen[] tas = getTypeAnnotations(getMethod(jc,"m").getAttributes(), true);
+               assertEquals(1,tas.length);
+               checkTypeAnnotationLocalVariable(tas[0],new int[]{11,8,1}, "@Anno");
+       }
+
+       public void testResourceVariable() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnResourceVariable");
+               // TODO I think the attribute should be on the code for the method, not the method
+               TypeAnnotationGen[] tas = getTypeAnnotations(getMethod(jc,"m").getAttributes(), true);
+               assertEquals(2,tas.length);
+               checkTypeAnnotationResourceVariable(tas[0],new int[]{17,204,1}, "@Anno");
+               checkTypeAnnotationResourceVariable(tas[1],new int[]{36,114,3}, "@Anno(value=99)");
+       }
+       
+       public void testExceptionParameter() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnExceptionParameter");
+               // TODO I think the attribute should be on the code for the method, not the method
+               TypeAnnotationGen[] tas = getTypeAnnotations(getMethod(jc,"m").getAttributes(), true);
+               assertEquals(2,tas.length);
+               checkTypeAnnotationExceptionParameter(tas[0],0, "@Anno(value=99)");
+               checkTypeAnnotationExceptionParameter(tas[1],0, "@Anno");
+       }
+
+       public void testInstanceOf() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnInstanceOf");
+               // TODO I think the attribute should be on the code for the method, not the method
+               TypeAnnotationGen[] tas = getTypeAnnotations(getMethod(jc,"m").getAttributes(), true);
+               assertEquals(2,tas.length);
+               checkTypeAnnotationInstanceOf(tas[0],3, "@Anno(value=1)");
+               checkTypeAnnotationInstanceOf(tas[1],18, "@Anno(value=1)");
+       }
+
+       public void testNew() throws Exception {
+               JavaClass jc = getClassFromJava8Jar("TypeAnnoOnNew");
+               // TODO I think the attribute should be on the code for the method, not the method
+               TypeAnnotationGen[] tas = getTypeAnnotations(getMethod(jc,"m").getAttributes(), true);
+               assertEquals(4,tas.length);
+               checkTypeAnnotationNew(tas[0],0, "@Anno");
+               checkTypePath(tas[0],TypeAnnotationGen.NO_TYPE_PATH);
+               
+               // TODO type path bugs in javac b90 according to the spec
+               checkTypeAnnotationNew(tas[1],8, "@Anno(value=2)");
+               checkTypePath(tas[1],new int[]{
+                               TypeAnnotationGen.TYPE_PATH_ENTRY_KIND_ARRAY,0
+                               });
+               checkTypeAnnotationNew(tas[2],13, "@Anno(value=4)");
+               checkTypePath(tas[2],TypeAnnotationGen.NO_TYPE_PATH);
+               checkTypeAnnotationNew(tas[3],13, "@Anno(value=3)");
+               checkTypePath(tas[3],new int[]{
+                               TypeAnnotationGen.TYPE_PATH_ENTRY_KIND_ARRAY,0,
+                               TypeAnnotationGen.TYPE_PATH_ENTRY_KIND_ARRAY,0
+                               });
+       }
+
+
+       // ---
+       private TypeAnnotationGen[] getTypeAnnotations(Attribute[] attrs, boolean visible) {
+               RuntimeTypeAnnos rvta = (RuntimeTypeAnnos)getAttribute(attrs, visible?Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS:Constants.ATTR_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
+               return rvta.getTypeAnnotations();
+       }
+       
+       private TypeAnnotationGen[] getTypeAnnotations(Method m, boolean visible) {
+               RuntimeTypeAnnos rvta = (RuntimeTypeAnnos)getAttribute(m.getAttributes(), visible?Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS:Constants.ATTR_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
+               return rvta.getTypeAnnotations();
+       }
+       
+       private TypeAnnotationGen[] getTypeAnnotations(Field f, boolean visible) {
+               RuntimeTypeAnnos rvta = (RuntimeTypeAnnos)getAttribute(f.getAttributes(), visible?Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS:Constants.ATTR_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
+               return rvta.getTypeAnnotations();
+       }
+       
+       private void checkTypePath(TypeAnnotationGen ta, int[] expectedTypePath) {
+               int[] typepath = ta.getTypePath();
+               if (expectedTypePath==TypeAnnotationGen.NO_TYPE_PATH || expectedTypePath==null) {
+                       if (typepath!=TypeAnnotationGen.NO_TYPE_PATH) {
+                               fail("Expected no type path but was "+ta.getTypePathString());
+                       }
+               } else {
+                       assertEquals(expectedTypePath.length, typepath.length);
+                       for (int i=0;i<expectedTypePath.length;i++) {
+                               if (expectedTypePath[i]!=typepath[i]) {
+                                       fail("Expected type path: "+TypeAnnotationGen.toTypePathString(expectedTypePath)+" does not match actual type path "+ta.getTypePathString());
+                               }
+                       }
+               }
+       }
+
+       private void checkLocalVarTarget(TypeAnnotationGen ta, int[] expectedLocalVarTarget) {
+               int[] localVarTarget = ta.getLocalVarTarget();
+               assertEquals(expectedLocalVarTarget.length, localVarTarget.length);
+               for (int i=0;i<expectedLocalVarTarget.length;i++) {
+                       if (expectedLocalVarTarget[i]!=localVarTarget[i]) {
+                               fail("Expected local var target: "+toLocalVarTargetString(expectedLocalVarTarget)+" does not match actual type path "+toLocalVarTargetString(localVarTarget));
+                       }
+               }
+       }
+       
+       public static String toLocalVarTargetString(int[] localVarTarget) {
+               StringBuilder sb = new StringBuilder();
+               int count = 0;
+               while (count < localVarTarget.length) {
+                       sb.append("{start_pc="+localVarTarget[count++]+",length="+localVarTarget[count++]+",index="+localVarTarget[count++]+"}");
+               }
+               return sb.toString();
+       }
+
+       private void checkTypeAnnotationLocalVariable(TypeAnnotationGen ta, int[] expectedLocalVarTarget, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.LOCAL_VARIABLE,ta.getTargetType());
+               checkLocalVarTarget(ta,expectedLocalVarTarget);
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationResourceVariable(TypeAnnotationGen ta, int[] expectedLocalVarTarget, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.RESOURCE_VARIABLE,ta.getTargetType());
+               checkLocalVarTarget(ta,expectedLocalVarTarget);
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationExceptionParameter(TypeAnnotationGen ta, int expectedExceptionTableIndex, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.EXCEPTION_PARAMETER,ta.getTargetType());
+               assertEquals(expectedExceptionTableIndex,ta.getExceptionTableIndex());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationInstanceOf(TypeAnnotationGen ta, int expectedOffset, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.INSTANCEOF,ta.getTargetType());
+               assertEquals(expectedOffset,ta.getOffset());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationNew(TypeAnnotationGen ta, int expectedOffset, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.NEW,ta.getTargetType());
+               assertEquals(expectedOffset,ta.getOffset());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationConstructorReference(TypeAnnotationGen ta, int expectedOffset, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.CONSTRUCTOR_REFERENCE,ta.getTargetType());
+               assertEquals(expectedOffset,ta.getOffset());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationMethodReference(TypeAnnotationGen ta, int expectedOffset, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.METHOD_REFERENCE,ta.getTargetType());
+               assertEquals(expectedOffset,ta.getOffset());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationField(TypeAnnotationGen ta, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.FIELD,ta.getTargetType());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationMethodReturn(TypeAnnotationGen ta, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.METHOD_RETURN,ta.getTargetType());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationMethodFormalParameter(TypeAnnotationGen ta, int expectedFormalParameterIndex, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.METHOD_FORMAL_PARAMETER,ta.getTargetType());
+               assertEquals(expectedFormalParameterIndex,ta.getMethodFormalParameterIndex());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+       
+       private void checkTypeAnnotationThrows(TypeAnnotationGen ta, int expectedThrowsTypeIndex, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.THROWS,ta.getTargetType());
+               assertEquals(expectedThrowsTypeIndex,ta.getThrowsTypeIndex());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+       
+       private void checkTypeAnnotationMethodReceiver(TypeAnnotationGen ta, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.METHOD_RECEIVER,ta.getTargetType());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+       
+       private void checkTypeAnnotationClassExtends(TypeAnnotationGen ta, int expectedSupertypeIndex, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.CLASS_EXTENDS,ta.getTargetType());
+               assertEquals(expectedSupertypeIndex,ta.getSupertypeIndex());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationClassTypeParameter(TypeAnnotationGen ta, int expectedTypeParameterIndex, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.CLASS_TYPE_PARAMETER,ta.getTargetType());
+               assertEquals(expectedTypeParameterIndex,ta.getTypeParameterIndex());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+       
+       private void checkTypeAnnotationClassTypeParameterBound(TypeAnnotationGen ta, int expectedTypeParameterIndex, int expectedBoundIndex, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.CLASS_TYPE_PARAMETER_BOUND,ta.getTargetType());
+               assertEquals(expectedTypeParameterIndex,ta.getTypeParameterIndex());
+               assertEquals(expectedBoundIndex,ta.getBoundIndex());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationMethodTypeParameterBound(TypeAnnotationGen ta, int expectedTypeParameterIndex, int expectedBoundIndex, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.METHOD_TYPE_PARAMETER_BOUND,ta.getTargetType());
+               assertEquals(expectedTypeParameterIndex,ta.getTypeParameterIndex());
+               assertEquals(expectedBoundIndex,ta.getBoundIndex());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
+
+       private void checkTypeAnnotationMethodTypeParameter(TypeAnnotationGen ta, int expectedTypeParameterIndex, String expectedAnnotationText) {
+               assertEquals(TypeAnnotationGen.METHOD_TYPE_PARAMETER,ta.getTargetType());
+               assertEquals(expectedTypeParameterIndex,ta.getTypeParameterIndex());
+               assertEquals(expectedAnnotationText,ta.getAnnotation().toShortString());
+       }
        
 }
index d8b6ba1ac2d99749f66e7633b22977a7bb4c7f62..251b94663d6f3b6c29a8adb513b32d3ae40b900a 100644 (file)
@@ -91,6 +91,7 @@ import org.aspectj.apache.bcel.classfile.LocalVariable;
 import org.aspectj.apache.bcel.classfile.LocalVariableTable;
 import org.aspectj.apache.bcel.classfile.LocalVariableTypeTable;
 import org.aspectj.apache.bcel.classfile.Method;
+import org.aspectj.apache.bcel.classfile.MethodParameters;
 import org.aspectj.apache.bcel.classfile.Signature;
 import org.aspectj.apache.bcel.classfile.SourceFile;
 import org.aspectj.apache.bcel.classfile.StackMap;
@@ -100,8 +101,10 @@ import org.aspectj.apache.bcel.classfile.Unknown;
 import org.aspectj.apache.bcel.classfile.ClassVisitor;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisParamAnnos;
+import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisTypeAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisParamAnnos;
+import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisTypeAnnos;
 
 /**
  * Traverses a JavaClass with another Visitor object 'piggy-backed'
@@ -424,6 +427,24 @@ public class DescendingVisitor implements ClassVisitor {
        stack.pop();
   }
   
+  public void visitRuntimeVisibleTypeAnnotations(RuntimeVisTypeAnnos attribute) {
+       stack.push(attribute);
+       attribute.accept(visitor);
+       stack.pop();
+  }
+  
+  public void visitMethodParameters(MethodParameters attribute) {
+         stack.push(attribute);
+         attribute.accept(visitor);
+         stack.pop();
+  }
+  
+  public void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisTypeAnnos attribute) {
+       stack.push(attribute);
+       attribute.accept(visitor);
+       stack.pop();
+  }
+  
   public void visitAnnotationDefault(AnnotationDefault attribute) {
        stack.push(attribute);
        attribute.accept(visitor);
index cbfd079ca1a1c1670b3940e35dc25e89102b156b..f1b61c1ac391b35c17b2a8daa75a370c0a900e9d 100644 (file)
@@ -1,5 +1,3 @@
-package org.aspectj.apache.bcel.verifier;
-
 /* ====================================================================
  * The Apache Software License, Version 1.1
  *
@@ -53,6 +51,7 @@ package org.aspectj.apache.bcel.verifier;
  * information on the Apache Software Foundation, please see
  * <http://www.apache.org/>.
  */
+package org.aspectj.apache.bcel.verifier;
 
 import org.aspectj.apache.bcel.classfile.AnnotationDefault;
 import org.aspectj.apache.bcel.classfile.BootstrapMethods;
@@ -87,6 +86,7 @@ import org.aspectj.apache.bcel.classfile.LocalVariable;
 import org.aspectj.apache.bcel.classfile.LocalVariableTable;
 import org.aspectj.apache.bcel.classfile.LocalVariableTypeTable;
 import org.aspectj.apache.bcel.classfile.Method;
+import org.aspectj.apache.bcel.classfile.MethodParameters;
 import org.aspectj.apache.bcel.classfile.Signature;
 import org.aspectj.apache.bcel.classfile.SourceFile;
 import org.aspectj.apache.bcel.classfile.StackMap;
@@ -96,8 +96,10 @@ import org.aspectj.apache.bcel.classfile.Unknown;
 import org.aspectj.apache.bcel.classfile.ClassVisitor;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisParamAnnos;
+import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisTypeAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisAnnos;
 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisParamAnnos;
+import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisTypeAnnos;
 
 /**
  * Visitor with empty method bodies, can be extended and used in conjunction with the
@@ -158,5 +160,9 @@ public class EmptyClassVisitor implements ClassVisitor {
   public void visitAnnotationDefault(AnnotationDefault attribute) {}
   public void visitLocalVariableTypeTable(LocalVariableTypeTable obj) {}
         
+  // J8SUPPORT:
+  public void visitRuntimeVisibleTypeAnnotations(RuntimeVisTypeAnnos attribute) {}
+  public void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisTypeAnnos attribute) {}
+  public void visitMethodParameters(MethodParameters attribute) {}
 
 }