1 /*
2  * Copyright (c) 2008, 2011, 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.tools.classfile;
27 
28 import java.util.Arrays;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Set;
32 
33 /*
34  *  Family of classes used to represent the parsed form of a {@link Descriptor}
35  *  or {@link Signature}.
36  *
37  *  <p><b>This is NOT part of any supported API.
38  *  If you write code that depends on this, you do so at your own risk.
39  *  This code and its internal interfaces are subject to change or
40  *  deletion without notice.</b>
41  */
42 public abstract class Type {
Type()43     protected Type() { }
44 
isObject()45     public boolean isObject() {
46         return false;
47     }
48 
accept(Visitor<R,D> visitor, D data)49     public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
50 
append(StringBuilder sb, String prefix, List<? extends Type> types, String suffix)51     protected static void append(StringBuilder sb, String prefix, List<? extends Type> types, String suffix) {
52         sb.append(prefix);
53         String sep = "";
54         for (Type t: types) {
55             sb.append(sep);
56             sb.append(t);
57             sep = ", ";
58         }
59         sb.append(suffix);
60     }
61 
appendIfNotEmpty(StringBuilder sb, String prefix, List<? extends Type> types, String suffix)62     protected static void appendIfNotEmpty(StringBuilder sb, String prefix, List<? extends Type> types, String suffix) {
63         if (types != null && types.size() > 0)
64             append(sb, prefix, types, suffix);
65     }
66 
67     public interface Visitor<R,P> {
visitSimpleType(SimpleType type, P p)68         R visitSimpleType(SimpleType type, P p);
visitArrayType(ArrayType type, P p)69         R visitArrayType(ArrayType type, P p);
visitMethodType(MethodType type, P p)70         R visitMethodType(MethodType type, P p);
visitClassSigType(ClassSigType type, P p)71         R visitClassSigType(ClassSigType type, P p);
visitClassType(ClassType type, P p)72         R visitClassType(ClassType type, P p);
visitTypeParamType(TypeParamType type, P p)73         R visitTypeParamType(TypeParamType type, P p);
visitWildcardType(WildcardType type, P p)74         R visitWildcardType(WildcardType type, P p);
75     }
76 
77     /**
78      * Represents a type signature with a simple name. The name may be that of a
79      * primitive type, such "{@code int}, {@code float}, etc
80      * or that of a type argument, such as {@code T}, {@code K}, {@code V}, etc.
81      *
82      * See:
83      * JVMS 4.3.2
84      *      BaseType:
85      *          {@code B}, {@code C}, {@code D}, {@code F}, {@code I},
86      *          {@code J}, {@code S}, {@code Z};
87      *      VoidDescriptor:
88      *          {@code V};
89      * JVMS 4.3.4
90      *      TypeVariableSignature:
91      *          {@code T} Identifier {@code ;}
92      */
93     public static class SimpleType extends Type {
SimpleType(String name)94         public SimpleType(String name) {
95             this.name = name;
96         }
97 
accept(Visitor<R, D> visitor, D data)98         public <R, D> R accept(Visitor<R, D> visitor, D data) {
99             return visitor.visitSimpleType(this, data);
100         }
101 
isPrimitiveType()102         public boolean isPrimitiveType() {
103             return primitiveTypes.contains(name);
104         }
105         // where
106         private static final Set<String> primitiveTypes = new HashSet<>(Arrays.asList(
107             "boolean", "byte", "char", "double", "float", "int", "long", "short", "void"));
108 
109         @Override
toString()110         public String toString() {
111             return name;
112         }
113 
114         public final String name;
115     }
116 
117     /**
118      * Represents an array type signature.
119      *
120      * See:
121      * JVMS 4.3.4
122      *      ArrayTypeSignature:
123      *          {@code [} TypeSignature {@code ]}
124      */
125     public static class ArrayType extends Type {
ArrayType(Type elemType)126         public ArrayType(Type elemType) {
127             this.elemType = elemType;
128         }
129 
accept(Visitor<R, D> visitor, D data)130         public <R, D> R accept(Visitor<R, D> visitor, D data) {
131             return visitor.visitArrayType(this, data);
132         }
133 
134         @Override
toString()135         public String toString() {
136             return elemType + "[]";
137         }
138 
139         public final Type elemType;
140     }
141 
142     /**
143      * Represents a method type signature.
144      *
145      * See;
146      * JVMS 4.3.4
147      *      MethodTypeSignature:
148      *          FormalTypeParameters_opt {@code (} TypeSignature* {@code)} ReturnType
149      *              ThrowsSignature*
150      */
151     public static class MethodType extends Type {
MethodType(List<? extends Type> paramTypes, Type resultType)152         public MethodType(List<? extends Type> paramTypes, Type resultType) {
153             this(null, paramTypes, resultType, null);
154         }
155 
MethodType(List<? extends TypeParamType> typeParamTypes, List<? extends Type> paramTypes, Type returnType, List<? extends Type> throwsTypes)156         public MethodType(List<? extends TypeParamType> typeParamTypes,
157                 List<? extends Type> paramTypes,
158                 Type returnType,
159                 List<? extends Type> throwsTypes) {
160             this.typeParamTypes = typeParamTypes;
161             this.paramTypes = paramTypes;
162             this.returnType = returnType;
163             this.throwsTypes = throwsTypes;
164         }
165 
accept(Visitor<R, D> visitor, D data)166         public <R, D> R accept(Visitor<R, D> visitor, D data) {
167             return visitor.visitMethodType(this, data);
168         }
169 
170         @Override
toString()171         public String toString() {
172             StringBuilder sb = new StringBuilder();
173             appendIfNotEmpty(sb, "<", typeParamTypes, "> ");
174             sb.append(returnType);
175             append(sb, " (", paramTypes, ")");
176             appendIfNotEmpty(sb, " throws ", throwsTypes, "");
177             return sb.toString();
178         }
179 
180         public final List<? extends TypeParamType> typeParamTypes;
181         public final List<? extends Type> paramTypes;
182         public final Type returnType;
183         public final List<? extends Type> throwsTypes;
184     }
185 
186     /**
187      * Represents a class signature. These describe the signature of
188      * a class that has type arguments.
189      *
190      * See:
191      * JVMS 4.3.4
192      *      ClassSignature:
193      *          FormalTypeParameters_opt SuperclassSignature SuperinterfaceSignature*
194      */
195     public static class ClassSigType extends Type {
ClassSigType(List<TypeParamType> typeParamTypes, Type superclassType, List<Type> superinterfaceTypes)196         public ClassSigType(List<TypeParamType> typeParamTypes, Type superclassType,
197                 List<Type> superinterfaceTypes) {
198             this.typeParamTypes = typeParamTypes;
199             this.superclassType = superclassType;
200             this.superinterfaceTypes = superinterfaceTypes;
201         }
202 
accept(Visitor<R, D> visitor, D data)203         public <R, D> R accept(Visitor<R, D> visitor, D data) {
204             return visitor.visitClassSigType(this, data);
205         }
206 
207         @Override
toString()208         public String toString() {
209             StringBuilder sb = new StringBuilder();
210             appendIfNotEmpty(sb, "<", typeParamTypes, ">");
211             if (superclassType != null) {
212                 sb.append(" extends ");
213                 sb.append(superclassType);
214             }
215             appendIfNotEmpty(sb, " implements ", superinterfaceTypes, "");
216             return sb.toString();
217         }
218 
219         public final List<TypeParamType> typeParamTypes;
220         public final Type superclassType;
221         public final List<Type> superinterfaceTypes;
222     }
223 
224     /**
225      * Represents a class type signature. This is used to represent a
226      * reference to a class, such as in a field, parameter, return type, etc.
227      *
228      * See:
229      * JVMS 4.3.4
230      *      ClassTypeSignature:
231      *          {@code L} PackageSpecifier_opt SimpleClassTypeSignature
232      *                  ClassTypeSignatureSuffix* {@code ;}
233      *      PackageSpecifier:
234      *          Identifier {@code /} PackageSpecifier*
235      *      SimpleClassTypeSignature:
236      *          Identifier TypeArguments_opt }
237      *      ClassTypeSignatureSuffix:
238      *          {@code .} SimpleClassTypeSignature
239      */
240     public static class ClassType extends Type {
ClassType(ClassType outerType, String name, List<Type> typeArgs)241         public ClassType(ClassType outerType, String name, List<Type> typeArgs) {
242             this.outerType = outerType;
243             this.name = name;
244             this.typeArgs = typeArgs;
245         }
246 
accept(Visitor<R, D> visitor, D data)247         public <R, D> R accept(Visitor<R, D> visitor, D data) {
248             return visitor.visitClassType(this, data);
249         }
250 
getBinaryName()251         public String getBinaryName() {
252             if (outerType == null)
253                 return name;
254             else
255                 return (outerType.getBinaryName() + "$" + name);
256         }
257 
258         @Override
toString()259         public String toString() {
260             StringBuilder sb = new StringBuilder();
261             if (outerType != null) {
262                 sb.append(outerType);
263                 sb.append(".");
264             }
265             sb.append(name);
266             appendIfNotEmpty(sb, "<", typeArgs, ">");
267             return sb.toString();
268         }
269 
270         @Override
isObject()271         public boolean isObject() {
272             return (outerType == null)
273                     && name.equals("java/lang/Object")
274                     && (typeArgs == null || typeArgs.isEmpty());
275         }
276 
277         public final ClassType outerType;
278         public final String name;
279         public final List<Type> typeArgs;
280     }
281 
282     /**
283      * Represents a FormalTypeParameter. These are used to declare the type
284      * parameters for generic classes and methods.
285      *
286      * See:
287      * JVMS 4.3.4
288      *     FormalTypeParameters:
289      *          {@code <} FormalTypeParameter+ {@code >}
290      *     FormalTypeParameter:
291      *          Identifier ClassBound InterfaceBound*
292      *     ClassBound:
293      *          {@code :} FieldTypeSignature_opt
294      *     InterfaceBound:
295      *          {@code :} FieldTypeSignature
296      */
297     public static class TypeParamType extends Type {
TypeParamType(String name, Type classBound, List<Type> interfaceBounds)298         public TypeParamType(String name, Type classBound, List<Type> interfaceBounds) {
299             this.name = name;
300             this.classBound = classBound;
301             this.interfaceBounds = interfaceBounds;
302         }
303 
accept(Visitor<R, D> visitor, D data)304         public <R, D> R accept(Visitor<R, D> visitor, D data) {
305             return visitor.visitTypeParamType(this, data);
306         }
307 
308         @Override
toString()309         public String toString() {
310             StringBuilder sb = new StringBuilder();
311             sb.append(name);
312             String sep = " extends ";
313             if (classBound != null) {
314                 sb.append(sep);
315                 sb.append(classBound);
316                 sep = " & ";
317             }
318             if (interfaceBounds != null) {
319                 for (Type bound: interfaceBounds) {
320                     sb.append(sep);
321                     sb.append(bound);
322                     sep = " & ";
323                 }
324             }
325             return sb.toString();
326         }
327 
328         public final String name;
329         public final Type classBound;
330         public final List<Type> interfaceBounds;
331     }
332 
333     /**
334      * Represents a wildcard type argument.  A type argument that is not a
335      * wildcard type argument will be represented by a ClassType, ArrayType, etc.
336      *
337      * See:
338      * JVMS 4.3.4
339      *      TypeArgument:
340      *          WildcardIndicator_opt FieldTypeSignature
341      *          {@code *}
342      *      WildcardIndicator:
343      *          {@code +}
344      *          {@code -}
345      */
346     public static class WildcardType extends Type {
347         public enum Kind { UNBOUNDED, EXTENDS, SUPER }
348 
WildcardType()349         public WildcardType() {
350             this(Kind.UNBOUNDED, null);
351         }
WildcardType(Kind kind, Type boundType)352         public WildcardType(Kind kind, Type boundType) {
353             this.kind = kind;
354             this.boundType = boundType;
355         }
356 
accept(Visitor<R, D> visitor, D data)357         public <R, D> R accept(Visitor<R, D> visitor, D data) {
358             return visitor.visitWildcardType(this, data);
359         }
360 
361         @Override
toString()362         public String toString() {
363             switch (kind) {
364                 case UNBOUNDED:
365                     return "?";
366                 case EXTENDS:
367                     return "? extends " + boundType;
368                 case SUPER:
369                     return "? super " + boundType;
370                 default:
371                     throw new AssertionError();
372             }
373         }
374 
375         public final Kind kind;
376         public final Type boundType;
377     }
378 }
379