src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java

Mon, 04 Feb 2013 18:08:53 -0500

author
dholmes
date
Mon, 04 Feb 2013 18:08:53 -0500
changeset 1570
f91144b7da75
parent 1521
71f35e4b93a5
child 1563
bc456436c613
permissions
-rw-r--r--

Merge

jjg@309 1 /*
jjg@1521 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
jjg@309 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@309 4 *
jjg@309 5 * This code is free software; you can redistribute it and/or modify it
jjg@309 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
jjg@309 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
jjg@309 10 *
jjg@309 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@309 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@309 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@309 14 * version 2 for more details (a copy is included in the LICENSE file that
jjg@309 15 * accompanied this code).
jjg@309 16 *
jjg@309 17 * You should have received a copy of the GNU General Public License version
jjg@309 18 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@309 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@309 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
jjg@309 24 */
jjg@309 25
jjg@309 26 package com.sun.tools.javac.code;
jjg@309 27
jjg@1521 28 import java.util.Iterator;
jjg@1521 29
jjg@309 30 import com.sun.tools.javac.util.*;
jjg@309 31
jjg@309 32 /** A type annotation position.
jjg@309 33 *
jjg@581 34 * <p><b>This is NOT part of any supported API.
jjg@581 35 * If you write code that depends on this, you do so at your own risk.
jjg@309 36 * This code and its internal interfaces are subject to change or
jjg@309 37 * deletion without notice.</b>
jjg@309 38 */
jjg@1521 39 // Code duplicated in com.sun.tools.classfile.TypeAnnotation.Position
jjg@309 40 public class TypeAnnotationPosition {
jjg@309 41
jjg@1521 42 public enum TypePathEntryKind {
jjg@1521 43 ARRAY(0),
jjg@1521 44 INNER_TYPE(1),
jjg@1521 45 WILDCARD(2),
jjg@1521 46 TYPE_ARGUMENT(3);
jjg@1521 47
jjg@1521 48 public final int tag;
jjg@1521 49
jjg@1521 50 private TypePathEntryKind(int tag) {
jjg@1521 51 this.tag = tag;
jjg@1521 52 }
jjg@1521 53 }
jjg@1521 54
jjg@1521 55 public static class TypePathEntry {
jjg@1521 56 /** The fixed number of bytes per TypePathEntry. */
jjg@1521 57 public static final int bytesPerEntry = 2;
jjg@1521 58
jjg@1521 59 public final TypePathEntryKind tag;
jjg@1521 60 public final int arg;
jjg@1521 61
jjg@1521 62 public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY);
jjg@1521 63 public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE);
jjg@1521 64 public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD);
jjg@1521 65
jjg@1521 66 private TypePathEntry(TypePathEntryKind tag) {
jjg@1521 67 Assert.check(tag == TypePathEntryKind.ARRAY ||
jjg@1521 68 tag == TypePathEntryKind.INNER_TYPE ||
jjg@1521 69 tag == TypePathEntryKind.WILDCARD,
jjg@1521 70 "Invalid TypePathEntryKind: " + tag);
jjg@1521 71 this.tag = tag;
jjg@1521 72 this.arg = 0;
jjg@1521 73 }
jjg@1521 74
jjg@1521 75 public TypePathEntry(TypePathEntryKind tag, int arg) {
jjg@1521 76 Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT,
jjg@1521 77 "Invalid TypePathEntryKind: " + tag);
jjg@1521 78 this.tag = tag;
jjg@1521 79 this.arg = arg;
jjg@1521 80 }
jjg@1521 81
jjg@1521 82 public static TypePathEntry fromBinary(int tag, int arg) {
jjg@1521 83 Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag,
jjg@1521 84 "Invalid TypePathEntry tag/arg: " + tag + "/" + arg);
jjg@1521 85 switch (tag) {
jjg@1521 86 case 0:
jjg@1521 87 return ARRAY;
jjg@1521 88 case 1:
jjg@1521 89 return INNER_TYPE;
jjg@1521 90 case 2:
jjg@1521 91 return WILDCARD;
jjg@1521 92 case 3:
jjg@1521 93 return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg);
jjg@1521 94 default:
jjg@1521 95 Assert.error("Invalid TypePathEntryKind tag: " + tag);
jjg@1521 96 return null;
jjg@1521 97 }
jjg@1521 98 }
jjg@1521 99
jjg@1521 100 @Override
jjg@1521 101 public String toString() {
jjg@1521 102 return tag.toString() +
jjg@1521 103 (tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : "");
jjg@1521 104 }
jjg@1521 105
jjg@1521 106 @Override
jjg@1521 107 public boolean equals(Object other) {
jjg@1521 108 if (! (other instanceof TypePathEntry)) {
jjg@1521 109 return false;
jjg@1521 110 }
jjg@1521 111 TypePathEntry tpe = (TypePathEntry) other;
jjg@1521 112 return this.tag == tpe.tag && this.arg == tpe.arg;
jjg@1521 113 }
jjg@1521 114
jjg@1521 115 @Override
jjg@1521 116 public int hashCode() {
jjg@1521 117 return this.tag.hashCode() * 17 + this.arg;
jjg@1521 118 }
jjg@1521 119 }
jjg@1521 120
jjg@309 121 public TargetType type = TargetType.UNKNOWN;
jjg@309 122
jjg@309 123 // For generic/array types.
jjg@1521 124 public List<TypePathEntry> location = List.nil();
jjg@309 125
jjg@309 126 // Tree position.
jjg@309 127 public int pos = -1;
jjg@309 128
jjg@309 129 // For typecasts, type tests, new (and locals, as start_pc).
jjg@310 130 public boolean isValidOffset = false;
jjg@309 131 public int offset = -1;
jjg@309 132
jjg@309 133 // For locals. arrays same length
jjg@478 134 public int[] lvarOffset = null;
jjg@478 135 public int[] lvarLength = null;
jjg@478 136 public int[] lvarIndex = null;
jjg@309 137
jjg@309 138 // For type parameter bound
jjg@478 139 public int bound_index = Integer.MIN_VALUE;
jjg@309 140
jjg@309 141 // For type parameter and method parameter
jjg@478 142 public int parameter_index = Integer.MIN_VALUE;
jjg@309 143
jjg@1521 144 // For class extends, implements, and throws clauses
jjg@478 145 public int type_index = Integer.MIN_VALUE;
jjg@309 146
jjg@1521 147 // For exception parameters, index into exception table
jjg@1521 148 public int exception_index = Integer.MIN_VALUE;
jjg@1521 149
jjg@1521 150 public TypeAnnotationPosition() {}
jjg@309 151
jjg@309 152 @Override
jjg@309 153 public String toString() {
jjg@309 154 StringBuilder sb = new StringBuilder();
jjg@309 155 sb.append('[');
jjg@309 156 sb.append(type);
jjg@309 157
jjg@309 158 switch (type) {
jjg@1521 159 // type cast
jjg@1521 160 case CAST:
jjg@1521 161 // instanceof
jjg@309 162 case INSTANCEOF:
jjg@1521 163 // new expression
jjg@309 164 case NEW:
jjg@309 165 sb.append(", offset = ");
jjg@309 166 sb.append(offset);
jjg@309 167 break;
jjg@1521 168 // local variable
jjg@309 169 case LOCAL_VARIABLE:
jjg@1521 170 // resource variable
jjg@1521 171 case RESOURCE_VARIABLE:
jjg@1521 172 if (lvarOffset == null) {
jjg@1521 173 sb.append(", lvarOffset is null!");
jjg@1521 174 break;
jjg@1521 175 }
jjg@309 176 sb.append(", {");
jjg@309 177 for (int i = 0; i < lvarOffset.length; ++i) {
jjg@309 178 if (i != 0) sb.append("; ");
jjg@1521 179 sb.append("start_pc = ");
jjg@309 180 sb.append(lvarOffset[i]);
jjg@309 181 sb.append(", length = ");
jjg@309 182 sb.append(lvarLength[i]);
jjg@309 183 sb.append(", index = ");
jjg@309 184 sb.append(lvarIndex[i]);
jjg@309 185 }
jjg@309 186 sb.append("}");
jjg@309 187 break;
jjg@1521 188 // method receiver
jjg@309 189 case METHOD_RECEIVER:
jjg@309 190 // Do nothing
jjg@309 191 break;
jjg@1521 192 // type parameter
jjg@309 193 case CLASS_TYPE_PARAMETER:
jjg@309 194 case METHOD_TYPE_PARAMETER:
jjg@309 195 sb.append(", param_index = ");
jjg@309 196 sb.append(parameter_index);
jjg@309 197 break;
jjg@1521 198 // type parameter bound
jjg@309 199 case CLASS_TYPE_PARAMETER_BOUND:
jjg@309 200 case METHOD_TYPE_PARAMETER_BOUND:
jjg@309 201 sb.append(", param_index = ");
jjg@309 202 sb.append(parameter_index);
jjg@309 203 sb.append(", bound_index = ");
jjg@309 204 sb.append(bound_index);
jjg@309 205 break;
jjg@1521 206 // class extends or implements clause
jjg@309 207 case CLASS_EXTENDS:
jjg@309 208 sb.append(", type_index = ");
jjg@309 209 sb.append(type_index);
jjg@309 210 break;
jjg@1521 211 // throws
jjg@309 212 case THROWS:
jjg@309 213 sb.append(", type_index = ");
jjg@309 214 sb.append(type_index);
jjg@309 215 break;
jjg@1521 216 // exception parameter
jjg@1521 217 case EXCEPTION_PARAMETER:
jjg@1521 218 sb.append(", exception_index = ");
jjg@1521 219 sb.append(exception_index);
jjg@309 220 break;
jjg@1521 221 // method parameter
jjg@1521 222 case METHOD_FORMAL_PARAMETER:
jjg@309 223 sb.append(", param_index = ");
jjg@309 224 sb.append(parameter_index);
jjg@309 225 break;
jjg@1521 226 // method/constructor/reference type argument
jjg@1521 227 case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
jjg@1521 228 case METHOD_INVOCATION_TYPE_ARGUMENT:
jjg@1521 229 case METHOD_REFERENCE_TYPE_ARGUMENT:
jjg@309 230 sb.append(", offset = ");
jjg@309 231 sb.append(offset);
jjg@309 232 sb.append(", type_index = ");
jjg@309 233 sb.append(type_index);
jjg@309 234 break;
jjg@1521 235 // We don't need to worry about these
jjg@1521 236 case METHOD_RETURN:
jjg@1521 237 case FIELD:
jjg@1521 238 break;
jjg@1521 239 // lambda formal parameter
jjg@1521 240 case LAMBDA_FORMAL_PARAMETER:
jjg@1521 241 // TODO: also needs an offset?
jjg@1521 242 sb.append(", param_index = ");
jjg@1521 243 sb.append(parameter_index);
jjg@309 244 break;
jjg@309 245 case UNKNOWN:
jjg@1521 246 sb.append(", position UNKNOWN!");
jjg@309 247 break;
jjg@309 248 default:
jjg@1521 249 Assert.error("Unknown target type: " + type);
jjg@309 250 }
jjg@309 251
jjg@309 252 // Append location data for generics/arrays.
jjg@1521 253 if (!location.isEmpty()) {
jjg@309 254 sb.append(", location = (");
jjg@309 255 sb.append(location);
jjg@309 256 sb.append(")");
jjg@309 257 }
jjg@309 258
jjg@309 259 sb.append(", pos = ");
jjg@309 260 sb.append(pos);
jjg@309 261
jjg@309 262 sb.append(']');
jjg@309 263 return sb.toString();
jjg@309 264 }
jjg@310 265
jjg@310 266 /**
jjg@310 267 * Indicates whether the target tree of the annotation has been optimized
jjg@310 268 * away from classfile or not.
jjg@310 269 * @return true if the target has not been optimized away
jjg@310 270 */
jjg@310 271 public boolean emitToClassfile() {
jjg@1521 272 return !type.isLocal() || isValidOffset;
jjg@1521 273 }
jjg@1521 274
jjg@1521 275 /**
jjg@1521 276 * Decode the binary representation for a type path and set
jjg@1521 277 * the {@code location} field.
jjg@1521 278 *
jjg@1521 279 * @param list The bytecode representation of the type path.
jjg@1521 280 */
jjg@1521 281 public static List<TypePathEntry> getTypePathFromBinary(java.util.List<Integer> list) {
jjg@1521 282 ListBuffer<TypePathEntry> loc = ListBuffer.lb();
jjg@1521 283 Iterator<Integer> iter = list.iterator();
jjg@1521 284 while (iter.hasNext()) {
jjg@1521 285 Integer fst = iter.next();
jjg@1521 286 Assert.check(iter.hasNext(), "Could not decode type path: " + list);
jjg@1521 287 Integer snd = iter.next();
jjg@1521 288 loc = loc.append(TypePathEntry.fromBinary(fst, snd));
jjg@1521 289 }
jjg@1521 290 return loc.toList();
jjg@1521 291 }
jjg@1521 292
jjg@1521 293 public static List<Integer> getBinaryFromTypePath(java.util.List<TypePathEntry> locs) {
jjg@1521 294 ListBuffer<Integer> loc = ListBuffer.lb();
jjg@1521 295 for (TypePathEntry tpe : locs) {
jjg@1521 296 loc = loc.append(tpe.tag.tag);
jjg@1521 297 loc = loc.append(tpe.arg);
jjg@1521 298 }
jjg@1521 299 return loc.toList();
jjg@310 300 }
jjg@309 301 }

mercurial