mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			632 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			632 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Java
		
	
	
	
/* GenericSignatureParser.java
 | 
						|
   Copyright (C) 2005
 | 
						|
   Free Software Foundation
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
package gnu.java.lang.reflect;
 | 
						|
 | 
						|
import gnu.java.lang.CPStringBuilder;
 | 
						|
 | 
						|
import java.lang.reflect.Constructor;
 | 
						|
import java.lang.reflect.GenericArrayType;
 | 
						|
import java.lang.reflect.GenericDeclaration;
 | 
						|
import java.lang.reflect.GenericSignatureFormatError;
 | 
						|
import java.lang.reflect.MalformedParameterizedTypeException;
 | 
						|
import java.lang.reflect.Method;
 | 
						|
import java.lang.reflect.ParameterizedType;
 | 
						|
import java.lang.reflect.Type;
 | 
						|
import java.lang.reflect.TypeVariable;
 | 
						|
import java.lang.reflect.WildcardType;
 | 
						|
 | 
						|
import java.util.ArrayList;
 | 
						|
import java.util.Arrays;
 | 
						|
 | 
						|
final class TypeVariableImpl extends TypeImpl implements TypeVariable
 | 
						|
{
 | 
						|
    private GenericDeclaration decl;
 | 
						|
    private Type[] bounds;
 | 
						|
    private String name;
 | 
						|
 | 
						|
    TypeVariableImpl(GenericDeclaration decl, Type[] bounds, String name)
 | 
						|
    {
 | 
						|
        this.decl = decl;
 | 
						|
        this.bounds = bounds;
 | 
						|
        this.name = name;
 | 
						|
    }
 | 
						|
 | 
						|
    Type resolve()
 | 
						|
    {
 | 
						|
        return this;
 | 
						|
    }
 | 
						|
 | 
						|
    public Type[] getBounds()
 | 
						|
    {
 | 
						|
        resolve(bounds);
 | 
						|
        return (Type[]) bounds.clone();
 | 
						|
    }
 | 
						|
 | 
						|
    public GenericDeclaration getGenericDeclaration()
 | 
						|
    {
 | 
						|
        return decl;
 | 
						|
    }
 | 
						|
 | 
						|
    public String getName()
 | 
						|
    {
 | 
						|
        return name;
 | 
						|
    }
 | 
						|
 | 
						|
    public boolean equals(Object obj)
 | 
						|
    {
 | 
						|
        if (obj instanceof TypeVariableImpl)
 | 
						|
        {
 | 
						|
            TypeVariableImpl other = (TypeVariableImpl)obj;
 | 
						|
            return decl.equals(other.decl) && name.equals(other.name);
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    public int hashCode()
 | 
						|
    {
 | 
						|
        return 0x5f4d5156 ^ decl.hashCode() ^ name.hashCode();
 | 
						|
    }
 | 
						|
 | 
						|
    public String toString()
 | 
						|
    {
 | 
						|
        return name;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
final class ParameterizedTypeImpl extends TypeImpl implements ParameterizedType
 | 
						|
{
 | 
						|
    private String rawTypeName;
 | 
						|
    private ClassLoader loader;
 | 
						|
    private Class rawType;
 | 
						|
    private Type owner;
 | 
						|
    private Type[] typeArgs;
 | 
						|
 | 
						|
    ParameterizedTypeImpl(String rawTypeName, ClassLoader loader, Type owner,
 | 
						|
        Type[] typeArgs)
 | 
						|
    {
 | 
						|
        this.rawTypeName = rawTypeName;
 | 
						|
        this.loader = loader;
 | 
						|
        this.owner = owner;
 | 
						|
        this.typeArgs = typeArgs;
 | 
						|
    }
 | 
						|
 | 
						|
    Type resolve()
 | 
						|
    {
 | 
						|
        if (rawType == null)
 | 
						|
        {
 | 
						|
            try
 | 
						|
            {
 | 
						|
                rawType = Class.forName(rawTypeName, false, loader);
 | 
						|
            }
 | 
						|
            catch (ClassNotFoundException x)
 | 
						|
            {
 | 
						|
                throw new TypeNotPresentException(rawTypeName, x);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (typeArgs == null)
 | 
						|
        {
 | 
						|
            if (owner == null)
 | 
						|
            {
 | 
						|
                return rawType;
 | 
						|
            }
 | 
						|
            typeArgs = new Type[0];
 | 
						|
        }
 | 
						|
        resolve(typeArgs);
 | 
						|
        owner = resolve(owner);
 | 
						|
        return this;
 | 
						|
    }
 | 
						|
 | 
						|
    public Type[] getActualTypeArguments()
 | 
						|
    {
 | 
						|
      return (Type[]) typeArgs.clone();
 | 
						|
    }
 | 
						|
 | 
						|
    public Type getRawType()
 | 
						|
    {
 | 
						|
        return rawType;
 | 
						|
    }
 | 
						|
 | 
						|
    public Type getOwnerType()
 | 
						|
    {
 | 
						|
        return owner;
 | 
						|
    }
 | 
						|
 | 
						|
    public boolean equals(Object obj)
 | 
						|
    {
 | 
						|
        if (obj instanceof ParameterizedTypeImpl)
 | 
						|
        {
 | 
						|
            ParameterizedTypeImpl other = (ParameterizedTypeImpl)obj;
 | 
						|
            return rawType.equals(other.rawType)
 | 
						|
                && ((owner == null && other.owner == null)
 | 
						|
                    || owner.equals(other.owner))
 | 
						|
                && Arrays.deepEquals(typeArgs, other.typeArgs);
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    public int hashCode()
 | 
						|
    {
 | 
						|
        int h = 0x58158970 ^ rawType.hashCode();
 | 
						|
        if (owner != null)
 | 
						|
        {
 | 
						|
            h ^= Integer.reverse(owner.hashCode());
 | 
						|
        }
 | 
						|
        for (int i = 0; i < typeArgs.length; i++)
 | 
						|
        {
 | 
						|
            h ^= Integer.rotateLeft(typeArgs[i].hashCode(), i);
 | 
						|
        }
 | 
						|
        return h;
 | 
						|
    }
 | 
						|
 | 
						|
    public String toString()
 | 
						|
    {
 | 
						|
        CPStringBuilder sb = new CPStringBuilder();
 | 
						|
        if (owner != null)
 | 
						|
        {
 | 
						|
            sb.append(owner);
 | 
						|
            sb.append('.');
 | 
						|
            sb.append(rawType.getSimpleName());
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            sb.append(rawTypeName);
 | 
						|
        }
 | 
						|
        if (typeArgs.length > 0)
 | 
						|
        {
 | 
						|
            sb.append('<');
 | 
						|
            for (int i = 0; i < typeArgs.length; i++)
 | 
						|
            {
 | 
						|
                if (i > 0)
 | 
						|
                    sb.append(", ");
 | 
						|
                if (typeArgs[i] instanceof Class)
 | 
						|
                {
 | 
						|
                    sb.append(((Class)typeArgs[i]).getName());
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    sb.append(typeArgs[i]);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            sb.append('>');
 | 
						|
        }
 | 
						|
        return sb.toString();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
final class GenericArrayTypeImpl extends TypeImpl implements GenericArrayType
 | 
						|
{
 | 
						|
    private Type componentType;
 | 
						|
 | 
						|
    GenericArrayTypeImpl(Type componentType)
 | 
						|
    {
 | 
						|
        this.componentType = componentType;
 | 
						|
    }
 | 
						|
 | 
						|
    Type resolve()
 | 
						|
    {
 | 
						|
        componentType = resolve(componentType);
 | 
						|
        return this;
 | 
						|
    }
 | 
						|
 | 
						|
    public Type getGenericComponentType()
 | 
						|
    {
 | 
						|
        return componentType;
 | 
						|
    }
 | 
						|
 | 
						|
    public boolean equals(Object obj)
 | 
						|
    {
 | 
						|
        if (obj instanceof GenericArrayTypeImpl)
 | 
						|
        {
 | 
						|
            GenericArrayTypeImpl other = (GenericArrayTypeImpl)obj;
 | 
						|
            return componentType.equals(other.componentType);
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    public int hashCode()
 | 
						|
    {
 | 
						|
        return 0x4be37a7f ^ componentType.hashCode();
 | 
						|
    }
 | 
						|
 | 
						|
    public String toString()
 | 
						|
    {
 | 
						|
        return componentType + "[]";
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
final class UnresolvedTypeVariable extends TypeImpl implements Type
 | 
						|
{
 | 
						|
    private GenericDeclaration decl;
 | 
						|
    private String name;
 | 
						|
 | 
						|
    UnresolvedTypeVariable(GenericDeclaration decl, String name)
 | 
						|
    {
 | 
						|
        this.decl = decl;
 | 
						|
        this.name = name;
 | 
						|
    }
 | 
						|
 | 
						|
    Type resolve()
 | 
						|
    {
 | 
						|
        GenericDeclaration d = decl;
 | 
						|
        while (d != null)
 | 
						|
        {
 | 
						|
            for (TypeVariable t : d.getTypeParameters())
 | 
						|
            {
 | 
						|
                if (t.getName().equals(name))
 | 
						|
                {
 | 
						|
                    return t;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            d = getParent(d);
 | 
						|
        }
 | 
						|
        throw new MalformedParameterizedTypeException();
 | 
						|
    }
 | 
						|
 | 
						|
    private static GenericDeclaration getParent(GenericDeclaration d)
 | 
						|
    {
 | 
						|
        if (d instanceof Class)
 | 
						|
        {
 | 
						|
            Method m = ((Class)d).getEnclosingMethod();
 | 
						|
            if (m != null)
 | 
						|
            {
 | 
						|
                return m;
 | 
						|
            }
 | 
						|
            Constructor c = ((Class)d).getEnclosingConstructor();
 | 
						|
            if (c != null)
 | 
						|
            {
 | 
						|
                return c;
 | 
						|
            }
 | 
						|
            return ((Class)d).getEnclosingClass();
 | 
						|
        }
 | 
						|
        else if (d instanceof Method)
 | 
						|
        {
 | 
						|
            return ((Method)d).getDeclaringClass();
 | 
						|
        }
 | 
						|
        else if (d instanceof Constructor)
 | 
						|
        {
 | 
						|
            return ((Constructor)d).getDeclaringClass();
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            // TODO figure out what this represents
 | 
						|
            throw new Error();
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
final class WildcardTypeImpl extends TypeImpl implements WildcardType
 | 
						|
{
 | 
						|
    private Type lower;
 | 
						|
    private Type upper;
 | 
						|
 | 
						|
    WildcardTypeImpl(Type lower, Type upper)
 | 
						|
    {
 | 
						|
        this.lower = lower;
 | 
						|
        this.upper = upper;
 | 
						|
    }
 | 
						|
 | 
						|
    Type resolve()
 | 
						|
    {
 | 
						|
        upper = resolve(upper);
 | 
						|
        lower = resolve(lower);
 | 
						|
        return this;
 | 
						|
    }
 | 
						|
 | 
						|
    public Type[] getUpperBounds()
 | 
						|
    {
 | 
						|
        if (upper == null)
 | 
						|
        {
 | 
						|
            return new Type[0];
 | 
						|
        }
 | 
						|
        return new Type[] { upper };
 | 
						|
    }
 | 
						|
 | 
						|
    public Type[] getLowerBounds()
 | 
						|
    {
 | 
						|
        if (lower == null)
 | 
						|
        {
 | 
						|
            return new Type[0];
 | 
						|
        }
 | 
						|
        return new Type[] { lower };
 | 
						|
    }
 | 
						|
 | 
						|
    public boolean equals(Object obj)
 | 
						|
    {
 | 
						|
        if (obj instanceof WildcardTypeImpl)
 | 
						|
        {
 | 
						|
            WildcardTypeImpl other = (WildcardTypeImpl)obj;
 | 
						|
            return Arrays.deepEquals(getUpperBounds(), other.getUpperBounds())
 | 
						|
                && Arrays.deepEquals(getLowerBounds(), other.getLowerBounds());
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    public int hashCode()
 | 
						|
    {
 | 
						|
        int h = 0x75d074fd;
 | 
						|
        if (upper != null)
 | 
						|
        {
 | 
						|
            h ^= upper.hashCode();
 | 
						|
        }
 | 
						|
        if (lower != null)
 | 
						|
        {
 | 
						|
            h ^= lower.hashCode();
 | 
						|
        }
 | 
						|
        return h;
 | 
						|
    }
 | 
						|
 | 
						|
    public String toString()
 | 
						|
    {
 | 
						|
        if (lower != null)
 | 
						|
        {
 | 
						|
            return "? super " + lower;
 | 
						|
        }
 | 
						|
        if (upper == java.lang.Object.class)
 | 
						|
        {
 | 
						|
            return "?";
 | 
						|
        }
 | 
						|
        return "? extends " + upper;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
class GenericSignatureParser
 | 
						|
{
 | 
						|
    private ClassLoader loader;
 | 
						|
    private GenericDeclaration container;
 | 
						|
    private String signature;
 | 
						|
    private int pos;
 | 
						|
 | 
						|
    GenericSignatureParser(GenericDeclaration container, ClassLoader loader,
 | 
						|
        String signature)
 | 
						|
    {
 | 
						|
        this.container = container;
 | 
						|
        this.loader = loader;
 | 
						|
        this.signature = signature;
 | 
						|
    }
 | 
						|
 | 
						|
    TypeVariable[] readFormalTypeParameters()
 | 
						|
    {
 | 
						|
        consume('<');
 | 
						|
        ArrayList<TypeVariable> params = new ArrayList<TypeVariable>();
 | 
						|
        do
 | 
						|
        {
 | 
						|
            // TODO should we handle name clashes?
 | 
						|
            params.add(readFormalTypeParameter());
 | 
						|
        } while (peekChar() != '>');
 | 
						|
        consume('>');
 | 
						|
        TypeVariable[] list = new TypeVariable[params.size()];
 | 
						|
        params.toArray(list);
 | 
						|
        return list;
 | 
						|
    }
 | 
						|
 | 
						|
    private TypeVariable readFormalTypeParameter()
 | 
						|
    {
 | 
						|
        String identifier = readIdentifier();
 | 
						|
        consume(':');
 | 
						|
        ArrayList<Type> bounds = new ArrayList<Type>();
 | 
						|
        if (peekChar() != ':')
 | 
						|
        {
 | 
						|
            bounds.add(readFieldTypeSignature());
 | 
						|
        }
 | 
						|
        while (peekChar() == ':')
 | 
						|
        {
 | 
						|
            consume(':');
 | 
						|
            bounds.add(readFieldTypeSignature());
 | 
						|
        }
 | 
						|
        Type[] b = new Type[bounds.size()];
 | 
						|
        bounds.toArray(b);
 | 
						|
        return new TypeVariableImpl(container, b, identifier);
 | 
						|
    }
 | 
						|
 | 
						|
    Type readFieldTypeSignature()
 | 
						|
    {
 | 
						|
        switch (peekChar())
 | 
						|
        {
 | 
						|
            case 'L':
 | 
						|
                return readClassTypeSignature();
 | 
						|
            case '[':
 | 
						|
                return readArrayTypeSignature();
 | 
						|
            case 'T':
 | 
						|
                return readTypeVariableSignature();
 | 
						|
            default:
 | 
						|
                throw new GenericSignatureFormatError();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    Type readClassTypeSignature()
 | 
						|
    {
 | 
						|
        consume('L');
 | 
						|
        String className = "";
 | 
						|
        for (;;)
 | 
						|
        {
 | 
						|
            String part = readIdentifier();
 | 
						|
            if (peekChar() != '/')
 | 
						|
            {
 | 
						|
                className += part;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            consume('/');
 | 
						|
            className += part + ".";
 | 
						|
        }
 | 
						|
        Type[] typeArguments = null;
 | 
						|
        if (peekChar() == '<')
 | 
						|
        {
 | 
						|
            typeArguments = readTypeArguments();
 | 
						|
        }
 | 
						|
        Type type = new ParameterizedTypeImpl(className, loader, null,
 | 
						|
                                              typeArguments);
 | 
						|
        while (peekChar() == '.')
 | 
						|
        {
 | 
						|
            consume('.');
 | 
						|
            className += "$" + readIdentifier();
 | 
						|
            typeArguments = null;
 | 
						|
            if (peekChar() == '<')
 | 
						|
            {
 | 
						|
                typeArguments = readTypeArguments();
 | 
						|
            }
 | 
						|
            type = new ParameterizedTypeImpl(className, loader, type,
 | 
						|
                                             typeArguments);
 | 
						|
        }
 | 
						|
        consume(';');
 | 
						|
        return type;
 | 
						|
    }
 | 
						|
 | 
						|
    private Type[] readTypeArguments()
 | 
						|
    {
 | 
						|
        consume('<');
 | 
						|
        ArrayList<Type> list = new ArrayList<Type>();
 | 
						|
        do
 | 
						|
        {
 | 
						|
            list.add(readTypeArgument());
 | 
						|
        } while ((peekChar() != '>'));
 | 
						|
        consume('>');
 | 
						|
        Type[] arr = new Type[list.size()];
 | 
						|
        list.toArray(arr);
 | 
						|
        return arr;
 | 
						|
    }
 | 
						|
 | 
						|
    private Type readTypeArgument()
 | 
						|
    {
 | 
						|
        char c = peekChar();
 | 
						|
        if (c == '+')
 | 
						|
        {
 | 
						|
            consume('+');
 | 
						|
            return new WildcardTypeImpl(null, readFieldTypeSignature());
 | 
						|
        }
 | 
						|
        else if (c == '-')
 | 
						|
        {
 | 
						|
            consume('-');
 | 
						|
            return new WildcardTypeImpl(readFieldTypeSignature(),
 | 
						|
                java.lang.Object.class);
 | 
						|
        }
 | 
						|
        else if (c == '*')
 | 
						|
        {
 | 
						|
            consume('*');
 | 
						|
            return new WildcardTypeImpl(null, java.lang.Object.class);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            return readFieldTypeSignature();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    Type readArrayTypeSignature()
 | 
						|
    {
 | 
						|
        consume('[');
 | 
						|
        switch (peekChar())
 | 
						|
        {
 | 
						|
            case 'L':
 | 
						|
            case '[':
 | 
						|
            case 'T':
 | 
						|
                return new GenericArrayTypeImpl(readFieldTypeSignature());
 | 
						|
            case 'Z':
 | 
						|
                consume('Z');
 | 
						|
                return boolean[].class;
 | 
						|
            case 'B':
 | 
						|
                consume('B');
 | 
						|
                return byte[].class;
 | 
						|
            case 'S':
 | 
						|
                consume('S');
 | 
						|
                return short[].class;
 | 
						|
            case 'C':
 | 
						|
                consume('C');
 | 
						|
                return char[].class;
 | 
						|
            case 'I':
 | 
						|
                consume('I');
 | 
						|
                return int[].class;
 | 
						|
            case 'F':
 | 
						|
                consume('F');
 | 
						|
                return float[].class;
 | 
						|
            case 'J':
 | 
						|
                consume('J');
 | 
						|
                return long[].class;
 | 
						|
            case 'D':
 | 
						|
                consume('D');
 | 
						|
                return double[].class;
 | 
						|
            default:
 | 
						|
                throw new GenericSignatureFormatError();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    Type readTypeVariableSignature()
 | 
						|
    {
 | 
						|
        consume('T');
 | 
						|
        String identifier = readIdentifier();
 | 
						|
        consume(';');
 | 
						|
        return new UnresolvedTypeVariable(container, identifier);
 | 
						|
    }
 | 
						|
 | 
						|
    private String readIdentifier()
 | 
						|
    {
 | 
						|
        int start = pos;
 | 
						|
        char c;
 | 
						|
        do
 | 
						|
        {
 | 
						|
            readChar();
 | 
						|
            c = peekChar();
 | 
						|
        } while (";:./<>-+*".indexOf(c) == -1);
 | 
						|
        return signature.substring(start, pos);
 | 
						|
    }
 | 
						|
 | 
						|
    final char peekChar()
 | 
						|
    {
 | 
						|
        if (pos == signature.length())
 | 
						|
            return '\u0000';
 | 
						|
        else
 | 
						|
            return signature.charAt(pos);
 | 
						|
    }
 | 
						|
 | 
						|
    final char readChar()
 | 
						|
    {
 | 
						|
        return signature.charAt(pos++);
 | 
						|
    }
 | 
						|
 | 
						|
    final void consume(char c)
 | 
						|
    {
 | 
						|
        if (readChar() != c)
 | 
						|
            throw new GenericSignatureFormatError();
 | 
						|
    }
 | 
						|
 | 
						|
    final void end()
 | 
						|
    {
 | 
						|
        if (pos != signature.length())
 | 
						|
            throw new GenericSignatureFormatError();
 | 
						|
    }
 | 
						|
}
 |