langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java
changeset 15385 ee1eebe7e210
parent 7681 1f0819a3341f
child 15718 8e54c8e43d38
--- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java	Wed Jan 23 20:57:40 2013 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java	Wed Jan 23 13:27:24 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 
 package com.sun.tools.javac.code;
 
+import java.util.Iterator;
+
 import com.sun.tools.javac.util.*;
 
 /** A type annotation position.
@@ -34,12 +36,92 @@
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 */
+// Code duplicated in com.sun.tools.classfile.TypeAnnotation.Position
 public class TypeAnnotationPosition {
 
+    public enum TypePathEntryKind {
+        ARRAY(0),
+        INNER_TYPE(1),
+        WILDCARD(2),
+        TYPE_ARGUMENT(3);
+
+        public final int tag;
+
+        private TypePathEntryKind(int tag) {
+            this.tag = tag;
+        }
+    }
+
+    public static class TypePathEntry {
+        /** The fixed number of bytes per TypePathEntry. */
+        public static final int bytesPerEntry = 2;
+
+        public final TypePathEntryKind tag;
+        public final int arg;
+
+        public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY);
+        public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE);
+        public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD);
+
+        private TypePathEntry(TypePathEntryKind tag) {
+            Assert.check(tag == TypePathEntryKind.ARRAY ||
+                    tag == TypePathEntryKind.INNER_TYPE ||
+                    tag == TypePathEntryKind.WILDCARD,
+                    "Invalid TypePathEntryKind: " + tag);
+            this.tag = tag;
+            this.arg = 0;
+        }
+
+        public TypePathEntry(TypePathEntryKind tag, int arg) {
+            Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT,
+                    "Invalid TypePathEntryKind: " + tag);
+            this.tag = tag;
+            this.arg = arg;
+        }
+
+        public static TypePathEntry fromBinary(int tag, int arg) {
+            Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag,
+                    "Invalid TypePathEntry tag/arg: " + tag + "/" + arg);
+            switch (tag) {
+            case 0:
+                return ARRAY;
+            case 1:
+                return INNER_TYPE;
+            case 2:
+                return WILDCARD;
+            case 3:
+                return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg);
+            default:
+                Assert.error("Invalid TypePathEntryKind tag: " + tag);
+                return null;
+            }
+        }
+
+        @Override
+        public String toString() {
+            return tag.toString() +
+                    (tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : "");
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (! (other instanceof TypePathEntry)) {
+                return false;
+            }
+            TypePathEntry tpe = (TypePathEntry) other;
+            return this.tag == tpe.tag && this.arg == tpe.arg;
+        }
+
+        @Override
+        public int hashCode() {
+            return this.tag.hashCode() * 17 + this.arg;
+        }
+    }
+
     public TargetType type = TargetType.UNKNOWN;
 
     // For generic/array types.
-    public List<Integer> location = List.nil();
+    public List<TypePathEntry> location = List.nil();
 
     // Tree position.
     public int pos = -1;
@@ -59,11 +141,13 @@
     // For type parameter and method parameter
     public int parameter_index = Integer.MIN_VALUE;
 
-    // For class extends, implements, and throws classes
+    // For class extends, implements, and throws clauses
     public int type_index = Integer.MIN_VALUE;
 
-    // For wildcards
-    public TypeAnnotationPosition wildcard_position = null;
+    // For exception parameters, index into exception table
+    public int exception_index = Integer.MIN_VALUE;
+
+    public TypeAnnotationPosition() {}
 
     @Override
     public String toString() {
@@ -72,27 +156,27 @@
         sb.append(type);
 
         switch (type) {
-        // type case
-        case TYPECAST:
-        case TYPECAST_GENERIC_OR_ARRAY:
-            // object creation
+        // type cast
+        case CAST:
+        // instanceof
         case INSTANCEOF:
-        case INSTANCEOF_GENERIC_OR_ARRAY:
-            // new expression
+        // new expression
         case NEW:
-        case NEW_GENERIC_OR_ARRAY:
-        case NEW_TYPE_ARGUMENT:
-        case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
             sb.append(", offset = ");
             sb.append(offset);
             break;
-            // local variable
+        // local variable
         case LOCAL_VARIABLE:
-        case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
+        // resource variable
+        case RESOURCE_VARIABLE:
+            if (lvarOffset == null) {
+                sb.append(", lvarOffset is null!");
+                break;
+            }
             sb.append(", {");
             for (int i = 0; i < lvarOffset.length; ++i) {
                 if (i != 0) sb.append("; ");
-                sb.append(", start_pc = ");
+                sb.append("start_pc = ");
                 sb.append(lvarOffset[i]);
                 sb.append(", length = ");
                 sb.append(lvarLength[i]);
@@ -101,73 +185,72 @@
             }
             sb.append("}");
             break;
-            // method receiver
+        // method receiver
         case METHOD_RECEIVER:
             // Do nothing
             break;
-            // type parameters
+        // type parameter
         case CLASS_TYPE_PARAMETER:
         case METHOD_TYPE_PARAMETER:
             sb.append(", param_index = ");
             sb.append(parameter_index);
             break;
-            // type parameters bound
+        // type parameter bound
         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:
             sb.append(", param_index = ");
             sb.append(parameter_index);
             sb.append(", bound_index = ");
             sb.append(bound_index);
             break;
-            // wildcard
-        case WILDCARD_BOUND:
-        case WILDCARD_BOUND_GENERIC_OR_ARRAY:
-            sb.append(", wild_card = ");
-            sb.append(wildcard_position);
-            break;
-            // Class extends and implements clauses
+        // class extends or implements clause
         case CLASS_EXTENDS:
-        case CLASS_EXTENDS_GENERIC_OR_ARRAY:
             sb.append(", type_index = ");
             sb.append(type_index);
             break;
-            // throws
+        // throws
         case THROWS:
             sb.append(", type_index = ");
             sb.append(type_index);
             break;
-        case CLASS_LITERAL:
-        case CLASS_LITERAL_GENERIC_OR_ARRAY:
-            sb.append(", offset = ");
-            sb.append(offset);
+        // exception parameter
+        case EXCEPTION_PARAMETER:
+            sb.append(", exception_index = ");
+            sb.append(exception_index);
             break;
-            // method parameter: not specified
-        case METHOD_PARAMETER_GENERIC_OR_ARRAY:
+        // method parameter
+        case METHOD_FORMAL_PARAMETER:
             sb.append(", param_index = ");
             sb.append(parameter_index);
             break;
-            // method type argument: wasn't specified
-        case METHOD_TYPE_ARGUMENT:
-        case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
+        // method/constructor/reference type argument
+        case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+        case METHOD_INVOCATION_TYPE_ARGUMENT:
+        case METHOD_REFERENCE_TYPE_ARGUMENT:
             sb.append(", offset = ");
             sb.append(offset);
             sb.append(", type_index = ");
             sb.append(type_index);
             break;
-            // We don't need to worry abut these
-        case METHOD_RETURN_GENERIC_OR_ARRAY:
-        case FIELD_GENERIC_OR_ARRAY:
+        // We don't need to worry about these
+        case METHOD_RETURN:
+        case FIELD:
+            break;
+        // lambda formal parameter
+        case LAMBDA_FORMAL_PARAMETER:
+            // TODO: also needs an offset?
+            sb.append(", param_index = ");
+            sb.append(parameter_index);
             break;
         case UNKNOWN:
+            sb.append(", position UNKNOWN!");
             break;
         default:
-            //                throw new AssertionError("unknown type: " + type);
+            Assert.error("Unknown target type: " + type);
         }
 
         // Append location data for generics/arrays.
-        if (type.hasLocation()) {
+        if (!location.isEmpty()) {
             sb.append(", location = (");
             sb.append(location);
             sb.append(")");
@@ -186,10 +269,33 @@
      * @return true if the target has not been optimized away
      */
     public boolean emitToClassfile() {
-        if (type == TargetType.WILDCARD_BOUND
-            || type == TargetType.WILDCARD_BOUND_GENERIC_OR_ARRAY)
-            return wildcard_position.isValidOffset;
-        else
-            return !type.isLocal() || isValidOffset;
+        return !type.isLocal() || isValidOffset;
+    }
+
+    /**
+     * Decode the binary representation for a type path and set
+     * the {@code location} field.
+     *
+     * @param list The bytecode representation of the type path.
+     */
+    public static List<TypePathEntry> getTypePathFromBinary(java.util.List<Integer> list) {
+        ListBuffer<TypePathEntry> loc = ListBuffer.lb();
+        Iterator<Integer> iter = list.iterator();
+        while (iter.hasNext()) {
+            Integer fst = iter.next();
+            Assert.check(iter.hasNext(), "Could not decode type path: " + list);
+            Integer snd = iter.next();
+            loc = loc.append(TypePathEntry.fromBinary(fst, snd));
+        }
+        return loc.toList();
+    }
+
+    public static List<Integer> getBinaryFromTypePath(java.util.List<TypePathEntry> locs) {
+        ListBuffer<Integer> loc = ListBuffer.lb();
+        for (TypePathEntry tpe : locs) {
+            loc = loc.append(tpe.tag.tag);
+            loc = loc.append(tpe.arg);
+        }
+        return loc.toList();
     }
 }