langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
changeset 3149 0cd06d598d6f
parent 2723 b659ca23d5f5
child 3782 ae62279eeb46
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Jun 26 12:22:40 2009 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Jun 26 18:51:39 2009 -0700
@@ -47,7 +47,6 @@
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.file.BaseFileObject;
 import com.sun.tools.javac.util.*;
-import com.sun.tools.javac.util.List;
 
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.*;
@@ -187,6 +186,10 @@
     /** The minor version number of the class file being read. */
     int minorVersion;
 
+    /** Switch: debug output for JSR 308-related operations.
+     */
+    boolean debugJSR308;
+
     /** Get the ClassReader instance for this invocation. */
     public static ClassReader instance(Context context) {
         ClassReader instance = context.get(classReaderKey);
@@ -256,6 +259,7 @@
             : null;
 
         typevars = new Scope(syms.noSymbol);
+        debugJSR308 = options.get("TA:reader") != null;
 
         initAttributeReaders();
     }
@@ -303,6 +307,12 @@
         return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
     }
 
+    /** Read a byte.
+     */
+    byte nextByte() {
+        return buf[bp++];
+    }
+
     /** Read an integer.
      */
     int nextInt() {
@@ -1060,7 +1070,21 @@
                     if (allowVarargs)
                         sym.flags_field |= VARARGS;
                 }
-            }
+            },
+
+            // v51 attributes
+            new AttributeReader(names.RuntimeVisibleTypeAnnotations, V51, CLASS_OR_MEMBER_ATTRIBUTE) {
+                void read(Symbol sym, int attrLen) {
+                    attachTypeAnnotations(sym);
+                }
+            },
+
+            new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V51, CLASS_OR_MEMBER_ATTRIBUTE) {
+                void read(Symbol sym, int attrLen) {
+                    attachTypeAnnotations(sym);
+                }
+            },
+
 
             // The following attributes for a Code attribute are not currently handled
             // StackMapTable
@@ -1268,6 +1292,17 @@
         }
     }
 
+    void attachTypeAnnotations(final Symbol sym) {
+        int numAttributes = nextChar();
+        if (numAttributes != 0) {
+            ListBuffer<TypeAnnotationProxy> proxies =
+                ListBuffer.lb();
+            for (int i = 0; i < numAttributes; i++)
+                proxies.append(readTypeAnnotation());
+            annotate.later(new TypeAnnotationCompleter(sym, proxies.toList()));
+        }
+    }
+
     /** Attach the default value for an annotation element.
      */
     void attachAnnotationDefault(final Symbol sym) {
@@ -1304,6 +1339,121 @@
         return new CompoundAnnotationProxy(t, pairs.toList());
     }
 
+    TypeAnnotationProxy readTypeAnnotation() {
+        CompoundAnnotationProxy proxy = readCompoundAnnotation();
+        TypeAnnotationPosition position = readPosition();
+
+        if (debugJSR308)
+            System.out.println("TA: reading: " + proxy + " @ " + position
+                    + " in " + log.currentSourceFile());
+
+        return new TypeAnnotationProxy(proxy, position);
+    }
+
+    TypeAnnotationPosition readPosition() {
+        byte tag = nextByte();
+
+        if (!TargetType.isValidTargetTypeValue(tag))
+            throw this.badClassFile("bad.type.annotation.value", tag);
+
+        TypeAnnotationPosition position = new TypeAnnotationPosition();
+        TargetType type = TargetType.fromTargetTypeValue(tag);
+
+        position.type = type;
+
+        switch (type) {
+        // type case
+        case TYPECAST:
+        case TYPECAST_GENERIC_OR_ARRAY:
+        // object creation
+        case INSTANCEOF:
+        case INSTANCEOF_GENERIC_OR_ARRAY:
+        // new expression
+        case NEW:
+        case NEW_GENERIC_OR_ARRAY:
+            position.offset = nextChar();
+            break;
+         // local variable
+        case LOCAL_VARIABLE:
+        case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
+            int table_length = nextChar();
+            position.lvarOffset = new int[table_length];
+            position.lvarLength = new int[table_length];
+            position.lvarIndex = new int[table_length];
+
+            for (int i = 0; i < table_length; ++i) {
+                position.lvarOffset[i] = nextChar();
+                position.lvarLength[i] = nextChar();
+                position.lvarIndex[i] = nextChar();
+            }
+            break;
+         // method receiver
+        case METHOD_RECEIVER:
+            // Do nothing
+            break;
+        // type parameters
+        case CLASS_TYPE_PARAMETER:
+        case METHOD_TYPE_PARAMETER:
+            position.parameter_index = nextByte();
+            break;
+        // type parameter bounds
+        case CLASS_TYPE_PARAMETER_BOUND:
+        case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
+        case METHOD_TYPE_PARAMETER_BOUND:
+        case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
+            position.parameter_index = nextByte();
+            position.bound_index = nextByte();
+            break;
+         // wildcard
+        case WILDCARD_BOUND:
+        case WILDCARD_BOUND_GENERIC_OR_ARRAY:
+            position.wildcard_position = readPosition();
+            break;
+         // Class extends and implements clauses
+        case CLASS_EXTENDS:
+        case CLASS_EXTENDS_GENERIC_OR_ARRAY:
+            position.type_index = nextByte();
+            break;
+        // throws
+        case THROWS:
+            position.type_index = nextByte();
+            break;
+        case CLASS_LITERAL:
+        case CLASS_LITERAL_GENERIC_OR_ARRAY:
+            position.offset = nextChar();
+            break;
+        // method parameter: not specified
+        case METHOD_PARAMETER_GENERIC_OR_ARRAY:
+            position.parameter_index = nextByte();
+            break;
+        // method type argument: wasn't specified
+        case NEW_TYPE_ARGUMENT:
+        case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
+        case METHOD_TYPE_ARGUMENT:
+        case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
+            position.offset = nextChar();
+            position.type_index = nextByte();
+            break;
+        // We don't need to worry abut these
+        case METHOD_RETURN_GENERIC_OR_ARRAY:
+        case FIELD_GENERIC_OR_ARRAY:
+            break;
+        case UNKNOWN:
+            break;
+        default:
+            throw new AssertionError("unknown type: " + position);
+        }
+
+        if (type.hasLocation()) {
+            int len = nextChar();
+            ListBuffer<Integer> loc = ListBuffer.lb();
+            for (int i = 0; i < len; i++)
+                loc = loc.append((int)nextByte());
+            position.location = loc.toList();
+        }
+
+        return position;
+    }
     Attribute readAttributeValue() {
         char c = (char) buf[bp++];
         switch (c) {
@@ -1408,6 +1558,18 @@
         }
     }
 
+    /** A temporary proxy representing a type annotation.
+     */
+    static class TypeAnnotationProxy {
+        final CompoundAnnotationProxy compound;
+        final TypeAnnotationPosition position;
+        public TypeAnnotationProxy(CompoundAnnotationProxy compound,
+                TypeAnnotationPosition position) {
+            this.compound = compound;
+            this.position = position;
+        }
+    }
+
     class AnnotationDeproxy implements ProxyVisitor {
         private ClassSymbol requestingOwner = currentOwner.kind == MTH
             ? currentOwner.enclClass() : (ClassSymbol)currentOwner;
@@ -1604,6 +1766,45 @@
         }
     }
 
+    class TypeAnnotationCompleter extends AnnotationCompleter {
+
+        List<TypeAnnotationProxy> proxies;
+
+        TypeAnnotationCompleter(Symbol sym,
+                List<TypeAnnotationProxy> proxies) {
+            super(sym, List.<CompoundAnnotationProxy>nil());
+            this.proxies = proxies;
+        }
+
+        List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) {
+            ListBuffer<Attribute.TypeCompound> buf = ListBuffer.lb();
+            for (TypeAnnotationProxy proxy: proxies) {
+                Attribute.Compound compound = deproxyCompound(proxy.compound);
+                Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position);
+                buf.add(typeCompound);
+            }
+            return buf.toList();
+        }
+
+        @Override
+        public void enterAnnotation() {
+            JavaFileObject previousClassFile = currentClassFile;
+            try {
+                currentClassFile = classFile;
+                List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies);
+              if (debugJSR308)
+              System.out.println("TA: reading: adding " + newList
+                      + " to symbol " + sym + " in " + log.currentSourceFile());
+                sym.typeAnnotations = ((sym.typeAnnotations == null)
+                                        ? newList
+                                        : newList.prependList(sym.typeAnnotations));
+
+            } finally {
+                currentClassFile = previousClassFile;
+            }
+        }
+    }
+
 
 /************************************************************************
  * Reading Symbols