jjg@46: /* ohair@554: * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. jjg@46: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@46: * jjg@46: * This code is free software; you can redistribute it and/or modify it jjg@46: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this jjg@46: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. jjg@46: * jjg@46: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@46: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@46: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@46: * version 2 for more details (a copy is included in the LICENSE file that jjg@46: * accompanied this code). jjg@46: * jjg@46: * You should have received a copy of the GNU General Public License version jjg@46: * 2 along with this work; if not, write to the Free Software Foundation, jjg@46: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@46: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. jjg@46: */ jjg@46: jjg@46: package com.sun.tools.classfile; jjg@46: jjg@280: import java.util.Arrays; jjg@280: import java.util.HashSet; jjg@46: import java.util.List; jjg@280: import java.util.Set; jjg@46: jjg@46: /* jjg@427: * Family of classes used to represent the parsed form of a {@link Descriptor} jjg@427: * or {@link Signature}. jjg@427: * jjg@46: *

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