23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package com.sun.tools.javac.code; |
26 package com.sun.tools.javac.code; |
27 |
27 |
|
28 import java.util.Iterator; |
|
29 |
28 import com.sun.tools.javac.util.*; |
30 import com.sun.tools.javac.util.*; |
29 |
31 |
30 /** A type annotation position. |
32 /** A type annotation position. |
31 * |
33 * |
32 * <p><b>This is NOT part of any supported API. |
34 * <p><b>This is NOT part of any supported API. |
33 * If you write code that depends on this, you do so at your own risk. |
35 * If you write code that depends on this, you do so at your own risk. |
34 * This code and its internal interfaces are subject to change or |
36 * This code and its internal interfaces are subject to change or |
35 * deletion without notice.</b> |
37 * deletion without notice.</b> |
36 */ |
38 */ |
|
39 // Code duplicated in com.sun.tools.classfile.TypeAnnotation.Position |
37 public class TypeAnnotationPosition { |
40 public class TypeAnnotationPosition { |
38 |
41 |
|
42 public enum TypePathEntryKind { |
|
43 ARRAY(0), |
|
44 INNER_TYPE(1), |
|
45 WILDCARD(2), |
|
46 TYPE_ARGUMENT(3); |
|
47 |
|
48 public final int tag; |
|
49 |
|
50 private TypePathEntryKind(int tag) { |
|
51 this.tag = tag; |
|
52 } |
|
53 } |
|
54 |
|
55 public static class TypePathEntry { |
|
56 /** The fixed number of bytes per TypePathEntry. */ |
|
57 public static final int bytesPerEntry = 2; |
|
58 |
|
59 public final TypePathEntryKind tag; |
|
60 public final int arg; |
|
61 |
|
62 public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY); |
|
63 public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE); |
|
64 public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD); |
|
65 |
|
66 private TypePathEntry(TypePathEntryKind tag) { |
|
67 Assert.check(tag == TypePathEntryKind.ARRAY || |
|
68 tag == TypePathEntryKind.INNER_TYPE || |
|
69 tag == TypePathEntryKind.WILDCARD, |
|
70 "Invalid TypePathEntryKind: " + tag); |
|
71 this.tag = tag; |
|
72 this.arg = 0; |
|
73 } |
|
74 |
|
75 public TypePathEntry(TypePathEntryKind tag, int arg) { |
|
76 Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT, |
|
77 "Invalid TypePathEntryKind: " + tag); |
|
78 this.tag = tag; |
|
79 this.arg = arg; |
|
80 } |
|
81 |
|
82 public static TypePathEntry fromBinary(int tag, int arg) { |
|
83 Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag, |
|
84 "Invalid TypePathEntry tag/arg: " + tag + "/" + arg); |
|
85 switch (tag) { |
|
86 case 0: |
|
87 return ARRAY; |
|
88 case 1: |
|
89 return INNER_TYPE; |
|
90 case 2: |
|
91 return WILDCARD; |
|
92 case 3: |
|
93 return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg); |
|
94 default: |
|
95 Assert.error("Invalid TypePathEntryKind tag: " + tag); |
|
96 return null; |
|
97 } |
|
98 } |
|
99 |
|
100 @Override |
|
101 public String toString() { |
|
102 return tag.toString() + |
|
103 (tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : ""); |
|
104 } |
|
105 |
|
106 @Override |
|
107 public boolean equals(Object other) { |
|
108 if (! (other instanceof TypePathEntry)) { |
|
109 return false; |
|
110 } |
|
111 TypePathEntry tpe = (TypePathEntry) other; |
|
112 return this.tag == tpe.tag && this.arg == tpe.arg; |
|
113 } |
|
114 |
|
115 @Override |
|
116 public int hashCode() { |
|
117 return this.tag.hashCode() * 17 + this.arg; |
|
118 } |
|
119 } |
|
120 |
39 public TargetType type = TargetType.UNKNOWN; |
121 public TargetType type = TargetType.UNKNOWN; |
40 |
122 |
41 // For generic/array types. |
123 // For generic/array types. |
42 public List<Integer> location = List.nil(); |
124 public List<TypePathEntry> location = List.nil(); |
43 |
125 |
44 // Tree position. |
126 // Tree position. |
45 public int pos = -1; |
127 public int pos = -1; |
46 |
128 |
47 // For typecasts, type tests, new (and locals, as start_pc). |
129 // For typecasts, type tests, new (and locals, as start_pc). |
57 public int bound_index = Integer.MIN_VALUE; |
139 public int bound_index = Integer.MIN_VALUE; |
58 |
140 |
59 // For type parameter and method parameter |
141 // For type parameter and method parameter |
60 public int parameter_index = Integer.MIN_VALUE; |
142 public int parameter_index = Integer.MIN_VALUE; |
61 |
143 |
62 // For class extends, implements, and throws classes |
144 // For class extends, implements, and throws clauses |
63 public int type_index = Integer.MIN_VALUE; |
145 public int type_index = Integer.MIN_VALUE; |
64 |
146 |
65 // For wildcards |
147 // For exception parameters, index into exception table |
66 public TypeAnnotationPosition wildcard_position = null; |
148 public int exception_index = Integer.MIN_VALUE; |
|
149 |
|
150 public TypeAnnotationPosition() {} |
67 |
151 |
68 @Override |
152 @Override |
69 public String toString() { |
153 public String toString() { |
70 StringBuilder sb = new StringBuilder(); |
154 StringBuilder sb = new StringBuilder(); |
71 sb.append('['); |
155 sb.append('['); |
72 sb.append(type); |
156 sb.append(type); |
73 |
157 |
74 switch (type) { |
158 switch (type) { |
75 // type case |
159 // type cast |
76 case TYPECAST: |
160 case CAST: |
77 case TYPECAST_GENERIC_OR_ARRAY: |
161 // instanceof |
78 // object creation |
|
79 case INSTANCEOF: |
162 case INSTANCEOF: |
80 case INSTANCEOF_GENERIC_OR_ARRAY: |
163 // new expression |
81 // new expression |
|
82 case NEW: |
164 case NEW: |
83 case NEW_GENERIC_OR_ARRAY: |
|
84 case NEW_TYPE_ARGUMENT: |
|
85 case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY: |
|
86 sb.append(", offset = "); |
165 sb.append(", offset = "); |
87 sb.append(offset); |
166 sb.append(offset); |
88 break; |
167 break; |
89 // local variable |
168 // local variable |
90 case LOCAL_VARIABLE: |
169 case LOCAL_VARIABLE: |
91 case LOCAL_VARIABLE_GENERIC_OR_ARRAY: |
170 // resource variable |
|
171 case RESOURCE_VARIABLE: |
|
172 if (lvarOffset == null) { |
|
173 sb.append(", lvarOffset is null!"); |
|
174 break; |
|
175 } |
92 sb.append(", {"); |
176 sb.append(", {"); |
93 for (int i = 0; i < lvarOffset.length; ++i) { |
177 for (int i = 0; i < lvarOffset.length; ++i) { |
94 if (i != 0) sb.append("; "); |
178 if (i != 0) sb.append("; "); |
95 sb.append(", start_pc = "); |
179 sb.append("start_pc = "); |
96 sb.append(lvarOffset[i]); |
180 sb.append(lvarOffset[i]); |
97 sb.append(", length = "); |
181 sb.append(", length = "); |
98 sb.append(lvarLength[i]); |
182 sb.append(lvarLength[i]); |
99 sb.append(", index = "); |
183 sb.append(", index = "); |
100 sb.append(lvarIndex[i]); |
184 sb.append(lvarIndex[i]); |
101 } |
185 } |
102 sb.append("}"); |
186 sb.append("}"); |
103 break; |
187 break; |
104 // method receiver |
188 // method receiver |
105 case METHOD_RECEIVER: |
189 case METHOD_RECEIVER: |
106 // Do nothing |
190 // Do nothing |
107 break; |
191 break; |
108 // type parameters |
192 // type parameter |
109 case CLASS_TYPE_PARAMETER: |
193 case CLASS_TYPE_PARAMETER: |
110 case METHOD_TYPE_PARAMETER: |
194 case METHOD_TYPE_PARAMETER: |
111 sb.append(", param_index = "); |
195 sb.append(", param_index = "); |
112 sb.append(parameter_index); |
196 sb.append(parameter_index); |
113 break; |
197 break; |
114 // type parameters bound |
198 // type parameter bound |
115 case CLASS_TYPE_PARAMETER_BOUND: |
199 case CLASS_TYPE_PARAMETER_BOUND: |
116 case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: |
|
117 case METHOD_TYPE_PARAMETER_BOUND: |
200 case METHOD_TYPE_PARAMETER_BOUND: |
118 case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: |
|
119 sb.append(", param_index = "); |
201 sb.append(", param_index = "); |
120 sb.append(parameter_index); |
202 sb.append(parameter_index); |
121 sb.append(", bound_index = "); |
203 sb.append(", bound_index = "); |
122 sb.append(bound_index); |
204 sb.append(bound_index); |
123 break; |
205 break; |
124 // wildcard |
206 // class extends or implements clause |
125 case WILDCARD_BOUND: |
|
126 case WILDCARD_BOUND_GENERIC_OR_ARRAY: |
|
127 sb.append(", wild_card = "); |
|
128 sb.append(wildcard_position); |
|
129 break; |
|
130 // Class extends and implements clauses |
|
131 case CLASS_EXTENDS: |
207 case CLASS_EXTENDS: |
132 case CLASS_EXTENDS_GENERIC_OR_ARRAY: |
|
133 sb.append(", type_index = "); |
208 sb.append(", type_index = "); |
134 sb.append(type_index); |
209 sb.append(type_index); |
135 break; |
210 break; |
136 // throws |
211 // throws |
137 case THROWS: |
212 case THROWS: |
138 sb.append(", type_index = "); |
213 sb.append(", type_index = "); |
139 sb.append(type_index); |
214 sb.append(type_index); |
140 break; |
215 break; |
141 case CLASS_LITERAL: |
216 // exception parameter |
142 case CLASS_LITERAL_GENERIC_OR_ARRAY: |
217 case EXCEPTION_PARAMETER: |
143 sb.append(", offset = "); |
218 sb.append(", exception_index = "); |
144 sb.append(offset); |
219 sb.append(exception_index); |
145 break; |
220 break; |
146 // method parameter: not specified |
221 // method parameter |
147 case METHOD_PARAMETER_GENERIC_OR_ARRAY: |
222 case METHOD_FORMAL_PARAMETER: |
148 sb.append(", param_index = "); |
223 sb.append(", param_index = "); |
149 sb.append(parameter_index); |
224 sb.append(parameter_index); |
150 break; |
225 break; |
151 // method type argument: wasn't specified |
226 // method/constructor/reference type argument |
152 case METHOD_TYPE_ARGUMENT: |
227 case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: |
153 case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY: |
228 case METHOD_INVOCATION_TYPE_ARGUMENT: |
|
229 case METHOD_REFERENCE_TYPE_ARGUMENT: |
154 sb.append(", offset = "); |
230 sb.append(", offset = "); |
155 sb.append(offset); |
231 sb.append(offset); |
156 sb.append(", type_index = "); |
232 sb.append(", type_index = "); |
157 sb.append(type_index); |
233 sb.append(type_index); |
158 break; |
234 break; |
159 // We don't need to worry abut these |
235 // We don't need to worry about these |
160 case METHOD_RETURN_GENERIC_OR_ARRAY: |
236 case METHOD_RETURN: |
161 case FIELD_GENERIC_OR_ARRAY: |
237 case FIELD: |
|
238 break; |
|
239 // lambda formal parameter |
|
240 case LAMBDA_FORMAL_PARAMETER: |
|
241 // TODO: also needs an offset? |
|
242 sb.append(", param_index = "); |
|
243 sb.append(parameter_index); |
162 break; |
244 break; |
163 case UNKNOWN: |
245 case UNKNOWN: |
|
246 sb.append(", position UNKNOWN!"); |
164 break; |
247 break; |
165 default: |
248 default: |
166 // throw new AssertionError("unknown type: " + type); |
249 Assert.error("Unknown target type: " + type); |
167 } |
250 } |
168 |
251 |
169 // Append location data for generics/arrays. |
252 // Append location data for generics/arrays. |
170 if (type.hasLocation()) { |
253 if (!location.isEmpty()) { |
171 sb.append(", location = ("); |
254 sb.append(", location = ("); |
172 sb.append(location); |
255 sb.append(location); |
173 sb.append(")"); |
256 sb.append(")"); |
174 } |
257 } |
175 |
258 |
184 * Indicates whether the target tree of the annotation has been optimized |
267 * Indicates whether the target tree of the annotation has been optimized |
185 * away from classfile or not. |
268 * away from classfile or not. |
186 * @return true if the target has not been optimized away |
269 * @return true if the target has not been optimized away |
187 */ |
270 */ |
188 public boolean emitToClassfile() { |
271 public boolean emitToClassfile() { |
189 if (type == TargetType.WILDCARD_BOUND |
272 return !type.isLocal() || isValidOffset; |
190 || type == TargetType.WILDCARD_BOUND_GENERIC_OR_ARRAY) |
273 } |
191 return wildcard_position.isValidOffset; |
274 |
192 else |
275 /** |
193 return !type.isLocal() || isValidOffset; |
276 * Decode the binary representation for a type path and set |
|
277 * the {@code location} field. |
|
278 * |
|
279 * @param list The bytecode representation of the type path. |
|
280 */ |
|
281 public static List<TypePathEntry> getTypePathFromBinary(java.util.List<Integer> list) { |
|
282 ListBuffer<TypePathEntry> loc = ListBuffer.lb(); |
|
283 Iterator<Integer> iter = list.iterator(); |
|
284 while (iter.hasNext()) { |
|
285 Integer fst = iter.next(); |
|
286 Assert.check(iter.hasNext(), "Could not decode type path: " + list); |
|
287 Integer snd = iter.next(); |
|
288 loc = loc.append(TypePathEntry.fromBinary(fst, snd)); |
|
289 } |
|
290 return loc.toList(); |
|
291 } |
|
292 |
|
293 public static List<Integer> getBinaryFromTypePath(java.util.List<TypePathEntry> locs) { |
|
294 ListBuffer<Integer> loc = ListBuffer.lb(); |
|
295 for (TypePathEntry tpe : locs) { |
|
296 loc = loc.append(tpe.tag.tag); |
|
297 loc = loc.append(tpe.arg); |
|
298 } |
|
299 return loc.toList(); |
194 } |
300 } |
195 } |
301 } |