Signature.java revision 2942:08092deced3f
139665Smsmith/* 239665Smsmith * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. 339665Smsmith * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 439665Smsmith * 539665Smsmith * This code is free software; you can redistribute it and/or modify it 639665Smsmith * under the terms of the GNU General Public License version 2 only, as 739665Smsmith * published by the Free Software Foundation. Oracle designates this 839665Smsmith * particular file as subject to the "Classpath" exception as provided 939665Smsmith * by Oracle in the LICENSE file that accompanied this code. 1039665Smsmith * 1139665Smsmith * This code is distributed in the hope that it will be useful, but WITHOUT 1239665Smsmith * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1339665Smsmith * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1439665Smsmith * version 2 for more details (a copy is included in the LICENSE file that 1539665Smsmith * accompanied this code). 1639665Smsmith * 1739665Smsmith * You should have received a copy of the GNU General Public License version 1839665Smsmith * 2 along with this work; if not, write to the Free Software Foundation, 1939665Smsmith * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2039665Smsmith * 2139665Smsmith * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2239665Smsmith * or visit www.oracle.com if you need additional information or have any 2339665Smsmith * questions. 2439665Smsmith */ 2539665Smsmith 2639665Smsmithpackage com.sun.tools.classfile; 2739665Smsmith 2839665Smsmithimport java.util.ArrayList; 2939863Smsmithimport java.util.List; 3039665Smsmithimport com.sun.tools.classfile.Type.*; 3139665Smsmith 3239665Smsmith/** 3339665Smsmith * See JVMS 4.4.4. 3439665Smsmith * 3539665Smsmith * <p><b>This is NOT part of any supported API. 3639665Smsmith * If you write code that depends on this, you do so at your own risk. 3739665Smsmith * This code and its internal interfaces are subject to change or 3839863Smsmith * deletion without notice.</b> 3939665Smsmith */ 4039665Smsmithpublic class Signature extends Descriptor { 4139665Smsmith 4239665Smsmith public Signature(int index) { 4339665Smsmith super(index); 4439665Smsmith } 4539665Smsmith 4639665Smsmith public Type getType(ConstantPool constant_pool) throws ConstantPoolException { 4739672Sdfr if (type == null) 4839672Sdfr type = parse(getValue(constant_pool)); 4939672Sdfr return type; 5039672Sdfr } 5139672Sdfr 5239665Smsmith @Override 5339665Smsmith public int getParameterCount(ConstantPool constant_pool) throws ConstantPoolException { 5439665Smsmith MethodType m = (MethodType) getType(constant_pool); 5539665Smsmith return m.paramTypes.size(); 5639665Smsmith } 5739665Smsmith 5839665Smsmith @Override 5939665Smsmith public String getParameterTypes(ConstantPool constant_pool) throws ConstantPoolException { 6039665Smsmith MethodType m = (MethodType) getType(constant_pool); 6139665Smsmith StringBuilder sb = new StringBuilder(); 6239665Smsmith sb.append("("); 6339665Smsmith String sep = ""; 6439665Smsmith for (Type paramType: m.paramTypes) { 6539665Smsmith sb.append(sep); 6639665Smsmith sb.append(paramType); 6739665Smsmith sep = ", "; 6839665Smsmith } 6939665Smsmith sb.append(")"); 7039665Smsmith return sb.toString(); 7139665Smsmith } 7239665Smsmith 7339665Smsmith @Override 7439665Smsmith public String getReturnType(ConstantPool constant_pool) throws ConstantPoolException { 7539665Smsmith MethodType m = (MethodType) getType(constant_pool); 7639665Smsmith return m.returnType.toString(); 7739665Smsmith } 7839665Smsmith 7939665Smsmith @Override 8039665Smsmith public String getFieldType(ConstantPool constant_pool) throws ConstantPoolException { 8139665Smsmith return getType(constant_pool).toString(); 8239665Smsmith } 8339665Smsmith 8439665Smsmith private Type parse(String sig) { 8539665Smsmith this.sig = sig; 8639665Smsmith sigp = 0; 8739665Smsmith 8839665Smsmith List<TypeParamType> typeParamTypes = null; 8939665Smsmith if (sig.charAt(sigp) == '<') 9039665Smsmith typeParamTypes = parseTypeParamTypes(); 9139665Smsmith 9239665Smsmith if (sig.charAt(sigp) == '(') { 9339665Smsmith List<Type> paramTypes = parseTypeSignatures(')'); 9439665Smsmith Type returnType = parseTypeSignature(); 9539863Smsmith List<Type> throwsTypes = null; 9639863Smsmith while (sigp < sig.length() && sig.charAt(sigp) == '^') { 9739665Smsmith sigp++; 9839665Smsmith if (throwsTypes == null) 9939665Smsmith throwsTypes = new ArrayList<>(); 10039863Smsmith throwsTypes.add(parseTypeSignature()); 10139863Smsmith } 10239665Smsmith return new MethodType(typeParamTypes, paramTypes, returnType, throwsTypes); 10339665Smsmith } else { 10439665Smsmith Type t = parseTypeSignature(); 10539665Smsmith if (typeParamTypes == null && sigp == sig.length()) 10639665Smsmith return t; 10739665Smsmith Type superclass = t; 10839665Smsmith List<Type> superinterfaces = null; 10939665Smsmith while (sigp < sig.length()) { 11039665Smsmith if (superinterfaces == null) 11139665Smsmith superinterfaces = new ArrayList<>(); 11239665Smsmith superinterfaces.add(parseTypeSignature()); 11339665Smsmith } 11439665Smsmith return new ClassSigType(typeParamTypes, superclass, superinterfaces); 11539665Smsmith 11639665Smsmith } 11739665Smsmith } 11839665Smsmith 11939665Smsmith private Type parseTypeSignature() { 12039665Smsmith switch (sig.charAt(sigp)) { 12139665Smsmith case 'B': 12239665Smsmith sigp++; 12339665Smsmith return new SimpleType("byte"); 12439665Smsmith 12539665Smsmith case 'C': 12639665Smsmith sigp++; 12739665Smsmith return new SimpleType("char"); 12839665Smsmith 12939665Smsmith case 'D': 13039665Smsmith sigp++; 13139665Smsmith return new SimpleType("double"); 13239665Smsmith 13339665Smsmith case 'F': 13439665Smsmith sigp++; 13539665Smsmith return new SimpleType("float"); 13639665Smsmith 13739665Smsmith case 'I': 13839665Smsmith sigp++; 13939665Smsmith return new SimpleType("int"); 14039665Smsmith 14139665Smsmith case 'J': 14239665Smsmith sigp++; 14339665Smsmith return new SimpleType("long"); 14439665Smsmith 14539665Smsmith case 'L': 14639665Smsmith return parseClassTypeSignature(); 14739665Smsmith 14839665Smsmith case 'S': 14939665Smsmith sigp++; 15039665Smsmith return new SimpleType("short"); 15139665Smsmith 15239665Smsmith case 'T': 15339665Smsmith return parseTypeVariableSignature(); 15439665Smsmith 15539665Smsmith case 'V': 15639665Smsmith sigp++; 15739665Smsmith return new SimpleType("void"); 15839665Smsmith 15939665Smsmith case 'Z': 16039665Smsmith sigp++; 16139665Smsmith return new SimpleType("boolean"); 16239665Smsmith 16339665Smsmith case '[': 16439665Smsmith sigp++; 16539665Smsmith return new ArrayType(parseTypeSignature()); 16639665Smsmith 16739665Smsmith case '*': 16839665Smsmith sigp++; 16939665Smsmith return new WildcardType(); 17039665Smsmith 17139665Smsmith case '+': 17239665Smsmith sigp++; 17339665Smsmith return new WildcardType(WildcardType.Kind.EXTENDS, parseTypeSignature()); 17439665Smsmith 17539665Smsmith case '-': 17639665Smsmith sigp++; 17739665Smsmith return new WildcardType(WildcardType.Kind.SUPER, parseTypeSignature()); 17839665Smsmith 17939665Smsmith default: 18039665Smsmith throw new IllegalStateException(debugInfo()); 18139665Smsmith } 18239665Smsmith } 18339665Smsmith 18439665Smsmith private List<Type> parseTypeSignatures(char term) { 18539665Smsmith sigp++; 18639665Smsmith List<Type> types = new ArrayList<>(); 18739665Smsmith while (sig.charAt(sigp) != term) 18839665Smsmith types.add(parseTypeSignature()); 189 sigp++; 190 return types; 191 } 192 193 private Type parseClassTypeSignature() { 194 assert sig.charAt(sigp) == 'L'; 195 sigp++; 196 return parseClassTypeSignatureRest(); 197 } 198 199 private Type parseClassTypeSignatureRest() { 200 StringBuilder sb = new StringBuilder(); 201 List<Type> argTypes = null; 202 ClassType t = null; 203 char sigch ; 204 205 do { 206 switch (sigch = sig.charAt(sigp)) { 207 case '<': 208 argTypes = parseTypeSignatures('>'); 209 break; 210 211 case '.': 212 case ';': 213 sigp++; 214 t = new ClassType(t, sb.toString(), argTypes); 215 sb.setLength(0); 216 argTypes = null; 217 break; 218 219 default: 220 sigp++; 221 sb.append(sigch); 222 break; 223 } 224 } while (sigch != ';'); 225 226 return t; 227 } 228 229 private List<TypeParamType> parseTypeParamTypes() { 230 assert sig.charAt(sigp) == '<'; 231 sigp++; 232 List<TypeParamType> types = new ArrayList<>(); 233 while (sig.charAt(sigp) != '>') 234 types.add(parseTypeParamType()); 235 sigp++; 236 return types; 237 } 238 239 private TypeParamType parseTypeParamType() { 240 int sep = sig.indexOf(":", sigp); 241 String name = sig.substring(sigp, sep); 242 Type classBound = null; 243 List<Type> interfaceBounds = null; 244 sigp = sep + 1; 245 if (sig.charAt(sigp) != ':') 246 classBound = parseTypeSignature(); 247 while (sig.charAt(sigp) == ':') { 248 sigp++; 249 if (interfaceBounds == null) 250 interfaceBounds = new ArrayList<>(); 251 interfaceBounds.add(parseTypeSignature()); 252 } 253 return new TypeParamType(name, classBound, interfaceBounds); 254 } 255 256 private Type parseTypeVariableSignature() { 257 sigp++; 258 int sep = sig.indexOf(';', sigp); 259 Type t = new SimpleType(sig.substring(sigp, sep)); 260 sigp = sep + 1; 261 return t; 262 } 263 264 private String debugInfo() { 265 return sig.substring(0, sigp) + "!" + sig.charAt(sigp) + "!" + sig.substring(sigp+1); 266 } 267 268 private String sig; 269 private int sigp; 270 271 private Type type; 272} 273