1 /*
  2  * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 package org.openjdk.asmtools.jasm;
 24 
 25 import java.io.PrintWriter;
 26 
 27 /**
 28  * Type annotation types: target_type, target_info && target_path
 29  */
 30 public class TypeAnnotationTypes {
 31 
 32     /**
 33      * Interpretation of type_path_kind values (Table 4.7.20.2-A)
 34      */
 35     public enum EPathKind {
 36         ARRAY(0),
 37         INNER_TYPE(1),
 38         WILDCARD(2),
 39         TYPE_ARGUMENT(3);
 40 
 41         private final int tag;
 42         public static final int maxLen = 3;
 43 
 44         EPathKind(int tag) {
 45             this.tag = tag;
 46         }
 47 
 48         public int tag() {
 49             return tag;
 50         }
 51 
 52         public String parseKey() {
 53             return this.toString();
 54         }
 55 
 56         static EPathKind getPathKind(String token) {
 57             for (EPathKind pk : values()) {
 58                 if( pk.parseKey().equals(token)) {
 59                     return pk;
 60                 }
 61             }
 62             return null;
 63         }
 64     }
 65 
 66     // will throw ArrayIndexOutOfBounds if i < 0 or i > 3
 67     static public EPathKind getPathKind(int i) {
 68         return EPathKind.values()[i];
 69     }
 70 
 71     static public class TypePathEntry {
 72 
 73         private final EPathKind kind;
 74         private final int typeArgumentIndex;
 75 
 76         public TypePathEntry(int kind, int typeArgumentIndex) {
 77             this.kind = getPathKind(kind);
 78             this.typeArgumentIndex = typeArgumentIndex;
 79         }
 80 
 81         public TypePathEntry(EPathKind kind, int typeArgumentIndex) {
 82             this.kind = kind;
 83             this.typeArgumentIndex = typeArgumentIndex;
 84         }
 85 
 86         public int getTypePathKind() {
 87             return kind.tag();
 88         }
 89 
 90         public int getTypeArgumentIndex() {
 91             return typeArgumentIndex;
 92         }
 93 
 94         @Override
 95         public String toString() {
 96             // Chapter 4.7.20.2 The type_path structure
 97             // if the value of the type_path_kind is 0,1, or 2, thebn the value of the
 98             // type_argument_index item is 0.
 99             return kind.parseKey() +  ( kind.tag == 3 ?
100                     JasmTokens.Token.LBRACE.parseKey() + typeArgumentIndex + JasmTokens.Token.RBRACE.parseKey() :
101                     "");
102         }
103     }
104 
105     /**
106      *     union {
107      *         type_parameter_target;
108      *         supertype_target;
109      *         type_parameter_bound_target;
110      *         empty_target;
111      *         method_formal_parameter_target;
112      *         throws_target;
113      *         localvar_target;
114      *         catch_target;
115      *         offset_target;
116      *         type_argument_target;
117      *     } target_info;
118      */
119     public enum ETargetInfo {
120         TYPEPARAM           ("TYPEPARAM", "type_parameter"),
121         SUPERTYPE           ("SUPERTYPE", "supertype"),
122         TYPEPARAM_BOUND     ("TYPEPARAM_BOUND", "type_parameter_bound"),
123         EMPTY               ("EMPTY", "empty"),
124         METHODPARAM         ("METHODPARAM", "formal_parameter"),
125         EXCEPTION           ("EXCEPTION", "throws"),
126         LOCALVAR            ("LOCALVAR", "localvar"),
127         CATCH               ("CATCH", "catch"),
128         OFFSET              ("OFFSET", "offset"),
129         TYPEARG             ("TYPEARG", "type_argument");
130 
131         private final String parseKey;
132         private final String printValue;
133 
134         ETargetInfo(String parse, String printValue) {
135             parseKey = parse;
136             this.printValue = printValue;
137         }
138         public String parseKey() {
139             return this.parseKey;
140         }
141 
142         public String printValue() {
143             return this.printValue;
144         }
145     }
146 
147     /**
148      *  Interpretation of target_type values (Table 4.7.20-A./B.)
149      */
150     static public enum ETargetType {
151         class_type_param            (0x00, "CLASS_TYPE_PARAMETER",  ETargetInfo.TYPEPARAM, "class/interface type parameter"),
152         meth_type_param             (0x01, "METHOD_TYPE_PARAMETER",  ETargetInfo.TYPEPARAM, "method/constructor type parameter"),
153         class_exts_impls            (0x10, "CLASS_EXTENDS",  ETargetInfo.SUPERTYPE, "class extends/implements"),
154         class_type_param_bnds       (0x11, "CLASS_TYPE_PARAMETER_BOUND",  ETargetInfo.TYPEPARAM_BOUND, "class/interface type parameter bounds"),
155         meth_type_param_bnds        (0x12, "METHOD_TYPE_PARAMETER_BOUND",  ETargetInfo.TYPEPARAM_BOUND, "method/constructor type parameter bounds"),
156         field                       (0x13, "FIELD",  ETargetInfo.EMPTY, "field"),
157         meth_ret_type               (0x14, "METHOD_RETURN",  ETargetInfo.EMPTY, "method return type"),
158         meth_receiver               (0x15, "METHOD_RECEIVER",  ETargetInfo.EMPTY, "method receiver"),
159         meth_formal_param           (0x16, "METHOD_FORMAL_PARAMETER",  ETargetInfo.METHODPARAM, "method formal parameter type"),
160         throws_type                 (0x17, "THROWS",  ETargetInfo.EXCEPTION, "exception type in throws"),
161 
162         local_var                   (0x40, "LOCAL_VARIABLE",  ETargetInfo.LOCALVAR, "local variable"),
163         resource_var                (0x41, "RESOURCE_VARIABLE",  ETargetInfo.LOCALVAR, "resource variable"),
164         exception_param             (0x42, "EXCEPTION_PARAM",  ETargetInfo.CATCH, "exception parameter"),
165         type_test                   (0x43, "INSTANCEOF",  ETargetInfo.OFFSET, "type test (instanceof)"),
166         obj_creat                   (0x44, "NEW",  ETargetInfo.OFFSET, "object creation (new)"),
167         constr_ref_receiver         (0x45, "CONSTRUCTOR_REFERENCE_RECEIVER", ETargetInfo.OFFSET, "constructor reference receiver"),
168         meth_ref_receiver           (0x46, "METHOD_REFERENCE_RECEIVER", ETargetInfo.OFFSET, "method reference receiver"),
169         cast                        (0x47, "CAST",  ETargetInfo.TYPEARG, "cast"),
170         constr_invoc_typearg        (0x48, "CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT",  ETargetInfo.TYPEARG, "type argument in constructor call"),
171         meth_invoc_typearg          (0x49, "METHOD_INVOCATION_TYPE_ARGUMENT", ETargetInfo.TYPEARG, "type argument in method call"),
172         constr_ref_typearg          (0x4A, "CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT", ETargetInfo.TYPEARG, "type argument in constructor reference"),
173         meth_ref_typearg            (0x4B, "METHOD_REFERENCE_TYPE_ARGUMENT",  ETargetInfo.TYPEARG, "type argument in method reference");
174 
175         public static final int maxTag = 0x9A;
176         public static final int maxLen = 36;
177 
178         public final int value;
179         private final String parseKey;
180         private final ETargetInfo targetInfo;
181         private final String printVal;
182 
183         ETargetType(int val, String parse, ETargetInfo targetInfo, String printVal) {
184             value = val;
185             parseKey = parse;
186             this.targetInfo = targetInfo;
187             this.printVal = printVal;
188         }
189 
190         public String parseKey() {
191             return parseKey;
192         }
193 
194         public String infoKey() {
195             return targetInfo.parseKey();
196         }
197 
198         public ETargetInfo targetInfo() {
199             return targetInfo;
200         }
201 
202         public void print(PrintWriter out) {
203             out.print(parseKey);
204         }
205 
206         @Override
207         public String toString() {
208             return String.format("%s[%#x]", parseKey, value);
209         }
210 
211         public static ETargetType getTargetType(int typeCode)  {
212             for( ETargetType type: ETargetType.values() ) {
213                 if (type.value == typeCode) {
214                     return type;
215                 }
216             }
217             return null;
218         }
219 
220         static public ETargetType getTargetType(String typeName) {
221             for( ETargetType type: ETargetType.values() ) {
222                 if (type.parseKey.equals(typeName)) {
223                     return type;
224                 }
225             }
226             return null;
227         }
228     };
229 
230     /* TypeAnnotationVisitor Methods */
231     public static class TypeAnnotationTargetVisitor {
232 
233         public final void visit(ETargetType tt) {
234             switch (tt) {
235                 case class_type_param:
236                 case meth_type_param:
237                     visit_type_param_target(tt);
238                     break;
239                 case class_exts_impls:
240                     visit_supertype_target(tt);
241                     break;
242                 case class_type_param_bnds:
243                 case meth_type_param_bnds:
244                     visit_typeparam_bound_target(tt);
245                     break;
246                 case field:
247                 case meth_ret_type:
248                 case meth_receiver:
249                     visit_empty_target(tt);
250                     break;
251                 case meth_formal_param:
252                     visit_methodformalparam_target(tt);
253                     break;
254                 case throws_type:
255                     visit_throws_target(tt);
256                     break;
257                 case local_var:
258                 case resource_var:
259                     visit_localvar_target(tt);
260                     break;
261                 case exception_param:
262                     visit_catch_target(tt);
263                     break;
264                 case type_test:
265                 case obj_creat:
266                 case constr_ref_receiver:
267                 case meth_ref_receiver:
268                     visit_offset_target(tt);
269                     break;
270 
271                 case cast:
272                 case constr_invoc_typearg:
273                 case meth_invoc_typearg:
274                 case constr_ref_typearg:
275                 case meth_ref_typearg:
276 
277                     visit_typearg_target(tt);
278                     break;
279             }
280         }
281 
282         public void visit_type_param_target(ETargetType tt) {
283         }
284 
285         public void visit_supertype_target(ETargetType tt) {
286         }
287 
288         public void visit_typeparam_bound_target(ETargetType tt) {
289         }
290 
291         public void visit_empty_target(ETargetType tt) {
292         }
293 
294         public void visit_methodformalparam_target(ETargetType tt) {
295         }
296 
297         public void visit_throws_target(ETargetType tt) {
298         }
299 
300         public void visit_localvar_target(ETargetType tt) {
301         }
302 
303         public void visit_catch_target(ETargetType tt) {
304         }
305 
306         public void visit_offset_target(ETargetType tt) {
307         }
308 
309         public void visit_typearg_target(ETargetType tt) {
310         }
311     }
312 }