jjg@46: /*
ohair@554: * Copyright (c) 2007, 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@46: import java.util.ArrayList;
jjg@46: import java.util.List;
jjg@427: import com.sun.tools.classfile.Type.*;
jjg@46:
jjg@46: /**
jjh@972: * See JVMS 4.4.4.
jjg@46: *
jjg@581: *
This is NOT part of any supported API.
jjg@581: * If 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@46: public class Signature extends Descriptor {
jjg@46:
jjg@46: public Signature(int index) {
jjg@46: super(index);
jjg@46: }
jjg@46:
jjg@46: public Type getType(ConstantPool constant_pool) throws ConstantPoolException {
jjg@46: if (type == null)
jjg@46: type = parse(getValue(constant_pool));
jjg@46: return type;
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@46: public int getParameterCount(ConstantPool constant_pool) throws ConstantPoolException {
jjg@427: MethodType m = (MethodType) getType(constant_pool);
jjg@427: return m.paramTypes.size();
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@46: public String getParameterTypes(ConstantPool constant_pool) throws ConstantPoolException {
jjg@427: MethodType m = (MethodType) getType(constant_pool);
jjg@46: StringBuilder sb = new StringBuilder();
jjg@46: sb.append("(");
jjg@46: String sep = "";
jjg@427: for (Type paramType: m.paramTypes) {
jjg@46: sb.append(sep);
jjg@427: sb.append(paramType);
jjg@46: sep = ", ";
jjg@46: }
jjg@46: sb.append(")");
jjg@46: return sb.toString();
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@46: public String getReturnType(ConstantPool constant_pool) throws ConstantPoolException {
jjg@427: MethodType m = (MethodType) getType(constant_pool);
jjg@46: return m.returnType.toString();
jjg@46: }
jjg@46:
jjg@46: @Override
jjg@46: public String getFieldType(ConstantPool constant_pool) throws ConstantPoolException {
jjg@46: return getType(constant_pool).toString();
jjg@46: }
jjg@46:
jjg@46: private Type parse(String sig) {
jjg@46: this.sig = sig;
jjg@46: sigp = 0;
jjg@46:
jjg@427: List typeParamTypes = null;
jjg@46: if (sig.charAt(sigp) == '<')
jjg@427: typeParamTypes = parseTypeParamTypes();
jjg@46:
jjg@46: if (sig.charAt(sigp) == '(') {
jjg@427: List paramTypes = parseTypeSignatures(')');
jjg@46: Type returnType = parseTypeSignature();
jjg@46: List throwsTypes = null;
jjg@46: while (sigp < sig.length() && sig.charAt(sigp) == '^') {
jjg@46: sigp++;
jjg@46: if (throwsTypes == null)
jjg@46: throwsTypes = new ArrayList();
jjg@46: throwsTypes.add(parseTypeSignature());
jjg@46: }
jjg@427: return new MethodType(typeParamTypes, paramTypes, returnType, throwsTypes);
jjg@46: } else {
jjg@46: Type t = parseTypeSignature();
jjg@427: if (typeParamTypes == null && sigp == sig.length())
jjg@46: return t;
jjg@46: Type superclass = t;
jjg@427: List superinterfaces = null;
jjg@427: while (sigp < sig.length()) {
jjg@427: if (superinterfaces == null)
jjg@427: superinterfaces = new ArrayList();
jjg@46: superinterfaces.add(parseTypeSignature());
jjg@427: }
jjg@427: return new ClassSigType(typeParamTypes, superclass, superinterfaces);
jjg@46:
jjg@46: }
jjg@46: }
jjg@46:
jjg@46: private Type parseTypeSignature() {
jjg@46: switch (sig.charAt(sigp)) {
jjg@46: case 'B':
jjg@46: sigp++;
jjg@427: return new SimpleType("byte");
jjg@46:
jjg@46: case 'C':
jjg@46: sigp++;
jjg@427: return new SimpleType("char");
jjg@46:
jjg@46: case 'D':
jjg@46: sigp++;
jjg@427: return new SimpleType("double");
jjg@46:
jjg@46: case 'F':
jjg@46: sigp++;
jjg@427: return new SimpleType("float");
jjg@46:
jjg@46: case 'I':
jjg@46: sigp++;
jjg@427: return new SimpleType("int");
jjg@46:
jjg@46: case 'J':
jjg@46: sigp++;
jjg@427: return new SimpleType("long");
jjg@46:
jjg@46: case 'L':
jjg@46: return parseClassTypeSignature();
jjg@46:
jjg@46: case 'S':
jjg@46: sigp++;
jjg@427: return new SimpleType("short");
jjg@46:
jjg@46: case 'T':
jjg@46: return parseTypeVariableSignature();
jjg@46:
jjg@46: case 'V':
jjg@46: sigp++;
jjg@427: return new SimpleType("void");
jjg@46:
jjg@46: case 'Z':
jjg@46: sigp++;
jjg@427: return new SimpleType("boolean");
jjg@46:
jjg@46: case '[':
jjg@46: sigp++;
jjg@427: return new ArrayType(parseTypeSignature());
jjg@46:
jjg@46: case '*':
jjg@46: sigp++;
jjg@427: return new WildcardType();
jjg@46:
jjg@46: case '+':
jjg@46: sigp++;
jjg@427: return new WildcardType(WildcardType.Kind.EXTENDS, parseTypeSignature());
jjg@46:
jjg@46: case '-':
jjg@46: sigp++;
jjg@427: return new WildcardType(WildcardType.Kind.SUPER, parseTypeSignature());
jjg@46:
jjg@46: default:
jjg@46: throw new IllegalStateException(debugInfo());
jjg@46: }
jjg@46: }
jjg@46:
jjg@46: private List parseTypeSignatures(char term) {
jjg@46: sigp++;
jjg@46: List types = new ArrayList();
jjg@46: while (sig.charAt(sigp) != term)
jjg@46: types.add(parseTypeSignature());
jjg@46: sigp++;
jjg@46: return types;
jjg@46: }
jjg@46:
jjg@46: private Type parseClassTypeSignature() {
jjg@46: assert sig.charAt(sigp) == 'L';
jjg@46: sigp++;
jjg@46: return parseClassTypeSignatureRest();
jjg@46: }
jjg@46:
jjg@46: private Type parseClassTypeSignatureRest() {
jjg@46: StringBuilder sb = new StringBuilder();
jjg@427: List argTypes = null;
jjg@427: ClassType t = null;
jjg@427: char sigch ;
jjg@427:
jjg@427: do {
jjg@46: switch (sigch = sig.charAt(sigp)) {
jjg@427: case '<':
jjg@427: argTypes = parseTypeSignatures('>');
jjg@46: break;
jjg@46:
jjg@46: case '.':
jjg@46: case ';':
jjg@46: sigp++;
jjg@427: t = new ClassType(t, sb.toString(), argTypes);
jjg@427: sb.setLength(0);
jjg@427: argTypes = null;
jjg@46: break;
jjg@46:
jjg@46: default:
jjg@46: sigp++;
jjg@46: sb.append(sigch);
jjg@46: break;
jjg@46: }
jjg@427: } while (sigch != ';');
jjg@427:
jjg@427: return t;
jjg@46: }
jjg@46:
jjg@427: private List parseTypeParamTypes() {
jjg@46: assert sig.charAt(sigp) == '<';
jjg@46: sigp++;
jjg@427: List types = new ArrayList();
jjg@46: while (sig.charAt(sigp) != '>')
jjg@427: types.add(parseTypeParamType());
jjg@46: sigp++;
jjg@46: return types;
jjg@46: }
jjg@46:
jjg@427: private TypeParamType parseTypeParamType() {
jjg@46: int sep = sig.indexOf(":", sigp);
jjg@46: String name = sig.substring(sigp, sep);
jjg@46: Type classBound = null;
jjg@46: List interfaceBounds = null;
jjg@46: sigp = sep + 1;
jjg@46: if (sig.charAt(sigp) != ':')
jjg@46: classBound = parseTypeSignature();
jjg@46: while (sig.charAt(sigp) == ':') {
jjg@46: sigp++;
jjg@46: if (interfaceBounds == null)
jjg@46: interfaceBounds = new ArrayList();
jjg@46: interfaceBounds.add(parseTypeSignature());
jjg@46: }
jjg@427: return new TypeParamType(name, classBound, interfaceBounds);
jjg@46: }
jjg@46:
jjg@46: private Type parseTypeVariableSignature() {
jjg@46: sigp++;
jjg@46: int sep = sig.indexOf(';', sigp);
jjg@427: Type t = new SimpleType(sig.substring(sigp, sep));
jjg@46: sigp = sep + 1;
jjg@46: return t;
jjg@46: }
jjg@46:
jjg@46: private String debugInfo() {
jjg@46: return sig.substring(0, sigp) + "!" + sig.charAt(sigp) + "!" + sig.substring(sigp+1);
jjg@46: }
jjg@46:
jjg@46: private String sig;
jjg@46: private int sigp;
jjg@46:
jjg@46: private Type type;
jjg@46: }