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