169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.DataInputStream;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Map;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.ArrayList;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtClass;
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Signature_attribute</code>.
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class SignatureAttribute extends AttributeInfo {
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The name of this attribute <code>"Signature"</code>.
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String tag = "Signature";
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    SignatureAttribute(ConstPool cp, int n, DataInputStream in)
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws IOException
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, n, in);
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs a Signature attribute.
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param cp                a constant pool table.
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param signature         the signature represented by this attribute.
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public SignatureAttribute(ConstPool cp, String signature) {
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(cp, tag);
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int index = cp.addUtf8Info(signature);
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        byte[] bvalue = new byte[2];
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        bvalue[0] = (byte)(index >>> 8);
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        bvalue[1] = (byte)index;
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        set(bvalue);
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the signature indicated by <code>signature_index</code>.
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #toClassSignature(String)
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #toMethodSignature(String)
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getSignature() {
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return getConstPool().getUtf8Info(ByteArray.readU16bit(get(), 0));
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets <code>signature_index</code> to the index of the given signature,
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * which is added to a constant pool.
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param sig       new signature.
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.11
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setSignature(String sig) {
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int index = getConstPool().addUtf8Info(sig);
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ByteArray.write16bit(index, info, 0);
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes a copy.  Class names are replaced according to the
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * given <code>Map</code> object.
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param newCp     the constant pool table used by the new copy.
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param classnames        pairs of replaced and substituted
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          class names.
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public AttributeInfo copy(ConstPool newCp, Map classnames) {
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return new SignatureAttribute(newCp, getSignature());
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void renameClass(String oldname, String newname) {
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String sig = renameClass(getSignature(), oldname, newname);
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        setSignature(sig);
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void renameClass(Map classnames) {
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String sig = renameClass(getSignature(), classnames);
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        setSignature(sig);
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static String renameClass(String desc, String oldname, String newname) {
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Map map = new java.util.HashMap();
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        map.put(oldname, newname);
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return renameClass(desc, map);
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static String renameClass(String desc, Map map) {
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (map == null)
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return desc;
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        StringBuilder newdesc = new StringBuilder();
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int head = 0;
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i = 0;
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (;;) {
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int j = desc.indexOf('L', i);
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (j < 0)
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            StringBuilder nameBuf = new StringBuilder();
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int k = j;
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            char c;
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            try {
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                while ((c = desc.charAt(++k)) != ';') {
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    nameBuf.append(c);
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (c == '<') {
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        while ((c = desc.charAt(++k)) != '>')
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            nameBuf.append(c);
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        nameBuf.append(c);
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    }
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            catch (IndexOutOfBoundsException e) { break; }
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            i = k + 1;
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String name = nameBuf.toString();
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String name2 = (String)map.get(name);
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (name2 != null) {
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                newdesc.append(desc.substring(head, j));
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                newdesc.append('L');
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                newdesc.append(name2);
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                newdesc.append(c);
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                head = i;
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (head == 0)
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return desc;
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int len = desc.length();
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (head < len)
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                newdesc.append(desc.substring(head, len));
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return newdesc.toString();
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static boolean isNamePart(int c) {
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return c != ';' && c != '<';
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static private class Cursor {
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int position = 0;
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int indexOf(String s, int ch) throws BadBytecode {
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int i = s.indexOf(ch, position);
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (i < 0)
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw error(s);
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                position = i + 1;
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return i;
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Class signature.
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class ClassSignature {
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        TypeParameter[] params;
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassType superClass;
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassType[] interfaces;
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassSignature(TypeParameter[] p, ClassType s, ClassType[] i) {
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            params = p;
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            superClass = s;
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            interfaces = i;
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the type parameters.
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return a zero-length array if the type parameters are not specified.
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public TypeParameter[] getParameters() {
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return params;
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the super class.
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public ClassType getSuperClass() { return superClass; }
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the super interfaces.
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return a zero-length array if the super interfaces are not specified.
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public ClassType[] getInterfaces() { return interfaces; }
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the string representation.
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String toString() {
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            StringBuffer sbuf = new StringBuffer();
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TypeParameter.toString(sbuf, params);
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            sbuf.append(" extends ").append(superClass);
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (interfaces.length > 0) {
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append(" implements ");
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                Type.toString(sbuf, interfaces);
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return sbuf.toString();
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Method type signature.
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class MethodSignature {
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        TypeParameter[] typeParams;
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Type[] params;
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Type retType;
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ObjectType[] exceptions;
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        MethodSignature(TypeParameter[] tp, Type[] p, Type ret, ObjectType[] ex) {
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            typeParams = tp;
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            params = p;
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            retType = ret;
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exceptions = ex;
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the formal type parameters.
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return a zero-length array if the type parameters are not specified.
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public TypeParameter[] getTypeParameters() { return typeParams; }
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the types of the formal parameters.
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return a zero-length array if no formal parameter is taken.
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public Type[] getParameterTypes() { return params; }
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the type of the returned value.
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public Type getReturnType() { return retType; }
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the types of the exceptions that may be thrown.
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return a zero-length array if exceptions are never thrown or
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * the exception types are not parameterized types or type variables.
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public ObjectType[] getExceptionTypes() { return exceptions; }
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the string representation.
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String toString() {
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            StringBuffer sbuf = new StringBuffer();
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TypeParameter.toString(sbuf, typeParams);
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            sbuf.append(" (");
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Type.toString(sbuf, params);
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            sbuf.append(") ");
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            sbuf.append(retType);
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (exceptions.length > 0) {
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append(" throws ");
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                Type.toString(sbuf, exceptions);
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return sbuf.toString();
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Formal type parameters.
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class TypeParameter {
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String name;
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ObjectType superClass;
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ObjectType[] superInterfaces;
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        TypeParameter(String sig, int nb, int ne, ObjectType sc, ObjectType[] si) {
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            name = sig.substring(nb, ne);
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            superClass = sc;
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            superInterfaces = si;
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the name of the type parameter.
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String getName() {
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return name;
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the class bound of this parameter.
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return null if the class bound is not specified.
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public ObjectType getClassBound() { return superClass; }
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the interface bound of this parameter.
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return a zero-length array if the interface bound is not specified.
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public ObjectType[] getInterfaceBound() { return superInterfaces; }
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the string representation.
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String toString() {
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            StringBuffer sbuf = new StringBuffer(getName());
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (superClass != null)
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append(" extends ").append(superClass.toString());
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int len = superInterfaces.length;
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (len > 0) {
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                for (int i = 0; i < len; i++) {
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (i > 0 || superClass != null)
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        sbuf.append(" & ");
33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    else
33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        sbuf.append(" extends ");
33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    sbuf.append(superInterfaces[i].toString());
33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return sbuf.toString();
34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        static void toString(StringBuffer sbuf, TypeParameter[] tp) {
34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            sbuf.append('<');
34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < tp.length; i++) {
34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (i > 0)
34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    sbuf.append(", ");
34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append(tp[i]);
35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            sbuf.append('>');
35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Type argument.
35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class TypeArgument {
36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ObjectType arg;
36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        char wildcard;
36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        TypeArgument(ObjectType a, char w) {
36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            arg = a;
36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            wildcard = w;
36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the kind of this type argument.
37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return <code>' '</code> (not-wildcard), <code>'*'</code> (wildcard), <code>'+'</code> (wildcard with
37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * upper bound), or <code>'-'</code> (wildcard with lower bound).
37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public char getKind() { return wildcard; }
37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns true if this type argument is a wildcard type
37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * such as <code>?</code>, <code>? extends String</code>, or <code>? super Integer</code>.
38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public boolean isWildcard() { return wildcard != ' '; }
38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the type represented by this argument
38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * if the argument is not a wildcard type.  Otherwise, this method
38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * returns the upper bound (if the kind is '+'),
38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * the lower bound (if the kind is '-'), or null (if the upper or lower
38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * bound is not specified).
38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public ObjectType getType() { return arg; }
39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the string representation.
39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String toString() {
39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (wildcard == '*')
39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return "?";
39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String type = arg.toString();
40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (wildcard == ' ')
40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return type;
40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (wildcard == '+')
40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return "? extends " + type;
40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return "? super " + type;
40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Primitive types and object types.
41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static abstract class Type {
41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        static void toString(StringBuffer sbuf, Type[] ts) {
41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < ts.length; i++) {
41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (i > 0)
41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    sbuf.append(", ");
41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append(ts[i]);
41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Primitive types.
42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class BaseType extends Type {
42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        char descriptor;
42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        BaseType(char c) { descriptor = c; }
42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the descriptor representing this primitive type.
43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @see javassist.bytecode.Descriptor
43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public char getDescriptor() { return descriptor; }
43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the <code>CtClass</code> representing this
43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * primitive type.
44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public CtClass getCtlass() {
44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return Descriptor.toPrimitiveClass(descriptor);
44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the string representation.
44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String toString() {
44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return Descriptor.toClassName(Character.toString(descriptor));
45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Class types, array types, and type variables.
45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static abstract class ObjectType extends Type {}
45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Class types.
46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class ClassType extends ObjectType {
46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String name;
46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        TypeArgument[] arguments;
46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        static ClassType make(String s, int b, int e,
46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              TypeArgument[] targs, ClassType parent) {
46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (parent == null)
46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return new ClassType(s, b, e, targs);
46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return new NestedClassType(s, b, e, targs, parent);
47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassType(String signature, int begin, int end, TypeArgument[] targs) {
47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            name = signature.substring(begin, end).replace('/', '.');
47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            arguments = targs;
47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the class name.
48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String getName() {
48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return name;
48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the type arguments.
48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return null if no type arguments are given to this class.
48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public TypeArgument[] getTypeArguments() { return arguments; }
49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * If this class is a member of another class, returns the
49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * class in which this class is declared.
49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         *
49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * @return null if this class is not a member of another class.
49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public ClassType getDeclaringClass() { return null; }
49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the string representation.
50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String toString() {
50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            StringBuffer sbuf = new StringBuffer();
50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ClassType parent = getDeclaringClass();
50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (parent != null)
50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append(parent.toString()).append('.');
50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            sbuf.append(name);
51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (arguments != null) {
51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append('<');
51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int n = arguments.length;
51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                for (int i = 0; i < n; i++) {
51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (i > 0)
51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        sbuf.append(", ");
51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    sbuf.append(arguments[i].toString());
51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append('>');
52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return sbuf.toString();
52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
52769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
52869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Nested class types.
52969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
53069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class NestedClassType extends ClassType {
53169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassType parent;
53269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        NestedClassType(String s, int b, int e,
53369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        TypeArgument[] targs, ClassType p) {
53469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super(s, b, e, targs);
53569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            parent = p;
53669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
53769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
53869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
53969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the class that declares this nested class.
54069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * This nested class is a member of that declaring class.
54169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
54269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public ClassType getDeclaringClass() { return parent; }
54369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
54469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
54569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
54669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Array types.
54769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
54869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class ArrayType extends ObjectType {
54969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int dim;
55069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Type componentType;
55169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
55269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public ArrayType(int d, Type comp) {
55369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            dim = d;
55469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            componentType = comp;
55569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
55669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
55769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
55869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the dimension of the array.
55969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
56069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public int getDimension() { return dim; }
56169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
56269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
56369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the component type.
56469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
56569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public Type getComponentType() {
56669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return componentType;
56769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
56869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
56969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
57069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the string representation.
57169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
57269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String toString() {
57369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            StringBuffer sbuf = new StringBuffer(componentType.toString());
57469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < dim; i++)
57569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append("[]");
57669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
57769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return sbuf.toString();
57869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
57969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
58069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
58169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
58269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Type variables.
58369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
58469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class TypeVariable extends ObjectType {
58569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String name;
58669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
58769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        TypeVariable(String sig, int begin, int end) {
58869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            name = sig.substring(begin, end);
58969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
59069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
59169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
59269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the variable name.
59369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
59469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String getName() {
59569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return name;
59669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
59769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
59869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /**
59969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * Returns the string representation.
60069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
60169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public String toString() {
60269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return name;
60369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
60469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
60569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
60669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
60769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Parses the given signature string as a class signature.
60869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
60969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param  sig                  the signature.
61069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws BadBytecode          thrown when a syntactical error is found.
61169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.5
61269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
61369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static ClassSignature toClassSignature(String sig) throws BadBytecode {
61469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
61569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return parseSig(sig);
61669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
61769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (IndexOutOfBoundsException e) {
61869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw error(sig);
61969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
62069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
62169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
62269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
62369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Parses the given signature string as a method type signature.
62469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
62569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param  sig                  the signature.
62669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws BadBytecode          thrown when a syntactical error is found.
62769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.5
62869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
62969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static MethodSignature toMethodSignature(String sig) throws BadBytecode {
63069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
63169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return parseMethodSig(sig);
63269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
63369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (IndexOutOfBoundsException e) {
63469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw error(sig);
63569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
63669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
63769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
63869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
63969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Parses the given signature string as a field type signature.
64069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
64169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param  sig                  the signature string.
64269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return the field type signature.
64369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @throws BadBytecode          thrown when a syntactical error is found.
64469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.5
64569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
64669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static ObjectType toFieldSignature(String sig) throws BadBytecode {
64769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
64869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return parseObjectType(sig, new Cursor(), false);
64969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
65069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (IndexOutOfBoundsException e) {
65169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw error(sig);
65269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
65369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
65469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
65569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static ClassSignature parseSig(String sig)
65669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode, IndexOutOfBoundsException
65769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
65869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Cursor cur = new Cursor();
65969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        TypeParameter[] tp = parseTypeParams(sig, cur);
66069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassType superClass = parseClassType(sig, cur);
66169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int sigLen = sig.length();
66269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList ifArray = new ArrayList();
66369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (cur.position < sigLen && sig.charAt(cur.position) == 'L')
66469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ifArray.add(parseClassType(sig, cur));
66569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
66669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassType[] ifs
66769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = (ClassType[])ifArray.toArray(new ClassType[ifArray.size()]);
66869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return new ClassSignature(tp, superClass, ifs);
66969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
67069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
67169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static MethodSignature parseMethodSig(String sig)
67269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
67369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
67469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Cursor cur = new Cursor();
67569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        TypeParameter[] tp = parseTypeParams(sig, cur);
67669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (sig.charAt(cur.position++) != '(')
67769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw error(sig);
67869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
67969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList params = new ArrayList();
68069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (sig.charAt(cur.position) != ')') {
68169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Type t = parseType(sig, cur);
68269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            params.add(t);
68369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
68469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
68569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        cur.position++;
68669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Type ret = parseType(sig, cur);
68769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int sigLen = sig.length();
68869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList exceptions = new ArrayList();
68969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (cur.position < sigLen && sig.charAt(cur.position) == '^') {
69069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            cur.position++;
69169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ObjectType t = parseObjectType(sig, cur, false);
69269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (t instanceof ArrayType)
69369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw error(sig);
69469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
69569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exceptions.add(t);
69669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
69769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
69869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Type[] p = (Type[])params.toArray(new Type[params.size()]);
69969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ObjectType[] ex = (ObjectType[])exceptions.toArray(new ObjectType[exceptions.size()]);
70069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return new MethodSignature(tp, p, ret, ex);
70169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
70269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
70369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static TypeParameter[] parseTypeParams(String sig, Cursor cur)
70469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
70569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
70669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList typeParam = new ArrayList();
70769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (sig.charAt(cur.position) == '<') {
70869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            cur.position++;
70969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            while (sig.charAt(cur.position) != '>') {
71069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int nameBegin = cur.position;
71169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                int nameEnd = cur.indexOf(sig, ':');
71269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ObjectType classBound = parseObjectType(sig, cur, true);
71369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ArrayList ifBound = new ArrayList();
71469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                while (sig.charAt(cur.position) == ':') {
71569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    cur.position++;
71669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    ObjectType t = parseObjectType(sig, cur, false);
71769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    ifBound.add(t);
71869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
71969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
72069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                TypeParameter p = new TypeParameter(sig, nameBegin, nameEnd,
72169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        classBound, (ObjectType[])ifBound.toArray(new ObjectType[ifBound.size()]));
72269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                typeParam.add(p);
72369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
72469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
72569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            cur.position++;
72669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
72769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
72869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return (TypeParameter[])typeParam.toArray(new TypeParameter[typeParam.size()]);
72969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
73069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
73169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static ObjectType parseObjectType(String sig, Cursor c, boolean dontThrow)
73269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
73369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
73469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i;
73569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int begin = c.position;
73669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        switch (sig.charAt(begin)) {
73769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'L' :
73869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return parseClassType2(sig, c, null);
73969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case 'T' :
74069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            i = c.indexOf(sig, ';');
74169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return new TypeVariable(sig, begin + 1, i);
74269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case '[' :
74369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return parseArray(sig, c);
74469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        default :
74569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (dontThrow)
74669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return null;
74769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
74869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw error(sig);
74969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
75069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
75169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
75269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static ClassType parseClassType(String sig, Cursor c)
75369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
75469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
75569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (sig.charAt(c.position) == 'L')
75669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return parseClassType2(sig, c, null);
75769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
75869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw error(sig);
75969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
76069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
76169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static ClassType parseClassType2(String sig, Cursor c, ClassType parent)
76269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
76369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
76469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int start = ++c.position;
76569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        char t;
76669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        do {
76769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            t = sig.charAt(c.position++);
76869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        } while (t != '$' && t != '<' && t != ';');
76969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int end = c.position - 1;
77069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        TypeArgument[] targs;
77169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (t == '<') {
77269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            targs = parseTypeArgs(sig, c);
77369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            t = sig.charAt(c.position++);
77469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
77569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
77669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            targs = null;
77769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
77869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ClassType thisClass = ClassType.make(sig, start, end, targs, parent);
77969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (t == '$') {
78069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            c.position--;
78169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return parseClassType2(sig, c, thisClass);
78269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
78369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
78469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return thisClass;
78569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
78669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
78769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static TypeArgument[] parseTypeArgs(String sig, Cursor c) throws BadBytecode {
78869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ArrayList args = new ArrayList();
78969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        char t;
79069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while ((t = sig.charAt(c.position++)) != '>') {
79169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            TypeArgument ta;
79269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (t == '*' )
79369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ta = new TypeArgument(null, '*');
79469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
79569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (t != '+' && t != '-') {
79669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    t = ' ';
79769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    c.position--;
79869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
79969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
80069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ta = new TypeArgument(parseObjectType(sig, c, false), t);
80169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
80269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
80369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            args.add(ta);
80469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
80569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
80669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return (TypeArgument[])args.toArray(new TypeArgument[args.size()]);
80769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
80869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
80969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static ObjectType parseArray(String sig, Cursor c) throws BadBytecode {
81069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int dim = 1;
81169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (sig.charAt(++c.position) == '[')
81269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            dim++;
81369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
81469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return new ArrayType(dim, parseType(sig, c));
81569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
81669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
81769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static Type parseType(String sig, Cursor c) throws BadBytecode {
81869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Type t = parseObjectType(sig, c, true);
81969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (t == null)
82069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            t = new BaseType(sig.charAt(c.position++));
82169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
82269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return t;
82369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
82469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
82569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static BadBytecode error(String sig) {
82669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return new BadBytecode("bad signature: " + sig);
82769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
82869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
829