/* * Copyright 2008 Sun Microsystems, Inc. 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package com.sun.tools.classfile; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; /* * Family of classes used to represent the parsed form of a {@link Descriptor} * or {@link Signature}. * *

This is NOT part of any API supported by Sun Microsystems. If * you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice. */ public abstract class Type { protected Type() { } public abstract R accept(Visitor visitor, D data); protected static void append(StringBuilder sb, String prefix, List types, String suffix) { sb.append(prefix); String sep = ""; for (Type t: types) { sb.append(sep); sb.append(t); sep = ", "; } sb.append(suffix); } protected static void appendIfNotEmpty(StringBuilder sb, String prefix, List types, String suffix) { if (types != null && types.size() > 0) append(sb, prefix, types, suffix); } public interface Visitor { R visitSimpleType(SimpleType type, P p); R visitArrayType(ArrayType type, P p); R visitMethodType(MethodType type, P p); R visitFunctionType(FunctionType type, P p); R visitClassSigType(ClassSigType type, P p); R visitClassType(ClassType type, P p); R visitTypeParamType(TypeParamType type, P p); R visitWildcardType(WildcardType type, P p); } /** * Represents a type signature with a simple name. The name may be that of a * primitive type, such "{@code int}, {@code float}, etc * or that of a type argument, such as {@code T}, {@code K}, {@code V}, etc. * * See: * JVMS 4.3.2 * BaseType: * {@code B}, {@code C}, {@code D}, {@code F}, {@code I}, * {@code J}, {@code S}, {@code Z}; * VoidDescriptor: * {@code V}; * JVMS 4.3.4 * TypeVariableSignature: * {@code T} Identifier {@code ;} */ public static class SimpleType extends Type { public SimpleType(String name) { this.name = name; } public R accept(Visitor visitor, D data) { return visitor.visitSimpleType(this, data); } public boolean isPrimitiveType() { return primitiveTypes.contains(name); } // where private static final Set primitiveTypes = new HashSet(Arrays.asList( "boolean", "byte", "char", "double", "float", "int", "long", "short", "void")); @Override public String toString() { return name; } public final String name; } /** * Represents an array type signature. * * See: * JVMS 4.3.4 * ArrayTypeSignature: * {@code [} TypeSignature {@code ]} */ public static class ArrayType extends Type { public ArrayType(Type elemType) { this.elemType = elemType; } public R accept(Visitor visitor, D data) { return visitor.visitArrayType(this, data); } @Override public String toString() { return elemType + "[]"; } public final Type elemType; } /** * Represents a method type signature. * * See; * JVMS 4.3.4 * MethodTypeSignature: * FormalTypeParameters_opt {@code (} TypeSignature* {@code)} ReturnType * ThrowsSignature* */ public static class MethodType extends Type { public MethodType(List paramTypes, Type resultType) { this(null, paramTypes, resultType, null); } public MethodType(List typeParamTypes, List paramTypes, Type returnType, List throwsTypes) { this.typeParamTypes = typeParamTypes; this.paramTypes = paramTypes; this.returnType = returnType; this.throwsTypes = throwsTypes; } public R accept(Visitor visitor, D data) { return visitor.visitMethodType(this, data); } @Override public String toString() { StringBuilder sb = new StringBuilder(); appendIfNotEmpty(sb, "<", typeParamTypes, "> "); sb.append(returnType); append(sb, " (", paramTypes, ")"); appendIfNotEmpty(sb, " throws ", throwsTypes, ""); return sb.toString(); } public final List typeParamTypes; public final List paramTypes; public final Type returnType; public final List throwsTypes; } /** * Represents a method type signature. * * See; * JVMS ??? * FunctionTypeSignature: * {@code #} ReturnType {@code (} TypeSignature* {@code)} */ public static class FunctionType extends Type { public FunctionType(Type returnType, List parameterTypes) { this.returnType = returnType; this.parameterTypes = parameterTypes; } public R accept(Visitor visitor, D data) { return visitor.visitFunctionType(this, data); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append('#').append(returnType); append(sb, "(", parameterTypes, ")"); return sb.toString(); } public final List parameterTypes; public final Type returnType; } /** * Represents a class signature. These describe the signature of * a class that has type arguments. * * See: * JVMS 4.3.4 * ClassSignature: * FormalTypeParameters_opt SuperclassSignature SuperinterfaceSignature* */ public static class ClassSigType extends Type { public ClassSigType(List typeParamTypes, Type superclassType, List superinterfaceTypes) { this.typeParamTypes = typeParamTypes; this.superclassType = superclassType; this.superinterfaceTypes = superinterfaceTypes; } public R accept(Visitor visitor, D data) { return visitor.visitClassSigType(this, data); } @Override public String toString() { StringBuilder sb = new StringBuilder(); appendIfNotEmpty(sb, "<", typeParamTypes, ">"); if (superclassType != null) { sb.append(" extends "); sb.append(superclassType); } appendIfNotEmpty(sb, " implements ", superinterfaceTypes, ""); return sb.toString(); } public final List typeParamTypes; public final Type superclassType; public final List superinterfaceTypes; } /** * Represents a class type signature. This is used to represent a * reference to a class, such as in a field, parameter, return type, etc. * * See: * JVMS 4.3.4 * ClassTypeSignature: * {@code L} PackageSpecifier_opt SimpleClassTypeSignature * ClassTypeSignatureSuffix* {@code ;} * PackageSpecifier: * Identifier {@code /} PackageSpecifier* * SimpleClassTypeSignature: * Identifier TypeArguments_opt } * ClassTypeSignatureSuffix: * {@code .} SimpleClassTypeSignature */ public static class ClassType extends Type { public ClassType(ClassType outerType, String name, List typeArgs) { this.outerType = outerType; this.name = name; this.typeArgs = typeArgs; } public R accept(Visitor visitor, D data) { return visitor.visitClassType(this, data); } public String getBinaryName() { if (outerType == null) return name; else return (outerType.getBinaryName() + "$" + name); } @Override public String toString() { StringBuilder sb = new StringBuilder(); if (outerType != null) { sb.append(outerType); sb.append("."); } sb.append(name); appendIfNotEmpty(sb, "<", typeArgs, ">"); return sb.toString(); } public final ClassType outerType; public final String name; public final List typeArgs; } /** * Represents a FormalTypeParameter. These are used to declare the type * parameters for generic classes and methods. * * See: * JVMS 4.3.4 * FormalTypeParameters: * {@code <} FormalTypeParameter+ {@code >} * FormalTypeParameter: * Identifier ClassBound InterfaceBound* * ClassBound: * {@code :} FieldTypeSignature_opt * InterfaceBound: * {@code :} FieldTypeSignature */ public static class TypeParamType extends Type { public TypeParamType(String name, Type classBound, List interfaceBounds) { this.name = name; this.classBound = classBound; this.interfaceBounds = interfaceBounds; } public R accept(Visitor visitor, D data) { return visitor.visitTypeParamType(this, data); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(name); String sep = " extends "; if (classBound != null) { sb.append(sep); sb.append(classBound); sep = " & "; } if (interfaceBounds != null) { for (Type bound: interfaceBounds) { sb.append(sep); sb.append(bound); sep = " & "; } } return sb.toString(); } public final String name; public final Type classBound; public final List interfaceBounds; } /** * Represents a wildcard type argument. A type argument that is not a * wildcard type argument will be represented by a ClassType, ArrayType, etc. * * See: * JVMS 4.3.4 * TypeArgument: * WildcardIndicator_opt FieldTypeSignature * {@code *} * WildcardIndicator: * {@code +} * {@code -} */ public static class WildcardType extends Type { public enum Kind { UNBOUNDED, EXTENDS, SUPER }; public WildcardType() { this(Kind.UNBOUNDED, null); } public WildcardType(Kind kind, Type boundType) { this.kind = kind; this.boundType = boundType; } public R accept(Visitor visitor, D data) { return visitor.visitWildcardType(this, data); } @Override public String toString() { switch (kind) { case UNBOUNDED: return "?"; case EXTENDS: return "? extends " + boundType; case SUPER: return "? super " + boundType; default: throw new AssertionError(); } } public final Kind kind; public final Type boundType; } }